From e7cd14c65584e1d8154b013b228e29959fa42fa1 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 25 Mar 2025 07:27:44 -0600 Subject: [PATCH 001/206] auto save format --- .../spark_interface.dart | 1131 ++++++++--------- 1 file changed, 549 insertions(+), 582 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 347bf9f2c..102d6a753 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -5,7 +5,8 @@ import 'dart:math'; import 'package:bitcoindart/bitcoindart.dart' as btc; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart' as spark +import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart' + as spark show Log; import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart'; import 'package:isar/isar.dart'; @@ -57,15 +58,10 @@ String _hashTag(String tag) { void initSparkLogging(Level level) { final levels = Level.values.where((e) => e >= level).map((e) => e.name); - spark.Log.levels - .addAll(LoggingLevel.values.where((e) => levels.contains(e.name))); - spark.Log.onLog = ( - level, - value, { - error, - stackTrace, - required time, - }) { + spark.Log.levels.addAll( + LoggingLevel.values.where((e) => levels.contains(e.name)), + ); + spark.Log.onLog = (level, value, {error, stackTrace, required time}) { Logging.instance.log( level.getLoggerLevel(), value, @@ -84,27 +80,24 @@ abstract class _SparkIsolate { static Future initialize() async { final level = Prefs.instance.logLevel; - _isolate = await Isolate.spawn( - (SendPort sendPort) { - initSparkLogging(level); // ensure logging is set up in isolate + _isolate = await Isolate.spawn((SendPort sendPort) { + initSparkLogging(level); // ensure logging is set up in isolate - final receivePort = ReceivePort(); + final receivePort = ReceivePort(); - sendPort.send(receivePort.sendPort); + sendPort.send(receivePort.sendPort); - receivePort.listen((message) async { - if (message is List && message.length == 3) { - final function = message[0] as Function; - final argument = message[1]; - final replyPort = message[2] as SendPort; + receivePort.listen((message) async { + if (message is List && message.length == 3) { + final function = message[0] as Function; + final argument = message[1]; + final replyPort = message[2] as SendPort; - final result = await function(argument); - replyPort.send(result); - } - }); - }, - _receivePort.sendPort, - ); + final result = await function(argument); + replyPort.send(result); + } + }); + }, _receivePort.sendPort); _sendPort = await _receivePort.first as SendPort; } @@ -139,8 +132,7 @@ mixin SparkInterface static bool validateSparkAddress({ required String address, required bool isTestNet, - }) => - LibSpark.validateAddress(address: address, isTestNet: isTestNet); + }) => LibSpark.validateAddress(address: address, isTestNet: isTestNet); Future hashTag(String tag) async { try { @@ -192,19 +184,20 @@ mixin SparkInterface @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.spark) - .or() - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.spark) + .or() + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } @@ -265,20 +258,22 @@ mixin SparkInterface ); } else { // fetch spendable spark coins - final coins = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .isUsedEqualTo(false) - .and() - .heightIsNotNull() - .and() - .not() - .valueIntStringEqualTo("0") - .findAll(); - - final available = - coins.map((e) => e.value).fold(BigInt.zero, (p, e) => p + e); + final coins = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .isUsedEqualTo(false) + .and() + .heightIsNotNull() + .and() + .not() + .valueIntStringEqualTo("0") + .findAll(); + + final available = coins + .map((e) => e.value) + .fold(BigInt.zero, (p, e) => p + e); if (amount.raw > available) { return Amount( @@ -288,16 +283,17 @@ mixin SparkInterface } // prepare coin data for ffi - final serializedCoins = coins - .map( - (e) => ( - serializedCoin: e.serializedCoinB64!, - serializedCoinContext: e.contextB64!, - groupId: e.groupId, - height: e.height!, - ), - ) - .toList(); + final serializedCoins = + coins + .map( + (e) => ( + serializedCoin: e.serializedCoinB64!, + serializedCoinContext: e.contextB64!, + groupId: e.groupId, + height: e.height!, + ), + ) + .toList(); final root = await getRootHDNode(); final String derivationPath; @@ -329,9 +325,7 @@ mixin SparkInterface } /// Spark to Spark/Transparent (spend) creation - Future prepareSendSpark({ - required TxData txData, - }) async { + Future prepareSendSpark({required TxData txData}) async { // There should be at least one output. if (!(txData.recipients?.isNotEmpty == true || txData.sparkRecipients?.isNotEmpty == true)) { @@ -343,14 +337,15 @@ mixin SparkInterface throw Exception("Spark shielded output limit exceeded."); } - final transparentSumOut = - (txData.recipients ?? []).map((e) => e.amount).fold( - Amount( - rawValue: BigInt.zero, - fractionDigits: cryptoCurrency.fractionDigits, - ), - (p, e) => p + e, - ); + final transparentSumOut = (txData.recipients ?? []) + .map((e) => e.amount) + .fold( + Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ), + (p, e) => p + e, + ); // See SPARK_VALUE_SPEND_LIMIT_PER_TRANSACTION at https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/include/spark.h#L17 // and COIN https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/bitcoin/amount.h#L17 @@ -365,29 +360,31 @@ mixin SparkInterface ); } - final sparkSumOut = - (txData.sparkRecipients ?? []).map((e) => e.amount).fold( - Amount( - rawValue: BigInt.zero, - fractionDigits: cryptoCurrency.fractionDigits, - ), - (p, e) => p + e, - ); + final sparkSumOut = (txData.sparkRecipients ?? []) + .map((e) => e.amount) + .fold( + Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ), + (p, e) => p + e, + ); final txAmount = transparentSumOut + sparkSumOut; // fetch spendable spark coins - final coins = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .isUsedEqualTo(false) - .and() - .heightIsNotNull() - .and() - .not() - .valueIntStringEqualTo("0") - .findAll(); + final coins = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .isUsedEqualTo(false) + .and() + .heightIsNotNull() + .and() + .not() + .valueIntStringEqualTo("0") + .findAll(); final available = info.cachedBalanceTertiary.spendable; @@ -398,16 +395,17 @@ mixin SparkInterface final bool isSendAll = available == txAmount; // prepare coin data for ffi - final serializedCoins = coins - .map( - (e) => ( - serializedCoin: e.serializedCoinB64!, - serializedCoinContext: e.contextB64!, - groupId: e.groupId, - height: e.height!, - ), - ) - .toList(); + final serializedCoins = + coins + .map( + (e) => ( + serializedCoin: e.serializedCoinB64!, + serializedCoinContext: e.contextB64!, + groupId: e.groupId, + height: e.height!, + ), + ) + .toList(); final currentId = await electrumXClient.getSparkLatestCoinId(); final List> setMaps = []; @@ -433,43 +431,36 @@ mixin SparkInterface "blockHash": info.blockHash, "setHash": info.setHash, "coinGroupID": i, - "coins": resultSet - .map( - (e) => [ - e.serialized, - e.txHash, - e.context, - ], - ) - .toList(), + "coins": + resultSet.map((e) => [e.serialized, e.txHash, e.context]).toList(), }; setData["coinGroupID"] = i; setMaps.add(setData); - idAndBlockHashes.add( - ( - groupId: i, - blockHash: setData["blockHash"] as String, - ), - ); + idAndBlockHashes.add(( + groupId: i, + blockHash: setData["blockHash"] as String, + )); } - final allAnonymitySets = setMaps - .map( - (e) => ( - setId: e["coinGroupID"] as int, - setHash: e["setHash"] as String, - set: (e["coins"] as List) - .map( - (e) => ( - serializedCoin: e[0] as String, - txHash: e[1] as String, - ), - ) - .toList(), - ), - ) - .toList(); + final allAnonymitySets = + setMaps + .map( + (e) => ( + setId: e["coinGroupID"] as int, + setHash: e["setHash"] as String, + set: + (e["coins"] as List) + .map( + (e) => ( + serializedCoin: e[0] as String, + txHash: e[1] as String, + ), + ) + .toList(), + ), + ) + .toList(); final root = await getRootHDNode(); final String derivationPath; @@ -480,31 +471,17 @@ mixin SparkInterface } final privateKey = root.derivePath(derivationPath).privateKey.data; - final txb = btc.TransactionBuilder( - network: _bitcoinDartNetwork, - ); + final txb = btc.TransactionBuilder(network: _bitcoinDartNetwork); txb.setLockTime(await chainHeight); txb.setVersion(3 | (9 << 16)); - List< - ({ - String address, - Amount amount, - bool isChange, - })>? recipientsWithFeeSubtracted; - List< - ({ - String address, - Amount amount, - String memo, - bool isChange, - })>? sparkRecipientsWithFeeSubtracted; - final recipientCount = (txData.recipients - ?.where( - (e) => e.amount.raw > BigInt.zero, - ) - .length ?? - 0); + List<({String address, Amount amount, bool isChange})>? + recipientsWithFeeSubtracted; + List<({String address, Amount amount, String memo, bool isChange})>? + sparkRecipientsWithFeeSubtracted; + final recipientCount = + (txData.recipients?.where((e) => e.amount.raw > BigInt.zero).length ?? + 0); final totalRecipientCount = recipientCount + (txData.sparkRecipients?.length ?? 0); final BigInt estimatedFee; @@ -530,18 +507,17 @@ mixin SparkInterface } for (int i = 0; i < (txData.sparkRecipients?.length ?? 0); i++) { - sparkRecipientsWithFeeSubtracted!.add( - ( - address: txData.sparkRecipients![i].address, - amount: Amount( - rawValue: txData.sparkRecipients![i].amount.raw - - (estimatedFee ~/ BigInt.from(totalRecipientCount)), - fractionDigits: cryptoCurrency.fractionDigits, - ), - memo: txData.sparkRecipients![i].memo, - isChange: sparkChangeAddress == txData.sparkRecipients![i].address, + sparkRecipientsWithFeeSubtracted!.add(( + address: txData.sparkRecipients![i].address, + amount: Amount( + rawValue: + txData.sparkRecipients![i].amount.raw - + (estimatedFee ~/ BigInt.from(totalRecipientCount)), + fractionDigits: cryptoCurrency.fractionDigits, ), - ); + memo: txData.sparkRecipients![i].memo, + isChange: sparkChangeAddress == txData.sparkRecipients![i].address, + )); } // temp tx data to show in gui while waiting for real data from server @@ -552,17 +528,16 @@ mixin SparkInterface if (txData.recipients![i].amount.raw == BigInt.zero) { continue; } - recipientsWithFeeSubtracted!.add( - ( - address: txData.recipients![i].address, - amount: Amount( - rawValue: txData.recipients![i].amount.raw - - (estimatedFee ~/ BigInt.from(totalRecipientCount)), - fractionDigits: cryptoCurrency.fractionDigits, - ), - isChange: txData.recipients![i].isChange, + recipientsWithFeeSubtracted!.add(( + address: txData.recipients![i].address, + amount: Amount( + rawValue: + txData.recipients![i].amount.raw - + (estimatedFee ~/ BigInt.from(totalRecipientCount)), + fractionDigits: cryptoCurrency.fractionDigits, ), - ); + isChange: txData.recipients![i].isChange, + )); final scriptPubKey = btc.Address.addressToOutputScript( txData.recipients![i].address, @@ -577,10 +552,9 @@ mixin SparkInterface OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: scriptPubKey.toHex, valueStringSats: recipientsWithFeeSubtracted[i].amount.raw.toString(), - addresses: [ - recipientsWithFeeSubtracted[i].address.toString(), - ], - walletOwns: (await mainDB.isar.addresses + addresses: [recipientsWithFeeSubtracted[i].address.toString()], + walletOwns: + (await mainDB.isar.addresses .where() .walletIdEqualTo(walletId) .filter() @@ -598,10 +572,9 @@ mixin SparkInterface OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: Uint8List.fromList([OP_SPARKSMINT]).toHex, valueStringSats: recip.amount.raw.toString(), - addresses: [ - recip.address.toString(), - ], - walletOwns: (await mainDB.isar.addresses + addresses: [recip.address.toString()], + walletOwns: + (await mainDB.isar.addresses .where() .walletIdEqualTo(walletId) .filter() @@ -624,42 +597,42 @@ mixin SparkInterface ); extractedTx.setPayload(Uint8List(0)); - final spend = await computeWithLibSparkLogging( - _createSparkSend, - ( - privateKeyHex: privateKey.toHex, - index: kDefaultSparkIndex, - recipients: txData.recipients - ?.map( - (e) => ( - address: e.address, - amount: e.amount.raw.toInt(), - subtractFeeFromAmount: isSendAll, - ), - ) - .toList() ?? - [], - privateRecipients: txData.sparkRecipients - ?.map( - (e) => ( - sparkAddress: e.address, - amount: e.amount.raw.toInt(), - subtractFeeFromAmount: isSendAll, - memo: e.memo, - ), - ) - .toList() ?? - [], - serializedCoins: serializedCoins, - allAnonymitySets: allAnonymitySets, - idAndBlockHashes: idAndBlockHashes - .map( - (e) => (setId: e.groupId, blockHash: base64Decode(e.blockHash)), - ) - .toList(), - txHash: extractedTx.getHash(), - ), - ); + final spend = await computeWithLibSparkLogging(_createSparkSend, ( + privateKeyHex: privateKey.toHex, + index: kDefaultSparkIndex, + recipients: + txData.recipients + ?.map( + (e) => ( + address: e.address, + amount: e.amount.raw.toInt(), + subtractFeeFromAmount: isSendAll, + ), + ) + .toList() ?? + [], + privateRecipients: + txData.sparkRecipients + ?.map( + (e) => ( + sparkAddress: e.address, + amount: e.amount.raw.toInt(), + subtractFeeFromAmount: isSendAll, + memo: e.memo, + ), + ) + .toList() ?? + [], + serializedCoins: serializedCoins, + allAnonymitySets: allAnonymitySets, + idAndBlockHashes: + idAndBlockHashes + .map( + (e) => (setId: e.groupId, blockHash: base64Decode(e.blockHash)), + ) + .toList(), + txHash: extractedTx.getHash(), + )); for (final outputScript in spend.outputScripts) { extractedTx.addOutput(outputScript, 0); @@ -687,10 +660,11 @@ mixin SparkInterface sequence: 0xffffffff, outpoint: null, addresses: [], - valueStringSats: tempOutputs - .map((e) => e.value) - .fold(fee.raw, (p, e) => p + e) - .toString(), + valueStringSats: + tempOutputs + .map((e) => e.value) + .fold(fee.raw, (p, e) => p + e) + .toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -709,12 +683,10 @@ mixin SparkInterface usedCoin.height == e.height && usedCoin.groupId == e.groupId && base64Decode(e.serializedCoinB64!).toHex.startsWith( - base64Decode(usedCoin.serializedCoin).toHex, - ), + base64Decode(usedCoin.serializedCoin).toHex, + ), ) - .copyWith( - isUsed: true, - ), + .copyWith(isUsed: true), ); } catch (_) { throw Exception( @@ -735,15 +707,12 @@ mixin SparkInterface timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(tempInputs), outputs: List.unmodifiable(tempOutputs), - type: tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e) - ? TransactionType.sentToSelf - : TransactionType.outgoing, + type: + tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e) + ? TransactionType.sentToSelf + : TransactionType.outgoing, subType: TransactionSubType.sparkSpend, - otherData: jsonEncode( - { - "overrideFee": fee.toJsonString(), - }, - ), + otherData: jsonEncode({"overrideFee": fee.toJsonString()}), height: null, version: 3, ), @@ -752,9 +721,7 @@ mixin SparkInterface } // this may not be needed for either mints or spends or both - Future confirmSendSpark({ - required TxData txData, - }) async { + Future confirmSendSpark({required TxData txData}) async { try { Logging.instance.d("confirmSend txData: $txData"); @@ -821,11 +788,7 @@ mixin SparkInterface for (final data in sparkDataToCheck) { for (int i = 0; i < data.coins.length; i++) { - rawCoins.add([ - data.coins[i], - data.txid, - data.serialContext.first, - ]); + rawCoins.add([data.coins[i], data.txid, data.serialContext.first]); } checkedTxids.add(data.txid); @@ -836,16 +799,13 @@ mixin SparkInterface // if there is new data we try and identify the coins if (rawCoins.isNotEmpty) { // run identify off main isolate - final myCoins = await computeWithLibSparkLogging( - _identifyCoins, - ( - anonymitySetCoins: rawCoins, - groupId: groupId, - privateKeyHexSet: privateKeyHexSet, - walletId: walletId, - isTestNet: cryptoCurrency.network.isTestNet, - ), - ); + final myCoins = await computeWithLibSparkLogging(_identifyCoins, ( + anonymitySetCoins: rawCoins, + groupId: groupId, + privateKeyHexSet: privateKeyHexSet, + walletId: walletId, + isTestNet: cryptoCurrency.network.isTestNet, + )); // add checked txids after identification _mempoolTxidsChecked.addAll(checkedTxids); @@ -872,21 +832,13 @@ mixin SparkInterface // returns next percent double _triggerEventHelper(double current, double increment) { refreshingPercent = current; - GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - current, - walletId, - ), - ); + GlobalEventBus.instance.fire(RefreshPercentChangedEvent(current, walletId)); return current + increment; } // Linearly make calls so there is less chance of timing out or otherwise breaking Future refreshSparkData( - ( - double startingPercent, - double endingPercent, - )? refreshProgressRange, + (double startingPercent, double endingPercent)? refreshProgressRange, ) async { final start = DateTime.now(); try { @@ -898,9 +850,9 @@ mixin SparkInterface for (int id = 1; id < latestGroupId; id++) { final setExists = await FiroCacheCoordinator.checkSetInfoForGroupIdExists( - id, - cryptoCurrency.network, - ); + id, + cryptoCurrency.network, + ); if (!setExists) { groupIds.add(id); } @@ -908,7 +860,8 @@ mixin SparkInterface } groupIds.add(latestGroupId); - final steps = groupIds.length + + final steps = + groupIds.length + 1 // get used tags step + 1 // check updated cache step @@ -919,9 +872,10 @@ mixin SparkInterface + 1; // update balance - final percentIncrement = refreshProgressRange == null - ? null - : (refreshProgressRange.$2 - refreshProgressRange.$1) / steps; + final percentIncrement = + refreshProgressRange == null + ? null + : (refreshProgressRange.$2 - refreshProgressRange.$1) / steps; double currentPercent = refreshProgressRange?.$1 ?? 0; // fetch and update process for each set groupId as required @@ -963,8 +917,8 @@ mixin SparkInterface // after that block. final groupIdBlockHashMap = info.otherData[WalletInfoKeys.firoSparkCacheSetBlockHashCache] - as Map? ?? - {}; + as Map? ?? + {}; // iterate through the cache, fetching spark coin data that hasn't been // processed by this wallet yet @@ -977,19 +931,14 @@ mixin SparkInterface ); final anonymitySetResult = await FiroCacheCoordinator.getSetCoinsForGroupId( - i, - afterBlockHash: lastCheckedHash, - network: cryptoCurrency.network, - ); - final coinsRaw = anonymitySetResult - .map( - (e) => [ - e.serialized, - e.txHash, - e.context, - ], - ) - .toList(); + i, + afterBlockHash: lastCheckedHash, + network: cryptoCurrency.network, + ); + final coinsRaw = + anonymitySetResult + .map((e) => [e.serialized, e.txHash, e.context]) + .toList(); if (coinsRaw.isNotEmpty) { rawCoinsBySetId[i] = coinsRaw; @@ -1005,33 +954,36 @@ mixin SparkInterface // get address(es) to get the private key hex strings required for // identifying spark coins - final sparkAddresses = await mainDB.isar.addresses - .where() - .walletIdEqualTo(walletId) - .filter() - .typeEqualTo(AddressType.spark) - .findAll(); + final sparkAddresses = + await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.spark) + .findAll(); final root = await getRootHDNode(); - final Set privateKeyHexSet = sparkAddresses - .map( - (e) => - root.derivePath(e.derivationPath!.value).privateKey.data.toHex, - ) - .toSet(); + final Set privateKeyHexSet = + sparkAddresses + .map( + (e) => + root + .derivePath(e.derivationPath!.value) + .privateKey + .data + .toHex, + ) + .toSet(); // try to identify any coins in the unchecked set data final List newlyIdCoins = []; for (final groupId in rawCoinsBySetId.keys) { - final myCoins = await computeWithLibSparkLogging( - _identifyCoins, - ( - anonymitySetCoins: rawCoinsBySetId[groupId]!, - groupId: groupId, - privateKeyHexSet: privateKeyHexSet, - walletId: walletId, - isTestNet: cryptoCurrency.network.isTestNet, - ), - ); + final myCoins = await computeWithLibSparkLogging(_identifyCoins, ( + anonymitySetCoins: rawCoinsBySetId[groupId]!, + groupId: groupId, + privateKeyHexSet: privateKeyHexSet, + walletId: walletId, + isTestNet: cryptoCurrency.network.isTestNet, + )); newlyIdCoins.addAll(myCoins); } // if any were found, add to database @@ -1066,14 +1018,15 @@ mixin SparkInterface } // get unused and or unconfirmed coins from db - final coinsToCheck = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .heightIsNull() - .or() - .isUsedEqualTo(false) - .findAll(); + final coinsToCheck = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .heightIsNull() + .or() + .isUsedEqualTo(false) + .findAll(); Set? spentCoinTags; // only fetch tags from db if we need them to compare against any items @@ -1104,9 +1057,10 @@ mixin SparkInterface checked = coin; } } else { - checked = spentCoinTags!.contains(coin.lTagHash) - ? coin.copyWith(isUsed: true) - : coin; + checked = + spentCoinTags!.contains(coin.lTagHash) + ? coin.copyWith(isUsed: true) + : coin; } checkedCoins.add(checked); @@ -1126,12 +1080,13 @@ mixin SparkInterface final currentHeight = await chainHeight; // get all unused coins to update wallet spark balance - final unusedCoins = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .isUsedEqualTo(false) - .findAll(); + final unusedCoins = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .isUsedEqualTo(false) + .findAll(); final total = Amount( rawValue: unusedCoins @@ -1165,8 +1120,11 @@ mixin SparkInterface isar: mainDB.isar, ); } catch (e, s) { - Logging.instance - .e("$runtimeType $walletId ${info.name}: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType $walletId ${info.name}: ", + error: e, + stackTrace: s, + ); rethrow; } finally { Logging.instance.d( @@ -1177,13 +1135,14 @@ mixin SparkInterface } Future> getSparkSpendTransactionIds() async { - final tags = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .isUsedEqualTo(true) - .lTagHashProperty() - .findAll(); + final tags = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .isUsedEqualTo(true) + .lTagHashProperty() + .findAll(); final pairs = await FiroCacheCoordinator.getUsedCoinTxidsFor( tags: tags, @@ -1195,9 +1154,7 @@ mixin SparkInterface /// Should only be called within the standard wallet [recover] function due to /// mutex locking. Otherwise behaviour MAY be undefined. - Future recoverSparkWallet({ - required int latestSparkCoinId, - }) async { + Future recoverSparkWallet({required int latestSparkCoinId}) async { // generate spark addresses if non existing if (await getCurrentReceivingSparkAddress() == null) { final address = await generateNextSparkAddress(); @@ -1207,8 +1164,11 @@ mixin SparkInterface try { await refreshSparkData(null); } catch (e, s) { - Logging.instance - .e("$runtimeType $walletId ${info.name}: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType $walletId ${info.name}: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -1229,8 +1189,9 @@ mixin SparkInterface // addresses when confirming the transactions later as well assert(outputs.length == 1); - BigInt valueToMint = - outputs.map((e) => e.value).reduce((value, element) => value + element); + BigInt valueToMint = outputs + .map((e) => e.value) + .reduce((value, element) => value + element); if (valueToMint <= BigInt.zero) { throw Exception("Cannot mint amount=$valueToMint"); @@ -1251,9 +1212,10 @@ mixin SparkInterface // setup some vars int nChangePosInOut = -1; final int nChangePosRequest = nChangePosInOut; - List outputs_ = outputs - .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) - .toList(); // deep copy + List outputs_ = + outputs + .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) + .toList(); // deep copy final feesObject = await fees; final currentHeight = await chainHeight; final random = Random.secure(); @@ -1262,9 +1224,10 @@ mixin SparkInterface valueAndUTXOs.shuffle(random); while (valueAndUTXOs.isNotEmpty) { - final lockTime = random.nextInt(10) == 0 - ? max(0, currentHeight - random.nextInt(100)) - : currentHeight; + final lockTime = + random.nextInt(10) == 0 + ? max(0, currentHeight - random.nextInt(100)) + : currentHeight; const txVersion = 1; final List vin = []; final List<(dynamic, int, String?)> vout = []; @@ -1311,9 +1274,10 @@ mixin SparkInterface setCoins.clear(); // deep copy - final remainingOutputs = outputs_ - .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) - .toList(); + final remainingOutputs = + outputs_ + .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) + .toList(); final List singleTxOutputs = []; if (autoMintAll) { @@ -1328,8 +1292,10 @@ mixin SparkInterface BigInt remainingMintValue = BigInt.parse(mintedValue.toString()); while (remainingMintValue > BigInt.zero) { - final singleMintValue = - _min(remainingMintValue, remainingOutputs.first.value); + final singleMintValue = _min( + remainingMintValue, + remainingOutputs.first.value, + ); singleTxOutputs.add( MutableSparkRecipient( remainingOutputs.first.address, @@ -1372,15 +1338,16 @@ mixin SparkInterface // Generate dummy mint coins to save time final dummyRecipients = LibSpark.createSparkMintRecipients( - outputs: singleTxOutputs - .map( - (e) => ( - sparkAddress: e.address, - value: e.value.toInt(), - memo: "", - ), - ) - .toList(), + outputs: + singleTxOutputs + .map( + (e) => ( + sparkAddress: e.address, + value: e.value.toInt(), + memo: "", + ), + ) + .toList(), serialContext: Uint8List(0), generate: false, ); @@ -1393,13 +1360,11 @@ mixin SparkInterface if (recipient.amount < cryptoCurrency.dustLimit.raw.toInt()) { throw Exception("Output amount too small"); } - vout.add( - ( - recipient.scriptPubKey, - recipient.amount, - singleTxOutputs[i].address, - ), - ); + vout.add(( + recipient.scriptPubKey, + recipient.amount, + singleTxOutputs[i].address, + )); } // Choose coins to use @@ -1429,10 +1394,11 @@ mixin SparkInterface } final changeAddress = await getCurrentChangeAddress(); - vout.insert( - nChangePosInOut, - (changeAddress!.value, nChange.toInt(), null), - ); + vout.insert(nChangePosInOut, ( + changeAddress!.value, + nChange.toInt(), + null, + )); } } @@ -1450,42 +1416,40 @@ mixin SparkInterface switch (sd.derivePathType) { case DerivePathType.bip44: - data = btc - .P2PKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; + data = + btc + .P2PKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip49: - final p2wpkh = btc - .P2WPKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; - data = btc - .P2SH( - data: btc.PaymentData(redeem: p2wpkh), - network: _bitcoinDartNetwork, - ) - .data; + final p2wpkh = + btc + .P2WPKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; + data = + btc + .P2SH( + data: btc.PaymentData(redeem: p2wpkh), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip84: - data = btc - .P2WPKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; + data = + btc + .P2WPKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip86: @@ -1530,10 +1494,7 @@ mixin SparkInterface } final nFeeNeeded = BigInt.from( - estimateTxFee( - vSize: nBytes, - feeRatePerKB: feesObject.medium, - ), + estimateTxFee(vSize: nBytes, feeRatePerKB: feesObject.medium), ); // One day we'll do this properly if (nFeeRet >= nFeeNeeded) { @@ -1548,25 +1509,19 @@ mixin SparkInterface // Generate real mint coins final serialContext = LibSpark.serializeMintContext( - inputs: setCoins - .map( - (e) => ( - e.utxo.txid, - e.utxo.vout, - ), - ) - .toList(), + inputs: setCoins.map((e) => (e.utxo.txid, e.utxo.vout)).toList(), ); final recipients = LibSpark.createSparkMintRecipients( - outputs: singleTxOutputs - .map( - (e) => ( - sparkAddress: e.address, - memo: e.memo, - value: e.value.toInt(), - ), - ) - .toList(), + outputs: + singleTxOutputs + .map( + (e) => ( + sparkAddress: e.address, + memo: e.memo, + value: e.value.toInt(), + ), + ) + .toList(), serialContext: serialContext, generate: true, ); @@ -1591,9 +1546,10 @@ mixin SparkInterface } // deep copy - outputs_ = remainingOutputs - .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) - .toList(); + outputs_ = + remainingOutputs + .map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) + .toList(); break; // Done, enough fee included. } @@ -1621,42 +1577,40 @@ mixin SparkInterface switch (input.derivePathType) { case DerivePathType.bip44: - data = btc - .P2PKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; + data = + btc + .P2PKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip49: - final p2wpkh = btc - .P2WPKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; - data = btc - .P2SH( - data: btc.PaymentData(redeem: p2wpkh), - network: _bitcoinDartNetwork, - ) - .data; + final p2wpkh = + btc + .P2WPKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; + data = + btc + .P2SH( + data: btc.PaymentData(redeem: p2wpkh), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip84: - data = btc - .P2WPKH( - data: btc.PaymentData( - pubkey: pubKey, - ), - network: _bitcoinDartNetwork, - ) - .data; + data = + btc + .P2WPKH( + data: btc.PaymentData(pubkey: pubKey), + network: _bitcoinDartNetwork, + ) + .data; break; case DerivePathType.bip86: @@ -1707,7 +1661,8 @@ mixin SparkInterface addresses: [ if (addressOrScript is String) addressOrScript.toString(), ], - walletOwns: (await mainDB.isar.addresses + walletOwns: + (await mainDB.isar.addresses .where() .walletIdEqualTo(walletId) .filter() @@ -1752,21 +1707,24 @@ mixin SparkInterface assert(outputs.length == 1); final data = TxData( - sparkRecipients: vout - .where((e) => e.$1 is Uint8List) // ignore change - .map( - (e) => ( - address: outputs.first - .address, // for display purposes on confirm tx screen. See todos above - memo: "", - amount: Amount( - rawValue: BigInt.from(e.$2), - fractionDigits: cryptoCurrency.fractionDigits, - ), - isChange: false, // ok? - ), - ) - .toList(), + sparkRecipients: + vout + .where((e) => e.$1 is Uint8List) // ignore change + .map( + (e) => ( + address: + outputs + .first + .address, // for display purposes on confirm tx screen. See todos above + memo: "", + amount: Amount( + rawValue: BigInt.from(e.$2), + fractionDigits: cryptoCurrency.fractionDigits, + ), + isChange: false, // ok? + ), + ) + .toList(), vSize: builtTx.virtualSize(), txid: builtTx.getId(), raw: builtTx.toHex(), @@ -1853,23 +1811,25 @@ mixin SparkInterface const subtractFeeFromAmount = true; // must be true for mint all final currentHeight = await chainHeight; - final spendableUtxos = await mainDB.isar.utxos - .where() - .walletIdEqualTo(walletId) - .filter() - .isBlockedEqualTo(false) - .and() - .group((q) => q.usedEqualTo(false).or().usedIsNull()) - .and() - .valueGreaterThan(0) - .findAll(); + final spendableUtxos = + await mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .isBlockedEqualTo(false) + .and() + .group((q) => q.usedEqualTo(false).or().usedIsNull()) + .and() + .valueGreaterThan(0) + .findAll(); spendableUtxos.removeWhere( - (e) => !e.isConfirmed( - currentHeight, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - ), + (e) => + !e.isConfirmed( + currentHeight, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + ), ); if (spendableUtxos.isEmpty) { @@ -1910,15 +1870,12 @@ mixin SparkInterface if (txData.sparkRecipients?.isNotEmpty != true) { throw Exception("Missing spark recipients."); } - final recipients = txData.sparkRecipients! - .map( - (e) => MutableSparkRecipient( - e.address, - e.amount.raw, - e.memo, - ), - ) - .toList(); + final recipients = + txData.sparkRecipients! + .map( + (e) => MutableSparkRecipient(e.address, e.amount.raw, e.memo), + ) + .toList(); final total = recipients .map((e) => e.value) @@ -1933,11 +1890,12 @@ mixin SparkInterface final utxos = txData.utxos; final bool coinControl = utxos != null; - final utxosTotal = coinControl - ? utxos - .map((e) => e.value) - .fold(BigInt.zero, (p, e) => p + BigInt.from(e)) - : null; + final utxosTotal = + coinControl + ? utxos + .map((e) => e.value) + .fold(BigInt.zero, (p, e) => p + BigInt.from(e)) + : null; if (coinControl && utxosTotal! < total) { throw Exception("Insufficient selected UTXOs!"); @@ -1947,7 +1905,8 @@ mixin SparkInterface final currentHeight = await chainHeight; - final availableOutputs = utxos?.toList() ?? + final availableOutputs = + utxos?.toList() ?? await mainDB.isar.utxos .where() .walletIdEqualTo(walletId) @@ -1961,17 +1920,18 @@ mixin SparkInterface final canCPFP = this is CpfpInterface && coinControl; - final spendableUtxos = availableOutputs - .where( - (e) => - canCPFP || - e.isConfirmed( - currentHeight, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - ), - ) - .toList(); + final spendableUtxos = + availableOutputs + .where( + (e) => + canCPFP || + e.isConfirmed( + currentHeight, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + ), + ) + .toList(); if (spendableUtxos.isEmpty) { throw Exception("No available UTXOs found to anonymize"); @@ -2031,63 +1991,70 @@ mixin SparkInterface // ====================== Private ============================================ btc.NetworkType get _bitcoinDartNetwork => btc.NetworkType( - messagePrefix: cryptoCurrency.networkParams.messagePrefix, - bech32: cryptoCurrency.networkParams.bech32Hrp, - bip32: btc.Bip32Type( - public: cryptoCurrency.networkParams.pubHDPrefix, - private: cryptoCurrency.networkParams.privHDPrefix, - ), - pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix, - scriptHash: cryptoCurrency.networkParams.p2shPrefix, - wif: cryptoCurrency.networkParams.wifPrefix, - ); + messagePrefix: cryptoCurrency.networkParams.messagePrefix, + bech32: cryptoCurrency.networkParams.bech32Hrp, + bip32: btc.Bip32Type( + public: cryptoCurrency.networkParams.pubHDPrefix, + private: cryptoCurrency.networkParams.privHDPrefix, + ), + pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix, + scriptHash: cryptoCurrency.networkParams.p2shPrefix, + wif: cryptoCurrency.networkParams.wifPrefix, + ); } /// Top level function which should be called wrapped in [compute] Future< - ({ - Uint8List serializedSpendPayload, - List outputScripts, - int fee, - List< - ({ - int groupId, - int height, - String serializedCoin, - String serializedCoinContext - })> usedCoins, - })> _createSparkSend( + ({ + Uint8List serializedSpendPayload, + List outputScripts, + int fee, + List< + ({ + int groupId, + int height, + String serializedCoin, + String serializedCoinContext, + }) + > + usedCoins, + }) +> +_createSparkSend( ({ String privateKeyHex, int index, List<({String address, int amount, bool subtractFeeFromAmount})> recipients, List< - ({ - String sparkAddress, - int amount, - bool subtractFeeFromAmount, - String memo - })> privateRecipients, + ({ + String sparkAddress, + int amount, + bool subtractFeeFromAmount, + String memo, + }) + > + privateRecipients, List< - ({ - String serializedCoin, - String serializedCoinContext, - int groupId, - int height, - })> serializedCoins, + ({ + String serializedCoin, + String serializedCoinContext, + int groupId, + int height, + }) + > + serializedCoins, List< - ({ - int setId, - String setHash, - List<({String serializedCoin, String txHash})> set - })> allAnonymitySets, - List< - ({ - int setId, - Uint8List blockHash, - })> idAndBlockHashes, + ({ + int setId, + String setHash, + List<({String serializedCoin, String txHash})> set, + }) + > + allAnonymitySets, + List<({int setId, Uint8List blockHash})> idAndBlockHashes, Uint8List txHash, - }) args, + }) + args, ) async { final spend = LibSpark.createSparkSendTransaction( privateKeyHex: args.privateKeyHex, @@ -2111,7 +2078,8 @@ Future> _identifyCoins( Set privateKeyHexSet, String walletId, bool isTestNet, - }) args, + }) + args, ) async { final List myCoins = []; @@ -2200,12 +2168,13 @@ class MutableSparkRecipient { } } -typedef SerializedCoinData = ({ - int groupId, - int height, - String serializedCoin, - String serializedCoinContext -}); +typedef SerializedCoinData = + ({ + int groupId, + int height, + String serializedCoin, + String serializedCoinContext, + }); Future _asyncSparkFeesWrapper({ required String privateKeyHex, @@ -2215,17 +2184,14 @@ Future _asyncSparkFeesWrapper({ required List serializedCoins, required int privateRecipientsCount, }) async { - return await computeWithLibSparkLogging( - _estSparkFeeComputeFunc, - ( - privateKeyHex: privateKeyHex, - index: index, - sendAmount: sendAmount, - subtractFeeFromAmount: subtractFeeFromAmount, - serializedCoins: serializedCoins, - privateRecipientsCount: privateRecipientsCount, - ), - ); + return await computeWithLibSparkLogging(_estSparkFeeComputeFunc, ( + privateKeyHex: privateKeyHex, + index: index, + sendAmount: sendAmount, + subtractFeeFromAmount: subtractFeeFromAmount, + serializedCoins: serializedCoins, + privateRecipientsCount: privateRecipientsCount, + )); } int _estSparkFeeComputeFunc( @@ -2236,7 +2202,8 @@ int _estSparkFeeComputeFunc( bool subtractFeeFromAmount, List serializedCoins, int privateRecipientsCount, - }) args, + }) + args, ) { final est = LibSpark.estimateSparkFee( privateKeyHex: args.privateKeyHex, From bee49df2a9c1ce124a25960136256b8d3a33f7d5 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 25 Mar 2025 07:53:47 -0600 Subject: [PATCH 002/206] linter rule change due to dart 3.7 --- analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index ea46ed3ca..db030aa14 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -92,7 +92,7 @@ linter: constant_identifier_names: false prefer_final_locals: true prefer_final_in_for_each: true - require_trailing_commas: true +# require_trailing_commas: true // causes issues with dart 3.7 # avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule From 8eb91507d2f8b5ced8382cd28b087a88a138b228 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 25 Mar 2025 15:05:54 -0600 Subject: [PATCH 003/206] WIP spark names --- lib/electrumx_rpc/electrumx_client.dart | 355 ++-- .../spark_names/buy_spark_name_view.dart | 423 ++++ .../confirm_spark_name_transaction_view.dart | 975 +++++++++ .../spark_names/spark_names_home_view.dart | 231 +++ .../buy_spark_name_option_widget.dart | 352 ++++ .../manage_spark_names_option_widget.dart | 98 + .../sub_widgets/owned_spark_name_card.dart | 225 +++ .../sub_widgets/spark_name_details.dart | 565 ++++++ lib/pages/wallet_view/wallet_view.dart | 629 +++--- .../sub_widgets/desktop_wallet_features.dart | 10 + .../more_features/more_features_dialog.dart | 9 + lib/route_generator.dart | 1754 +++++++---------- lib/wallets/crypto_currency/coins/firo.dart | 17 +- lib/wallets/models/tx_data.dart | 46 +- .../spark_interface.dart | 95 + 15 files changed, 4238 insertions(+), 1546 deletions(-) create mode 100644 lib/pages/spark_names/buy_spark_name_view.dart create mode 100644 lib/pages/spark_names/confirm_spark_name_transaction_view.dart create mode 100644 lib/pages/spark_names/spark_names_home_view.dart create mode 100644 lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart create mode 100644 lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart create mode 100644 lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart create mode 100644 lib/pages/spark_names/sub_widgets/spark_name_details.dart diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index 2691adf5a..9df7ed791 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -93,11 +93,8 @@ class ElectrumXClient { // StreamChannel? get electrumAdapterChannel => _electrumAdapterChannel; StreamChannel? _electrumAdapterChannel; - ElectrumClient? getElectrumAdapter() => - ClientManager.sharedInstance.getClient( - cryptoCurrency: cryptoCurrency, - netType: netType, - ); + ElectrumClient? getElectrumAdapter() => ClientManager.sharedInstance + .getClient(cryptoCurrency: cryptoCurrency, netType: netType); late Prefs _prefs; late TorService _torService; @@ -109,12 +106,10 @@ class ElectrumXClient { // add finalizer to cancel stream subscription when all references to an // instance of ElectrumX becomes inaccessible - static final Finalizer _finalizer = Finalizer( - (p0) { - p0._torPreferenceListener?.cancel(); - p0._torStatusListener?.cancel(); - }, - ); + static final Finalizer _finalizer = Finalizer((p0) { + p0._torPreferenceListener?.cancel(); + p0._torStatusListener?.cancel(); + }); StreamSubscription? _torPreferenceListener; StreamSubscription? _torStatusListener; @@ -129,8 +124,9 @@ class ElectrumXClient { required this.netType, required List failovers, required this.cryptoCurrency, - this.connectionTimeoutForSpecialCaseJsonRPCClients = - const Duration(seconds: 60), + this.connectionTimeoutForSpecialCaseJsonRPCClients = const Duration( + seconds: 60, + ), TorService? torService, EventBus? globalEventBusForTesting, }) { @@ -144,46 +140,45 @@ class ElectrumXClient { final bus = globalEventBusForTesting ?? GlobalEventBus.instance; // Listen for tor status changes. - _torStatusListener = bus.on().listen( - (event) async { - switch (event.newStatus) { - case TorConnectionStatus.connecting: - await _torConnectingLock.acquire(); - _requireMutex = true; - break; - - case TorConnectionStatus.connected: - case TorConnectionStatus.disconnected: - if (_torConnectingLock.isLocked) { - _torConnectingLock.release(); - } - _requireMutex = false; - break; - } - }, - ); + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + await _torConnectingLock.acquire(); + _requireMutex = true; + break; + + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + _requireMutex = false; + break; + } + }); // Listen for tor preference changes. - _torPreferenceListener = bus.on().listen( - (event) async { - // not sure if we need to do anything specific here - // switch (event.status) { - // case TorStatus.enabled: - // case TorStatus.disabled: - // } - - // setting to null should force the creation of a new json rpc client - // on the next request sent through this electrumx instance - _electrumAdapterChannel = null; - await (await ClientManager.sharedInstance - .remove(cryptoCurrency: cryptoCurrency)) - .$1 - ?.close(); - - // Also close any chain height services that are currently open. - // await ChainHeightServiceManager.dispose(); - }, - ); + _torPreferenceListener = bus.on().listen(( + event, + ) async { + // not sure if we need to do anything specific here + // switch (event.status) { + // case TorStatus.enabled: + // case TorStatus.disabled: + // } + + // setting to null should force the creation of a new json rpc client + // on the next request sent through this electrumx instance + _electrumAdapterChannel = null; + await (await ClientManager.sharedInstance.remove( + cryptoCurrency: cryptoCurrency, + )).$1?.close(); + + // Also close any chain height services that are currently open. + // await ChainHeightServiceManager.dispose(); + }); } factory ElectrumXClient.from({ @@ -252,14 +247,16 @@ class ElectrumXClient { if (netType == TorPlainNetworkOption.clear) { _electrumAdapterChannel = null; - await ClientManager.sharedInstance - .remove(cryptoCurrency: cryptoCurrency); + await ClientManager.sharedInstance.remove( + cryptoCurrency: cryptoCurrency, + ); } } else { if (netType == TorPlainNetworkOption.tor) { _electrumAdapterChannel = null; - await ClientManager.sharedInstance - .remove(cryptoCurrency: cryptoCurrency); + await ClientManager.sharedInstance.remove( + cryptoCurrency: cryptoCurrency, + ); } } @@ -338,24 +335,22 @@ class ElectrumXClient { } if (_requireMutex) { - await _torConnectingLock - .protect(() async => await checkElectrumAdapter()); + await _torConnectingLock.protect( + () async => await checkElectrumAdapter(), + ); } else { await checkElectrumAdapter(); } try { - final response = await getElectrumAdapter()!.request( - command, - args, - ); + final response = await getElectrumAdapter()!.request(command, args); if (response is Map && response.keys.contains("error") && response["error"] != null) { - if (response["error"] - .toString() - .contains("No such mempool or blockchain transaction")) { + if (response["error"].toString().contains( + "No such mempool or blockchain transaction", + )) { throw NoSuchTransactionException( "No such mempool or blockchain transaction", args.first.toString(), @@ -399,11 +394,7 @@ class ElectrumXClient { } } catch (e, s) { final errorMessage = e.toString(); - Logging.instance.w( - "$host $e", - error: e, - stackTrace: s, - ); + Logging.instance.w("$host $e", error: e, stackTrace: s); if (errorMessage.contains("JSON-RPC error")) { currentFailoverIndex = _failovers.length; } @@ -437,8 +428,9 @@ class ElectrumXClient { } if (_requireMutex) { - await _torConnectingLock - .protect(() async => await checkElectrumAdapter()); + await _torConnectingLock.protect( + () async => await checkElectrumAdapter(), + ); } else { await checkElectrumAdapter(); } @@ -531,18 +523,19 @@ class ElectrumXClient { // electrum_adapter returns the result of the request, request() has been // updated to return a bool on a server.ping command as a special case. return await request( - requestID: requestID, - command: 'server.ping', - requestTimeout: const Duration(seconds: 30), - retries: retryCount, - ).timeout( - const Duration(seconds: 30), - onTimeout: () { - Logging.instance.d( - "ElectrumxClient.ping timed out with retryCount=$retryCount, host=$_host", - ); - }, - ) as bool; + requestID: requestID, + command: 'server.ping', + requestTimeout: const Duration(seconds: 30), + retries: retryCount, + ).timeout( + const Duration(seconds: 30), + onTimeout: () { + Logging.instance.d( + "ElectrumxClient.ping timed out with retryCount=$retryCount, host=$_host", + ); + }, + ) + as bool; } catch (e) { rethrow; } @@ -609,9 +602,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: 'blockchain.transaction.broadcast', - args: [ - rawTx, - ], + args: [rawTx], ); return response as String; } catch (e) { @@ -636,9 +627,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: 'blockchain.scripthash.get_balance', - args: [ - scripthash, - ], + args: [scripthash], ); return Map.from(response as Map); } catch (e) { @@ -673,9 +662,7 @@ class ElectrumXClient { requestID: requestID, command: 'blockchain.scripthash.get_history', requestTimeout: const Duration(minutes: 5), - args: [ - scripthash, - ], + args: [scripthash], ); result = response; retryCount--; @@ -731,9 +718,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: 'blockchain.scripthash.listunspent', - args: [ - scripthash, - ], + args: [scripthash], ); return List>.from(response as List); } catch (e) { @@ -826,14 +811,10 @@ class ElectrumXClient { bool verbose = true, String? requestID, }) async { - Logging.instance.d( - "attempting to fetch blockchain.transaction.get...", - ); + Logging.instance.d("attempting to fetch blockchain.transaction.get..."); await checkElectrumAdapter(); final dynamic response = await getElectrumAdapter()!.getTransaction(txHash); - Logging.instance.d( - "Fetching blockchain.transaction.get finished", - ); + Logging.instance.d("Fetching blockchain.transaction.get finished"); if (!verbose) { return {"rawtx": response as String}; @@ -861,16 +842,12 @@ class ElectrumXClient { String blockhash = "", String? requestID, }) async { - Logging.instance.d( - "attempting to fetch lelantus.getanonymityset...", - ); + Logging.instance.d("attempting to fetch lelantus.getanonymityset..."); await checkElectrumAdapter(); - final Map response = - await (getElectrumAdapter() as FiroElectrumClient) - .getLelantusAnonymitySet(groupId: groupId, blockHash: blockhash); - Logging.instance.d( - "Fetching lelantus.getanonymityset finished", - ); + final Map response = await (getElectrumAdapter() + as FiroElectrumClient) + .getLelantusAnonymitySet(groupId: groupId, blockHash: blockhash); + Logging.instance.d("Fetching lelantus.getanonymityset finished"); return response; } @@ -882,15 +859,11 @@ class ElectrumXClient { dynamic mints, String? requestID, }) async { - Logging.instance.d( - "attempting to fetch lelantus.getmintmetadata...", - ); + Logging.instance.d("attempting to fetch lelantus.getmintmetadata..."); await checkElectrumAdapter(); final dynamic response = await (getElectrumAdapter() as FiroElectrumClient) .getLelantusMintData(mints: mints); - Logging.instance.d( - "Fetching lelantus.getmintmetadata finished", - ); + Logging.instance.d("Fetching lelantus.getmintmetadata finished"); return response; } @@ -900,9 +873,7 @@ class ElectrumXClient { String? requestID, required int startNumber, }) async { - Logging.instance.d( - "attempting to fetch lelantus.getusedcoinserials...", - ); + Logging.instance.d("attempting to fetch lelantus.getusedcoinserials..."); await checkElectrumAdapter(); int retryCount = 3; @@ -912,9 +883,7 @@ class ElectrumXClient { response = await (getElectrumAdapter() as FiroElectrumClient) .getLelantusUsedCoinSerials(startNumber: startNumber); // TODO add 2 minute timeout. - Logging.instance.d( - "Fetching lelantus.getusedcoinserials finished", - ); + Logging.instance.d("Fetching lelantus.getusedcoinserials finished"); retryCount--; } @@ -926,15 +895,11 @@ class ElectrumXClient { /// /// ex: 1 Future getLelantusLatestCoinId({String? requestID}) async { - Logging.instance.d( - "attempting to fetch lelantus.getlatestcoinid...", - ); + Logging.instance.d("attempting to fetch lelantus.getlatestcoinid..."); await checkElectrumAdapter(); final int response = await (getElectrumAdapter() as FiroElectrumClient).getLatestCoinId(); - Logging.instance.d( - "Fetching lelantus.getlatestcoinid finished", - ); + Logging.instance.d("Fetching lelantus.getlatestcoinid finished"); return response; } @@ -961,12 +926,12 @@ class ElectrumXClient { try { final start = DateTime.now(); await checkElectrumAdapter(); - final Map response = - await (getElectrumAdapter() as FiroElectrumClient) - .getSparkAnonymitySet( - coinGroupId: coinGroupId, - startBlockHash: startBlockHash, - ); + final Map response = await (getElectrumAdapter() + as FiroElectrumClient) + .getSparkAnonymitySet( + coinGroupId: coinGroupId, + startBlockHash: startBlockHash, + ); Logging.instance.d( "Finished ElectrumXClient.getSparkAnonymitySet(coinGroupId" "=$coinGroupId, startBlockHash=$startBlockHash). " @@ -1053,34 +1018,23 @@ class ElectrumXClient { /// Returns the latest Spark set id /// /// ex: 1 - Future getSparkLatestCoinId({ - String? requestID, - }) async { + Future getSparkLatestCoinId({String? requestID}) async { try { - Logging.instance.d( - "attempting to fetch spark.getsparklatestcoinid...", - ); + Logging.instance.d("attempting to fetch spark.getsparklatestcoinid..."); await checkElectrumAdapter(); - final int response = await (getElectrumAdapter() as FiroElectrumClient) - .getSparkLatestCoinId(); - Logging.instance.d( - "Fetching spark.getsparklatestcoinid finished", - ); + final int response = + await (getElectrumAdapter() as FiroElectrumClient) + .getSparkLatestCoinId(); + Logging.instance.d("Fetching spark.getsparklatestcoinid finished"); return response; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, - ); + Logging.instance.e(e, error: e, stackTrace: s); rethrow; } } /// Returns the txids of the current transactions found in the mempool - Future> getMempoolTxids({ - String? requestID, - }) async { + Future> getMempoolTxids({String? requestID}) async { try { final start = DateTime.now(); final response = await request( @@ -1088,9 +1042,10 @@ class ElectrumXClient { command: "spark.getmempoolsparktxids", ); - final txids = List.from(response as List) - .map((e) => e.toHexReversedFromBase64) - .toSet(); + final txids = + List.from( + response as List, + ).map((e) => e.toHexReversedFromBase64).toSet(); Logging.instance.d( "Finished ElectrumXClient.getMempoolTxids(). " @@ -1099,11 +1054,7 @@ class ElectrumXClient { return txids; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, - ); + Logging.instance.e(e, error: e, stackTrace: s); rethrow; } } @@ -1119,9 +1070,7 @@ class ElectrumXClient { requestID: requestID, command: "spark.getmempoolsparktxs", args: [ - { - "txids": txids, - }, + {"txids": txids}, ], ); @@ -1131,8 +1080,9 @@ class ElectrumXClient { result.add( SparkMempoolData( txid: entry.key, - serialContext: - List.from(entry.value["serial_context"] as List), + serialContext: List.from( + entry.value["serial_context"] as List, + ), // the space after lTags is required lol lTags: List.from(entry.value["lTags "] as List), coins: List.from(entry.value["coins"] as List), @@ -1163,9 +1113,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: "spark.getusedcoinstagstxhashes", - args: [ - "$startNumber", - ], + args: ["$startNumber"], ); final map = Map.from(response as Map); @@ -1179,14 +1127,34 @@ class ElectrumXClient { return tags; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, + Logging.instance.e(e, error: e, stackTrace: s); + rethrow; + } + } + + Future> getSparkNames({String? requestID}) async { + try { + final start = DateTime.now(); + await checkElectrumAdapter(); + const command = "spark.getsparknames"; + Logging.instance.d( + "[${getElectrumAdapter()?.host}] => attempting to fetch $command...", ); + + final response = await request(requestID: requestID, command: command); + + Logging.instance.d( + "Finished ElectrumXClient.getSparkNames(). " + "coins.length: ${(response as List).length}" + "Duration=${DateTime.now().difference(start)}", + ); + + return response.cast(); + } catch (e) { rethrow; } } + // ======== New Paginated Endpoints ========================================== Future getSparkAnonymitySetMeta({ @@ -1203,9 +1171,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: command, - args: [ - "$coinGroupId", - ], + args: ["$coinGroupId"], ); final map = Map.from(response as Map); @@ -1227,11 +1193,7 @@ class ElectrumXClient { return result; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, - ); + Logging.instance.e(e, error: e, stackTrace: s); rethrow; } } @@ -1250,12 +1212,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: command, - args: [ - "$coinGroupId", - latestBlock, - "$startIndex", - "$endIndex", - ], + args: ["$coinGroupId", latestBlock, "$startIndex", "$endIndex"], ); final map = Map.from(response as Map); @@ -1275,11 +1232,7 @@ class ElectrumXClient { return result; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, - ); + Logging.instance.e(e, error: e, stackTrace: s); rethrow; } } @@ -1296,10 +1249,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: "blockchain.checkifmncollateral", - args: [ - txid, - index.toString(), - ], + args: [txid, index.toString()], ); Logging.instance.d( @@ -1310,11 +1260,7 @@ class ElectrumXClient { return response as bool; } catch (e, s) { - Logging.instance.e( - e, - error: e, - stackTrace: s, - ); + Logging.instance.e(e, error: e, stackTrace: s); rethrow; } } @@ -1344,9 +1290,7 @@ class ElectrumXClient { final response = await request( requestID: requestID, command: 'blockchain.estimatefee', - args: [ - blocks, - ], + args: [blocks], ); try { if (response == null || @@ -1371,7 +1315,8 @@ class ElectrumXClient { } return Decimal.parse(response.toString()); } catch (e, s) { - final String msg = "Error parsing fee rate. Response: $response" + final String msg = + "Error parsing fee rate. Response: $response" "\nResult: $response\nError: $e\nStack trace: $s"; Logging.instance.e(msg, error: e, stackTrace: s); throw Exception(msg); diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart new file mode 100644 index 000000000..0371ec485 --- /dev/null +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -0,0 +1,423 @@ +import 'dart:async'; + +import 'package:decimal/decimal.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../../providers/providers.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/logger.dart'; +import '../../../utilities/util.dart'; +import '../../../wallets/models/tx_data.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/stack_dialog.dart'; +import '../../themes/stack_colors.dart'; +import '../../utilities/amount/amount_formatter.dart'; +import '../../utilities/assets.dart'; +import '../../utilities/constants.dart'; +import '../../utilities/show_loading.dart'; +import '../../utilities/text_styles.dart'; +import '../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; +import '../../widgets/background.dart'; +import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/dialogs/s_dialog.dart'; +import '../../widgets/rounded_white_container.dart'; +import 'confirm_spark_name_transaction_view.dart'; + +class BuySparkNameView extends ConsumerStatefulWidget { + const BuySparkNameView({ + super.key, + required this.walletId, + required this.name, + }); + + final String walletId; + final String name; + + static const routeName = "/buySparkNameView"; + + @override + ConsumerState createState() => _BuySparkNameViewState(); +} + +class _BuySparkNameViewState extends ConsumerState { + final additionalInfoController = TextEditingController(); + + int _years = 1; + + Future _preRegFuture() async { + final wallet = + ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; + final myAddress = await wallet.getCurrentReceivingSparkAddress(); + if (myAddress == null) { + throw Exception("No spark address found"); + } + + final txData = await wallet.prepareSparkNameTransaction( + name: widget.name, + address: myAddress.value, + years: _years, + additionalInfo: additionalInfoController.text, + ); + return txData; + } + + bool _preRegLock = false; + Future _prepareNameTx() async { + if (_preRegLock) return; + _preRegLock = true; + try { + final txData = + (await showLoading( + whileFuture: _preRegFuture(), + context: context, + message: "Preparing transaction...", + onException: (e) { + throw e; + }, + ))!; + + if (mounted) { + if (Util.isDesktop) { + await showDialog( + context: context, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: ConfirmSparkNameTransactionView( + txData: txData, + walletId: widget.walletId, + ), + ), + ), + ); + } else { + await Navigator.of(context).pushNamed( + ConfirmSparkNameTransactionView.routeName, + arguments: (txData, widget.walletId), + ); + } + } + } catch (e, s) { + Logging.instance.e("_prepareNameTx failed", error: e, stackTrace: s); + + if (mounted) { + String err = e.toString(); + if (err.startsWith("Exception: ")) { + err = err.replaceFirst("Exception: ", ""); + } + + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Error", + message: err, + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), + ); + } + } finally { + _preRegLock = false; + } + } + + @override + void dispose() { + additionalInfoController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final coin = ref.watch(pWalletCoin(widget.walletId)); + return ConditionalParent( + condition: !Util.isDesktop, + builder: (child) { + return Background( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + leading: const AppBarBackButton(), + titleSpacing: 0, + title: Text( + "Buy name", + style: STextStyles.navBarTitle(context), + overflow: TextOverflow.ellipsis, + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (ctx, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, + ), + ), + ), + ); + }, + ), + ), + ), + ); + }, + child: Column( + crossAxisAlignment: + Util.isDesktop + ? CrossAxisAlignment.start + : CrossAxisAlignment.stretch, + children: [ + if (!Util.isDesktop) + Text( + "Buy name", + style: + Util.isDesktop + ? STextStyles.desktopH3(context) + : STextStyles.pageTitleH2(context), + ), + SizedBox(height: Util.isDesktop ? 24 : 16), + // Row( + // mainAxisAlignment: + // Util.isDesktop + // ? MainAxisAlignment.center + // : MainAxisAlignment.start, + // children: [ + // Text( + // "Name registration will take approximately 2 to 4 hours.", + // style: + // Util.isDesktop + // ? STextStyles.w500_14(context).copyWith( + // color: + // Theme.of( + // context, + // ).extension()!.textDark3, + // ) + // : STextStyles.w500_12(context).copyWith( + // color: + // Theme.of( + // context, + // ).extension()!.textDark3, + // ), + // ), + // ], + // ), + // SizedBox(height: Util.isDesktop ? 24 : 16), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Name", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ), + Text( + widget.name, + style: + Util.isDesktop + ? STextStyles.w500_14(context) + : STextStyles.w500_12(context), + ), + ], + ), + ), + SizedBox(height: Util.isDesktop ? 16 : 8), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + Amount.fromDecimal( + Decimal.fromInt( + kStandardSparkNamesFee[widget.name.length] * _years, + ), + fractionDigits: coin.fractionDigits, + ), + ), + style: + Util.isDesktop + ? STextStyles.w500_14(context) + : STextStyles.w500_12(context), + ), + ], + ), + ), + SizedBox(height: Util.isDesktop ? 16 : 8), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Register for", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ), + SizedBox( + width: Util.isDesktop ? 180 : 140, + child: DropdownButtonHideUnderline( + child: DropdownButton2( + value: _years, + items: [ + ...List.generate(10, (i) => i + 1).map( + (e) => DropdownMenuItem( + value: e, + child: Text( + "$e years", + style: STextStyles.w500_14(context), + ), + ), + ), + ], + onChanged: (value) { + if (value is int) { + setState(() { + _years = value; + }); + } + }, + isExpanded: true, + buttonStyleData: ButtonStyleData( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + iconStyleData: IconStyleData( + icon: Padding( + padding: const EdgeInsets.only(right: 10), + child: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + ), + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + maxHeight: 250, + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + ), + ), + ), + ), + ], + ), + ), + SizedBox(height: Util.isDesktop ? 16 : 8), + RoundedWhiteContainer( + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + controller: additionalInfoController, + textAlignVertical: TextAlignVertical.center, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.all(16), + hintStyle: STextStyles.fieldLabel(context), + hintText: "Additional info", + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + ), + ), + ), + ), + + SizedBox(height: Util.isDesktop ? 24 : 16), + if (!Util.isDesktop) const Spacer(), + PrimaryButton( + label: "Buy", + // width: Util.isDesktop ? 160 : double.infinity, + buttonHeight: Util.isDesktop ? ButtonHeight.l : null, + onPressed: _prepareNameTx, + ), + SizedBox(height: Util.isDesktop ? 32 : 16), + ], + ), + ); + } +} diff --git a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart new file mode 100644 index 000000000..6efd2a8fd --- /dev/null +++ b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart @@ -0,0 +1,975 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'dart:async'; +import 'dart:io'; + +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../models/isar/models/transaction_note.dart'; +import '../../notifications/show_flush_bar.dart'; +import '../../pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; +import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; +import '../../providers/db/main_db_provider.dart'; +import '../../providers/providers.dart'; +import '../../route_generator.dart'; +import '../../themes/stack_colors.dart'; +import '../../themes/theme_providers.dart'; +import '../../utilities/amount/amount.dart'; +import '../../utilities/amount/amount_formatter.dart'; +import '../../utilities/constants.dart'; +import '../../utilities/logger.dart'; +import '../../utilities/text_styles.dart'; +import '../../utilities/util.dart'; +import '../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../wallets/models/tx_data.dart'; +import '../../widgets/background.dart'; +import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/desktop/desktop_dialog.dart'; +import '../../widgets/desktop/desktop_dialog_close_button.dart'; +import '../../widgets/desktop/primary_button.dart'; +import '../../widgets/icon_widgets/x_icon.dart'; +import '../../widgets/rounded_container.dart'; +import '../../widgets/rounded_white_container.dart'; +import '../../widgets/stack_dialog.dart'; +import '../../widgets/stack_text_field.dart'; +import '../../widgets/textfield_icon_button.dart'; +import '../pinpad_views/lock_screen_view.dart'; +import '../send_view/sub_widgets/sending_transaction_dialog.dart'; + +class ConfirmSparkNameTransactionView extends ConsumerStatefulWidget { + const ConfirmSparkNameTransactionView({ + super.key, + required this.txData, + required this.walletId, + }); + + static const String routeName = "/confirmSparkNameTransactionView"; + + final TxData txData; + final String walletId; + + @override + ConsumerState createState() => + _ConfirmSparkNameTransactionViewState(); +} + +class _ConfirmSparkNameTransactionViewState + extends ConsumerState { + late final String walletId; + late final bool isDesktop; + + late final FocusNode _noteFocusNode; + late final TextEditingController noteController; + + Future _attemptSend() async { + final wallet = ref.read(pWallets).getWallet(walletId); + final coin = wallet.info.coin; + + final sendProgressController = ProgressAndSuccessController(); + + unawaited( + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: false, + builder: (context) { + return SendingTransactionDialog( + coin: coin, + controller: sendProgressController, + ); + }, + ), + ); + + final time = Future.delayed(const Duration(milliseconds: 2500)); + + final List txids = []; + Future txDataFuture; + + final note = noteController.text; + + try { + txDataFuture = wallet.confirmSend(txData: widget.txData); + + // await futures in parallel + final futureResults = await Future.wait([txDataFuture, time]); + + final txData = (futureResults.first as TxData); + + sendProgressController.triggerSuccess?.call(); + + // await futures in parallel + await Future.wait([ + // wait for animation + Future.delayed(const Duration(seconds: 5)), + ]); + + txids.add(txData.txid!); + ref.refresh(desktopUseUTXOs); + + // save note + for (final txid in txids) { + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), + ); + } + + unawaited(wallet.refresh()); + + if (mounted) { + // pop sending dialog + Navigator.of(context, rootNavigator: Util.isDesktop).pop(); + // pop confirm send view + Navigator.of(context, rootNavigator: Util.isDesktop).pop(); + // pop buy popup + Navigator.of(context, rootNavigator: Util.isDesktop).pop(); + } + } catch (e, s) { + const niceError = "Broadcast name transaction failed"; + + Logging.instance.e(niceError, error: e, stackTrace: s); + + if (mounted) { + // pop sending dialog + Navigator.of(context, rootNavigator: Util.isDesktop).pop(); + + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + if (isDesktop) { + return DesktopDialog( + maxWidth: 450, + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(niceError, style: STextStyles.desktopH3(context)), + const SizedBox(height: 24), + Flexible( + child: SingleChildScrollView( + child: SelectableText( + e.toString(), + style: STextStyles.smallMed14(context), + ), + ), + ), + const SizedBox(height: 56), + Row( + children: [ + const Spacer(), + Expanded( + child: PrimaryButton( + buttonHeight: ButtonHeight.l, + label: "Ok", + onPressed: Navigator.of(context).pop, + ), + ), + ], + ), + ], + ), + ), + ); + } else { + return StackDialog( + title: niceError, + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ); + } + }, + ); + } + } + } + + @override + void initState() { + isDesktop = Util.isDesktop; + walletId = widget.walletId; + _noteFocusNode = FocusNode(); + noteController = TextEditingController(); + noteController.text = widget.txData.note ?? ""; + + super.initState(); + } + + @override + void dispose() { + noteController.dispose(); + + _noteFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final coin = ref.watch(pWalletCoin(walletId)); + + final unit = coin.ticker; + + final fee = widget.txData.fee; + final amountWithoutChange = widget.txData.amountWithoutChange!; + + return ConditionalParent( + condition: !isDesktop, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Confirm transaction", + style: STextStyles.navBarTitle(context), + ), + ), + body: LayoutBuilder( + builder: (builderContext, 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: child, + ), + ), + ), + ), + ); + }, + ), + ), + ), + child: ConditionalParent( + condition: isDesktop, + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + AppBarBackButton( + size: 40, + iconSize: 24, + onPressed: + () => + Navigator.of(context, rootNavigator: true).pop(), + ), + Text( + "Confirm transaction", + style: STextStyles.desktopH3(context), + ), + ], + ), + Flexible(child: SingleChildScrollView(child: child)), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, + children: [ + if (!isDesktop) + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Confirm Name transaction", + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text("Name", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), + Text( + widget.txData.sparkNameInfo!.name, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Additional info", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 4), + Text( + widget.txData.sparkNameInfo!.additionalInfo, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Recipient", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 4), + Text( + widget.txData.recipients!.first.address, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Registration fee", + style: STextStyles.smallMed12(context), + ), + SelectableText( + ref + .watch(pAmountFormatter(coin)) + .format(amountWithoutChange), + style: STextStyles.itemSubtitle12(context), + textAlign: TextAlign.right, + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction fee", + style: STextStyles.smallMed12(context), + ), + SelectableText( + ref.watch(pAmountFormatter(coin)).format(fee!), + style: STextStyles.itemSubtitle12(context), + textAlign: TextAlign.right, + ), + ], + ), + ), + if (widget.txData.fee != null && widget.txData.vSize != null) + const SizedBox(height: 12), + if (widget.txData.fee != null && widget.txData.vSize != null) + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "sats/vByte", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 4), + SelectableText( + "~${fee.raw.toInt() ~/ widget.txData.vSize!}", + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + if (widget.txData.note != null && + widget.txData.note!.isNotEmpty) + const SizedBox(height: 12), + if (widget.txData.note != null && + widget.txData.note!.isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text("Note", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), + SelectableText( + widget.txData.note!, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + ], + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only( + top: 16, + left: 32, + right: 32, + bottom: 50, + ), + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + borderColor: + Theme.of(context).extension()!.background, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.background, + borderRadius: BorderRadius.only( + topLeft: Radius.circular( + Constants.size.circularBorderRadius, + ), + topRight: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 22, + ), + child: Row( + children: [ + SvgPicture.file( + File( + ref.watch( + themeProvider.select( + (value) => value.assets.send, + ), + ), + ), + width: 32, + height: 32, + ), + const SizedBox(width: 16), + Text( + "Send $unit Name transaction", + style: STextStyles.desktopTextMedium(context), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Name", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 2), + SelectableText( + widget.txData.sparkNameInfo!.name, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + ), + ], + ), + ), + Container( + height: 1, + color: + Theme.of( + context, + ).extension()!.background, + ), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Additional info", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 2), + SelectableText( + widget.txData.sparkNameInfo!.additionalInfo, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + ), + ], + ), + ), + ], + ), + ), + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only(left: 32, right: 32), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SelectableText( + "Note (optional)", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + textAlign: TextAlign.left, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 5, + autocorrect: isDesktop ? false : true, + enableSuggestions: isDesktop ? false : true, + controller: noteController, + focusNode: _noteFocusNode, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type something...", + _noteFocusNode, + context, + desktopMed: true, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ), + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState( + () => noteController.text = "", + ); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 16, left: 32), + child: Text( + "Registration fee", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), + child: RoundedContainer( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: Builder( + builder: (context) { + final externalCalls = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, + ), + ); + String fiatAmount = "N/A"; + + if (externalCalls) { + final price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getPrice(coin) + .item1; + if (price > Decimal.zero) { + fiatAmount = (amountWithoutChange.decimal * price) + .toAmount(fractionDigits: 2) + .fiatString( + locale: + ref + .read( + localeServiceChangeNotifierProvider, + ) + .locale, + ); + } + } + + return Row( + children: [ + SelectableText( + ref + .watch(pAmountFormatter(coin)) + .format(amountWithoutChange), + style: STextStyles.itemSubtitle(context), + ), + if (externalCalls) + Text( + " | ", + style: STextStyles.itemSubtitle(context), + ), + if (externalCalls) + SelectableText( + "~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.itemSubtitle(context), + ), + ], + ); + }, + ), + ), + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 16, left: 32), + child: Text( + "Recipient", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), + child: RoundedContainer( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: SelectableText( + widget.txData.recipients!.first.address, + style: STextStyles.itemSubtitle(context), + ), + ), + ), + + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 16, left: 32), + child: Text( + "Transaction fee", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + if (isDesktop) + Padding( + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), + child: RoundedContainer( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: SelectableText( + ref.watch(pAmountFormatter(coin)).format(fee!), + style: STextStyles.itemSubtitle(context), + ), + ), + ), + if (isDesktop && + widget.txData.fee != null && + widget.txData.vSize != null) + Padding( + padding: const EdgeInsets.only(top: 16, left: 32), + child: Text( + "sats/vByte", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + if (isDesktop && + widget.txData.fee != null && + widget.txData.vSize != null) + Padding( + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), + child: RoundedContainer( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: SelectableText( + "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", + style: STextStyles.itemSubtitle(context), + ), + ), + ), + if (!isDesktop) const Spacer(), + SizedBox(height: isDesktop ? 23 : 12), + Padding( + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), + child: RoundedContainer( + padding: + isDesktop + ? const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ) + : const EdgeInsets.all(12), + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + isDesktop ? "Total amount to send" : "Total amount", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.titleBold12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + ), + SelectableText( + ref + .watch(pAmountFormatter(coin)) + .format(amountWithoutChange + fee!), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + textAlign: TextAlign.right, + ), + ], + ), + ), + ), + SizedBox(height: isDesktop ? 28 : 16), + Padding( + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), + child: PrimaryButton( + label: "Send", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: () async { + final dynamic unlocked; + + if (isDesktop) { + unlocked = await showDialog( + context: context, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), + ], + ), + ), + ); + } else { + unlocked = await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: + "Confirm Transaction", + ), + settings: const RouteSettings( + name: "/confirmsendlockscreen", + ), + ), + ); + } + + if (mounted) { + if (unlocked == true) { + unawaited(_attemptSend()); + } else { + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: + Util.isDesktop + ? "Invalid passphrase" + : "Invalid PIN", + context: context, + ), + ); + } + } + } + }, + ), + ), + if (isDesktop) const SizedBox(height: 32), + ], + ), + ), + ); + } +} diff --git a/lib/pages/spark_names/spark_names_home_view.dart b/lib/pages/spark_names/spark_names_home_view.dart new file mode 100644 index 000000000..d4dbef2f9 --- /dev/null +++ b/lib/pages/spark_names/spark_names_home_view.dart @@ -0,0 +1,231 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../themes/stack_colors.dart'; +import '../../utilities/assets.dart'; +import '../../utilities/constants.dart'; +import '../../utilities/text_styles.dart'; +import '../../utilities/util.dart'; +import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/desktop/desktop_app_bar.dart'; +import '../../widgets/desktop/desktop_scaffold.dart'; +import '../../widgets/toggle.dart'; +import 'sub_widgets/buy_spark_name_option_widget.dart'; +import 'sub_widgets/manage_spark_names_option_widget.dart'; + +class SparkNamesHomeView extends ConsumerStatefulWidget { + const SparkNamesHomeView({super.key, required this.walletId}); + + final String walletId; + + static const String routeName = "/sparkNamesHomeView"; + + @override + ConsumerState createState() => + _NamecoinNamesHomeViewState(); +} + +class _NamecoinNamesHomeViewState extends ConsumerState { + bool _onManage = true; + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + final isDesktop = Util.isDesktop; + + return MasterScaffold( + isDesktop: isDesktop, + appBar: + isDesktop + ? DesktopAppBar( + isCompactHeight: true, + background: Theme.of(context).extension()!.popupBG, + leading: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 24, right: 20), + child: AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + ), + SvgPicture.asset( + Assets.svg.robotHead, + width: 32, + height: 32, + color: + Theme.of(context).extension()!.textDark, + ), + const SizedBox(width: 10), + Text("Names", style: STextStyles.desktopH3(context)), + ], + ), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "Names", + style: STextStyles.navBarTitle(context), + overflow: TextOverflow.ellipsis, + ), + ), + body: ConditionalParent( + condition: !isDesktop, + builder: + (child) => SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 16, left: 16, right: 16), + child: child, + ), + ), + child: + Util.isDesktop + ? Padding( + padding: const EdgeInsets.only(top: 24, left: 24, right: 24), + child: Row( + children: [ + SizedBox( + width: 460, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Text( + "Register", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + ], + ), + const SizedBox(height: 14), + Flexible( + child: BuySparkNameOptionWidget( + walletId: widget.walletId, + ), + ), + ], + ), + ), + const SizedBox(width: 24), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Text( + "Names", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + ], + ), + const SizedBox(height: 14), + Flexible( + child: SingleChildScrollView( + child: ManageSparkNamesOptionWidget( + walletId: widget.walletId, + ), + ), + ), + ], + ), + ), + ], + ), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + height: 48, + child: Toggle( + key: UniqueKey(), + onColor: + Theme.of(context).extension()!.popupBG, + offColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + onText: "Register", + offText: "Names", + isOn: !_onManage, + onValueChanged: (value) { + FocusManager.instance.primaryFocus?.unfocus(); + setState(() { + _onManage = !value; + }); + }, + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + ), + const SizedBox(height: 16), + Expanded( + child: IndexedStack( + index: _onManage ? 0 : 1, + children: [ + BuySparkNameOptionWidget(walletId: widget.walletId), + LayoutBuilder( + builder: (context, constraints) { + return ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: SingleChildScrollView( + child: IntrinsicHeight( + child: ManageSparkNamesOptionWidget( + walletId: widget.walletId, + ), + ), + ), + ); + }, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart new file mode 100644 index 000000000..b0ad03a38 --- /dev/null +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -0,0 +1,352 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../../providers/providers.dart'; +import '../../../themes/stack_colors.dart'; +import '../../../utilities/assets.dart'; +import '../../../utilities/constants.dart'; +import '../../../utilities/logger.dart'; +import '../../../utilities/show_loading.dart'; +import '../../../utilities/text_styles.dart'; +import '../../../utilities/util.dart'; +import '../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; +import '../../../widgets/desktop/desktop_dialog_close_button.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/desktop/secondary_button.dart'; +import '../../../widgets/dialogs/s_dialog.dart'; +import '../../../widgets/rounded_white_container.dart'; +import '../../../widgets/stack_dialog.dart'; +import '../buy_spark_name_view.dart'; + +class BuySparkNameOptionWidget extends ConsumerStatefulWidget { + const BuySparkNameOptionWidget({super.key, required this.walletId}); + + final String walletId; + + @override + ConsumerState createState() => + _BuySparkNameWidgetState(); +} + +class _BuySparkNameWidgetState extends ConsumerState { + final _nameController = TextEditingController(); + final _nameFieldFocus = FocusNode(); + + bool _isAvailable = false; + String? _lastLookedUpName; + + Future _checkIsAvailable(String name) async { + final wallet = + ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; + + final names = await wallet.electrumXClient.getSparkNames(); + + return !names.map((e) => e.toLowerCase()).contains(name.toLowerCase()); + } + + bool _lookupLock = false; + Future _lookup() async { + if (_lookupLock) return; + _lookupLock = true; + try { + _isAvailable = false; + + _lastLookedUpName = _nameController.text; + final result = await showLoading( + whileFuture: _checkIsAvailable(_lastLookedUpName!), + context: context, + message: "Searching...", + onException: (e) => throw e, + rootNavigator: Util.isDesktop, + delay: const Duration(seconds: 2), + ); + + _isAvailable = result == true; + + if (mounted) { + setState(() {}); + } + + Logging.instance.i("LOOKUP RESULT: $result"); + } catch (e, s) { + Logging.instance.e("_lookup failed", error: e, stackTrace: s); + + String? err; + if (e.toString().contains("Contains invalid characters")) { + err = "Contains invalid characters"; + } + + if (mounted) { + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Spark name lookup failed", + message: err, + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), + ); + } + } finally { + _lookupLock = false; + } + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + _nameFieldFocus.requestFocus(); + } + }); + } + + @override + void dispose() { + _nameController.dispose(); + _nameFieldFocus.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final double dotBitBoxLength = Util.isDesktop ? 100 : 74; + return Column( + crossAxisAlignment: + Util.isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, + children: [ + SizedBox( + height: 48, + child: Row( + children: [ + Expanded( + child: Container( + height: 48, + width: 100, + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.only( + topLeft: Radius.circular( + Constants.size.circularBorderRadius, + ), // Adjust radius as needed + bottomLeft: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: TextField( + inputFormatters: [ + LengthLimitingTextInputFormatter(kMaxNameLength), + ], + textInputAction: TextInputAction.search, + focusNode: _nameFieldFocus, + controller: _nameController, + textAlignVertical: TextAlignVertical.center, + decoration: InputDecoration( + isDense: true, + contentPadding: EdgeInsets.zero, + prefixIcon: Padding( + padding: const EdgeInsets.all(14), + child: SvgPicture.asset( + Assets.svg.search, + width: 20, + height: 20, + color: + Theme.of(context) + .extension()! + .textFieldDefaultSearchIconLeft, + ), + ), + fillColor: Colors.transparent, + hintText: "Find a spark name", + hintStyle: STextStyles.fieldLabel(context), + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + ), + onSubmitted: (_) { + if (_nameController.text.isNotEmpty) { + _lookup(); + } + }, + onChanged: (value) { + // trigger look up button enabled/disabled state change + setState(() {}); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 4), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.only(right: dotBitBoxLength), + child: Builder( + builder: (context) { + final length = _nameController.text.length; + return Text( + "$length/$kMaxNameLength", + style: STextStyles.w500_10(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle2, + ), + ); + }, + ), + ), + ], + ), + SizedBox(height: Util.isDesktop ? 24 : 16), + SecondaryButton( + label: "Lookup", + enabled: _nameController.text.isNotEmpty, + // width: Util.isDesktop ? 160 : double.infinity, + buttonHeight: Util.isDesktop ? ButtonHeight.l : null, + onPressed: _lookup, + ), + const SizedBox(height: 32), + if (_lastLookedUpName != null) + _NameCard( + walletId: widget.walletId, + isAvailable: _isAvailable, + name: _lastLookedUpName!, + ), + ], + ); + } +} + +class _NameCard extends ConsumerWidget { + const _NameCard({ + super.key, + required this.walletId, + required this.isAvailable, + required this.name, + }); + + final String walletId; + final bool isAvailable; + final String name; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final availability = isAvailable ? "Available" : "Unavailable"; + final color = + isAvailable + ? Theme.of(context).extension()!.accentColorGreen + : Theme.of(context).extension()!.accentColorRed; + + final style = + (Util.isDesktop + ? STextStyles.w500_16(context) + : STextStyles.w500_12(context)); + + return RoundedWhiteContainer( + padding: EdgeInsets.all(Util.isDesktop ? 24 : 16), + child: IntrinsicHeight( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(name, style: style), + const SizedBox(height: 4), + Text(availability, style: style.copyWith(color: color)), + ], + ), + ), + Column( + children: [ + PrimaryButton( + label: "Buy name", + enabled: isAvailable, + buttonHeight: + Util.isDesktop ? ButtonHeight.m : ButtonHeight.l, + width: Util.isDesktop ? 140 : 120, + onPressed: () async { + if (context.mounted) { + if (Util.isDesktop) { + await showDialog( + context: context, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Buy name", + style: STextStyles.desktopH3( + context, + ), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + ), + child: BuySparkNameView( + walletId: walletId, + name: name, + ), + ), + ], + ), + ), + ), + ); + } else { + await Navigator.of(context).pushNamed( + BuySparkNameView.routeName, + arguments: (walletId: walletId, name: name), + ); + } + } + }, + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart new file mode 100644 index 000000000..deece1a4e --- /dev/null +++ b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart @@ -0,0 +1,98 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:namecoin/namecoin.dart'; + +import '../../../models/isar/models/blockchain_data/utxo.dart'; +import '../../../providers/db/main_db_provider.dart'; +import '../../../utilities/util.dart'; +import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import 'owned_spark_name_card.dart'; + +class ManageSparkNamesOptionWidget extends ConsumerStatefulWidget { + const ManageSparkNamesOptionWidget({super.key, required this.walletId}); + + final String walletId; + + @override + ConsumerState createState() => + _ManageSparkNamesWidgetState(); +} + +class _ManageSparkNamesWidgetState + extends ConsumerState { + double _tempWidth = 0; + double? _width; + int _count = 0; + + void _sillyHack(double value, int length) { + if (value > _tempWidth) _tempWidth = value; + _count++; + if (_count == length) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _width = _tempWidth; + _tempWidth = 0; + }); + } + }); + } + } + + @override + Widget build(BuildContext context) { + final height = ref.watch(pWalletChainHeight(widget.walletId)); + return StreamBuilder( + stream: ref.watch( + mainDBProvider.select( + (s) => s.isar.utxos + .where() + .walletIdEqualTo(widget.walletId) + .filter() + .otherDataIsNotNull() + .watch(fireImmediately: true), + ), + ), + builder: (context, snapshot) { + List<(UTXO, OpNameData)> list = []; + if (snapshot.hasData) { + list = snapshot.data! + .map((utxo) { + final data = jsonDecode(utxo.otherData!) as Map; + + final nameData = + jsonDecode(data["nameOpData"] as String) as Map; + + return ( + utxo, + OpNameData(nameData.cast(), utxo.blockHeight ?? height), + ); + }) + .toList(growable: false); + } + + return Column( + children: [ + ...list.map( + (e) => Padding( + padding: const EdgeInsets.only(bottom: 10), + child: OwnedSparkNameCard( + key: ValueKey(e), + utxo: e.$1, + opNameData: e.$2, + firstColWidth: _width, + calculatedFirstColWidth: + (value) => _sillyHack(value, list.length), + ), + ), + ), + SizedBox(height: Util.isDesktop ? 14 : 6), + ], + ); + }, + ); + } +} diff --git a/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart new file mode 100644 index 000000000..f49a5f904 --- /dev/null +++ b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart @@ -0,0 +1,225 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:namecoin/namecoin.dart'; + +import '../../../models/isar/models/isar_models.dart'; +import '../../../providers/global/secure_store_provider.dart'; +import '../../../themes/stack_colors.dart'; +import '../../../utilities/text_styles.dart'; +import '../../../utilities/util.dart'; +import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../wallets/wallet/impl/namecoin_wallet.dart'; +import '../../../widgets/conditional_parent.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/dialogs/s_dialog.dart'; +import '../../../widgets/rounded_white_container.dart'; +import 'spark_name_details.dart'; + +class OwnedSparkNameCard extends ConsumerStatefulWidget { + const OwnedSparkNameCard({ + super.key, + required this.opNameData, + required this.utxo, + this.firstColWidth, + this.calculatedFirstColWidth, + }); + + final OpNameData opNameData; + final UTXO utxo; + + final double? firstColWidth; + final void Function(double)? calculatedFirstColWidth; + + @override + ConsumerState createState() => _OwnedSparkNameCardState(); +} + +class _OwnedSparkNameCardState extends ConsumerState { + String? constructedName, value; + + (String, Color) _getExpiry(int currentChainHeight, StackColors theme) { + final String message; + final Color color; + + if (widget.utxo.blockHash == null) { + message = "Expires in $blocksNameExpiration+ blocks"; + color = theme.accentColorGreen; + } else { + final remaining = widget.opNameData.expiredBlockLeft( + currentChainHeight, + false, + ); + final semiRemaining = widget.opNameData.expiredBlockLeft( + currentChainHeight, + true, + ); + + if (remaining == null) { + color = theme.accentColorRed; + message = "Expired"; + } else { + message = "Expires in $remaining blocks"; + if (semiRemaining == null) { + color = theme.accentColorYellow; + } else { + color = theme.accentColorGreen; + } + } + } + + return (message, color); + } + + bool _lock = false; + + Future _showDetails() async { + if (_lock) return; + _lock = true; + try { + if (Util.isDesktop) { + await showDialog( + context: context, + builder: + (context) => SDialog( + child: SparkNameDetailsView( + utxoId: widget.utxo.id, + walletId: widget.utxo.walletId, + ), + ), + ); + } else { + await Navigator.of(context).pushNamed( + SparkNameDetailsView.routeName, + arguments: (widget.utxo.id, widget.utxo.walletId), + ); + } + } finally { + _lock = false; + } + } + + void _setName() { + try { + constructedName = widget.opNameData.constructedName; + value = widget.opNameData.value; + } catch (_) { + if (widget.opNameData.op == OpName.nameNew) { + ref + .read(secureStoreProvider) + .read( + key: nameSaltKeyBuilder( + widget.utxo.txid, + widget.utxo.walletId, + widget.utxo.vout, + ), + ) + .then((onValue) { + if (onValue != null) { + final data = + (jsonDecode(onValue) as Map).cast(); + WidgetsBinding.instance.addPostFrameCallback((_) { + constructedName = data["name"]!; + value = data["value"]!; + if (mounted) { + setState(() {}); + } + }); + } else { + WidgetsBinding.instance.addPostFrameCallback((_) { + constructedName = "UNKNOWN"; + value = ""; + if (mounted) { + setState(() {}); + } + }); + } + }); + } + } + } + + @override + void initState() { + super.initState(); + _setName(); + } + + double _callbackWidth = 0; + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + final (message, color) = _getExpiry( + ref.watch(pWalletChainHeight(widget.utxo.walletId)), + Theme.of(context).extension()!, + ); + + return RoundedWhiteContainer( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ConditionalParent( + condition: widget.firstColWidth != null && Util.isDesktop, + builder: + (child) => ConstrainedBox( + constraints: BoxConstraints(maxWidth: widget.firstColWidth!), + child: child, + ), + child: ConditionalParent( + condition: widget.firstColWidth == null && Util.isDesktop, + builder: + (child) => LayoutBuilder( + builder: (context, constraints) { + if (widget.firstColWidth == null && + _callbackWidth != constraints.maxWidth) { + _callbackWidth = constraints.maxWidth; + widget.calculatedFirstColWidth?.call(_callbackWidth); + } + return ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth, + ), + child: child, + ); + }, + ), + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SelectableText(constructedName ?? ""), + const SizedBox(height: 8), + SelectableText( + message, + style: STextStyles.w500_12( + context, + ).copyWith(color: color), + ), + ], + ), + ), + ), + ), + if (Util.isDesktop) + Expanded( + child: SelectableText( + value ?? "", + style: STextStyles.w500_12(context), + ), + ), + if (Util.isDesktop) const SizedBox(width: 12), + PrimaryButton( + label: "Details", + buttonHeight: Util.isDesktop ? ButtonHeight.xs : ButtonHeight.l, + onPressed: _showDetails, + ), + ], + ), + ); + } +} diff --git a/lib/pages/spark_names/sub_widgets/spark_name_details.dart b/lib/pages/spark_names/sub_widgets/spark_name_details.dart new file mode 100644 index 000000000..3fe469cc8 --- /dev/null +++ b/lib/pages/spark_names/sub_widgets/spark_name_details.dart @@ -0,0 +1,565 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:namecoin/namecoin.dart'; + +import '../../../models/isar/models/isar_models.dart'; +import '../../../providers/db/main_db_provider.dart'; +import '../../../providers/global/secure_store_provider.dart'; +import '../../../providers/global/wallets_provider.dart'; +import '../../../themes/stack_colors.dart'; +import '../../../utilities/text_styles.dart'; +import '../../../utilities/util.dart'; +import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../wallets/wallet/impl/namecoin_wallet.dart'; +import '../../../widgets/background.dart'; +import '../../../widgets/conditional_parent.dart'; +import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../widgets/custom_buttons/simple_copy_button.dart'; +import '../../../widgets/desktop/desktop_dialog_close_button.dart'; +import '../../../widgets/rounded_container.dart'; +import '../../wallet_view/transaction_views/transaction_details_view.dart'; + +class SparkNameDetailsView extends ConsumerStatefulWidget { + const SparkNameDetailsView({ + super.key, + required this.utxoId, + required this.walletId, + }); + + static const routeName = "/sparkNameDetails"; + + final Id utxoId; + final String walletId; + + @override + ConsumerState createState() => + _SparkNameDetailsViewState(); +} + +class _SparkNameDetailsViewState extends ConsumerState { + late Stream streamUTXO; + UTXO? utxo; + OpNameData? opNameData; + + String? constructedName, value; + + Stream? streamLabel; + AddressLabel? label; + + void setUtxo(UTXO? utxo, int currentHeight) { + if (utxo != null) { + this.utxo = utxo; + final data = jsonDecode(utxo.otherData!) as Map; + + final nameData = jsonDecode(data["nameOpData"] as String) as Map; + opNameData = OpNameData( + nameData.cast(), + utxo.blockHeight ?? currentHeight, + ); + + _setName(); + } + } + + void _setName() { + try { + constructedName = opNameData!.constructedName; + value = opNameData!.value; + } catch (_) { + if (opNameData?.op == OpName.nameNew) { + ref + .read(secureStoreProvider) + .read( + key: nameSaltKeyBuilder(utxo!.txid, widget.walletId, utxo!.vout), + ) + .then((onValue) { + if (onValue != null) { + final data = + (jsonDecode(onValue) as Map).cast(); + WidgetsBinding.instance.addPostFrameCallback((_) { + constructedName = data["name"]!; + value = data["value"]!; + if (mounted) { + setState(() {}); + } + }); + } else { + WidgetsBinding.instance.addPostFrameCallback((_) { + constructedName = "UNKNOWN"; + value = ""; + if (mounted) { + setState(() {}); + } + }); + } + }); + } + } + } + + (String, Color) _getExpiry(int currentChainHeight, StackColors theme) { + final String message; + final Color color; + + if (utxo?.blockHash == null) { + message = "Expires in $blocksNameExpiration+ blocks"; + color = theme.accentColorGreen; + } else { + final remaining = opNameData?.expiredBlockLeft(currentChainHeight, false); + final semiRemaining = opNameData?.expiredBlockLeft( + currentChainHeight, + true, + ); + + if (remaining == null) { + color = theme.accentColorRed; + message = "Expired"; + } else { + message = "Expires in $remaining blocks"; + if (semiRemaining == null) { + color = theme.accentColorYellow; + } else { + color = theme.accentColorGreen; + } + } + } + + return (message, color); + } + + bool _checkConfirmedUtxo(int currentHeight) { + return (ref.read(pWallets).getWallet(widget.walletId) as NamecoinWallet) + .checkUtxoConfirmed(utxo!, currentHeight); + } + + @override + void initState() { + super.initState(); + + setUtxo( + ref + .read(mainDBProvider) + .isar + .utxos + .where() + .idEqualTo(widget.utxoId) + .findFirstSync(), + ref.read(pWalletChainHeight(widget.walletId)), + ); + + _setName(); + + if (utxo?.address != null) { + label = ref + .read(mainDBProvider) + .getAddressLabelSync(widget.walletId, utxo!.address!); + + if (label != null) { + streamLabel = ref.read(mainDBProvider).watchAddressLabel(id: label!.id); + } + } + + streamUTXO = ref.read(mainDBProvider).watchUTXO(id: widget.utxoId); + } + + @override + Widget build(BuildContext context) { + final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); + + final (message, color) = _getExpiry( + currentHeight, + Theme.of(context).extension()!, + ); + + return ConditionalParent( + condition: !Util.isDesktop, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + // Theme.of(context).extension()!.background, + leading: const AppBarBackButton(), + title: Text( + "Domain details", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ), + ); + }, + ), + ), + ), + ), + child: ConditionalParent( + condition: Util.isDesktop, + builder: (child) { + return SizedBox( + width: 641, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Domain details", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + top: 10, + ), + child: RoundedContainer( + padding: EdgeInsets.zero, + color: Colors.transparent, + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: child, + ), + ), + ], + ), + ); + }, + child: StreamBuilder( + stream: streamUTXO, + builder: (context, snapshot) { + if (snapshot.hasData) { + setUtxo(snapshot.data!, currentHeight); + } + + return utxo == null + ? Center( + child: Text( + "Missing output. Was it used recently?", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorRed, + ), + ), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // if (!isDesktop) + // const SizedBox( + // height: 10, + // ), + RoundedContainer( + padding: const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SelectableText( + constructedName ?? "", + style: STextStyles.pageTitleH2(context), + ), + if (Util.isDesktop) + SelectableText( + opNameData!.op.name, + style: STextStyles.w500_14(context), + ), + ], + ), + if (!Util.isDesktop) + SelectableText( + opNameData!.op.name, + style: STextStyles.w500_14(context), + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Value", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ), + ], + ), + const SizedBox(height: 4), + SelectableText( + value ?? "", + style: STextStyles.w500_14(context), + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Address", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ), + Util.isDesktop + ? IconCopyButton(data: utxo!.address!) + : SimpleCopyButton(data: utxo!.address!), + ], + ), + const SizedBox(height: 4), + SelectableText( + utxo!.address!, + style: STextStyles.w500_14(context), + ), + ], + ), + ), + if (label != null && label!.value.isNotEmpty) const _Div(), + if (label != null && label!.value.isNotEmpty) + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Address label", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + Util.isDesktop + ? IconCopyButton(data: label!.value) + : SimpleCopyButton(data: label!.value), + ], + ), + const SizedBox(height: 4), + SelectableText( + label!.value, + style: STextStyles.w500_14(context), + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction ID", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ), + Util.isDesktop + ? IconCopyButton(data: utxo!.txid) + : SimpleCopyButton(data: utxo!.txid), + ], + ), + const SizedBox(height: 4), + SelectableText( + utxo!.txid, + style: STextStyles.w500_14(context), + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Expiry", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ), + const SizedBox(height: 4), + SelectableText( + message, + style: STextStyles.w500_14( + context, + ).copyWith(color: color), + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ), + const SizedBox(height: 4), + SelectableText( + "${utxo!.getConfirmations(currentHeight)}", + style: STextStyles.w500_14(context), + ), + ], + ), + ), + ], + ); + }, + ), + ), + ); + } +} + +class _Div extends StatelessWidget { + const _Div({super.key}); + + @override + Widget build(BuildContext context) { + if (Util.isDesktop) { + return Container( + width: double.infinity, + height: 1.0, + color: Theme.of(context).extension()!.textFieldDefaultBG, + ); + } else { + return const SizedBox(height: 12); + } + } +} diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 41422c7e0..7356e07e6 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -98,6 +98,7 @@ import '../send_view/frost_ms/frost_send_view.dart'; import '../send_view/send_view.dart'; import '../settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import '../settings_views/wallet_settings_view/wallet_settings_view.dart'; +import '../spark_names/spark_names_home_view.dart'; import '../special/firo_rescan_recovery_error_dialog.dart'; import '../token_view/my_tokens_view.dart'; import 'sub_widgets/transactions_list.dart'; @@ -146,8 +147,9 @@ class _WalletViewState extends ConsumerState { bool _lelantusRescanRecovery = false; Future _firoRescanRecovery() async { - final success = await (ref.read(pWallets).getWallet(walletId) as FiroWallet) - .firoRescanRecovery(); + final success = + await (ref.read(pWallets).getWallet(walletId) as FiroWallet) + .firoRescanRecovery(); if (success) { // go into wallet @@ -160,10 +162,9 @@ class _WalletViewState extends ConsumerState { } else { // show error message dialog w/ options if (mounted) { - final shouldRetry = await Navigator.of(context).pushNamed( - FiroRescanRecoveryErrorView.routeName, - arguments: walletId, - ); + final shouldRetry = await Navigator.of( + context, + ).pushNamed(FiroRescanRecoveryErrorView.routeName, arguments: walletId); if (shouldRetry is bool && shouldRetry) { await _firoRescanRecovery(); @@ -218,41 +219,39 @@ class _WalletViewState extends ConsumerState { eventBus = widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; - _syncStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - // switch (event.newStatus) { - // case WalletSyncStatus.unableToSync: - // break; - // case WalletSyncStatus.synced: - // break; - // case WalletSyncStatus.syncing: - // break; - // } - setState(() { - _currentSyncStatus = event.newStatus; - }); - } - }, - ); - - _nodeStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - // switch (event.newStatus) { - // case NodeConnectionStatus.disconnected: - // break; - // case NodeConnectionStatus.connected: - // break; - // } - setState(() { - _currentNodeStatus = event.newStatus; - }); - } - }, - ); + _syncStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + // switch (event.newStatus) { + // case WalletSyncStatus.unableToSync: + // break; + // case WalletSyncStatus.synced: + // break; + // case WalletSyncStatus.syncing: + // break; + // } + setState(() { + _currentSyncStatus = event.newStatus; + }); + } + }); + + _nodeStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + // switch (event.newStatus) { + // case NodeConnectionStatus.disconnected: + // break; + // case NodeConnectionStatus.connected: + // break; + // } + setState(() { + _currentNodeStatus = event.newStatus; + }); + } + }); super.initState(); } @@ -379,9 +378,7 @@ class _WalletViewState extends ConsumerState { callerRouteName: WalletView.routeName, ); - await Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + await Navigator.of(context).pushNamed(FrostStepScaffold.routeName); } Future _onExchangePressed(BuildContext context) async { @@ -390,24 +387,27 @@ class _WalletViewState extends ConsumerState { if (coin.network.isTestNet) { await showDialog( context: context, - builder: (_) => const StackOkDialog( - title: "Exchange not available for test net coins", - ), + builder: + (_) => const StackOkDialog( + title: "Exchange not available for test net coins", + ), ); } else { Future _future; try { - _future = ExchangeDataLoadingService.instance.isar.currencies - .where() - .tickerEqualToAnyExchangeNameName(coin.ticker) - .findFirst(); + _future = + ExchangeDataLoadingService.instance.isar.currencies + .where() + .tickerEqualToAnyExchangeNameName(coin.ticker) + .findFirst(); } catch (_) { _future = ExchangeDataLoadingService.instance.loadAll().then( - (_) => ExchangeDataLoadingService.instance.isar.currencies + (_) => + ExchangeDataLoadingService.instance.isar.currencies .where() .tickerEqualToAnyExchangeNameName(coin.ticker) .findFirst(), - ); + ); } final currency = await showLoading( @@ -436,9 +436,10 @@ class _WalletViewState extends ConsumerState { if (coin.network.isTestNet) { await showDialog( context: context, - builder: (_) => const StackOkDialog( - title: "Buy not available for test net coins", - ), + builder: + (_) => const StackOkDialog( + title: "Buy not available for test net coins", + ), ); } else { if (mounted) { @@ -458,13 +459,14 @@ class _WalletViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => WillPopScope( - child: const CustomLoadingOverlay( - message: "Anonymizing balance", - eventBus: null, - ), - onWillPop: () async => shouldPop, - ), + builder: + (context) => WillPopScope( + child: const CustomLoadingOverlay( + message: "Anonymizing balance", + eventBus: null, + ), + onWillPop: () async => shouldPop, + ), ), ); final firoWallet = ref.read(pWallets).getWallet(walletId) as FiroWallet; @@ -473,9 +475,9 @@ class _WalletViewState extends ConsumerState { if (publicBalance <= Amount.zero) { shouldPop = true; if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(WalletView.routeName), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(WalletView.routeName)); unawaited( showFloatingFlushBar( type: FlushBarType.info, @@ -492,9 +494,9 @@ class _WalletViewState extends ConsumerState { await firoWallet.anonymizeAllSpark(); shouldPop = true; if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(WalletView.routeName), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(WalletView.routeName)); unawaited( showFloatingFlushBar( type: FlushBarType.success, @@ -506,15 +508,16 @@ class _WalletViewState extends ConsumerState { } catch (e) { shouldPop = true; if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(WalletView.routeName), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(WalletView.routeName)); await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Anonymize all failed", - message: "Reason: $e", - ), + builder: + (_) => StackOkDialog( + title: "Anonymize all failed", + message: "Reason: $e", + ), ); } } @@ -549,37 +552,46 @@ class _WalletViewState extends ConsumerState { eventBus: null, textColor: Theme.of(context).extension()!.textDark, - actionButton: _lelantusRescanRecovery - ? null - : SecondaryButton( - label: "Cancel", - onPressed: () async { - await showDialog( - context: context, - builder: (context) => StackDialog( - title: "Warning!", - message: "Skipping this process can completely" - " break your wallet. It is only meant to be done in" - " emergency situations where the migration fails" - " and will not let you continue. Still skip?", - leftButton: SecondaryButton( - label: "Cancel", - onPressed: - Navigator.of(context, rootNavigator: true) - .pop, - ), - rightButton: SecondaryButton( - label: "Ok", - onPressed: () { - Navigator.of(context, rootNavigator: true) - .pop(); - setState(() => _rescanningOnOpen = false); - }, - ), - ), - ); - }, - ), + actionButton: + _lelantusRescanRecovery + ? null + : SecondaryButton( + label: "Cancel", + onPressed: () async { + await showDialog( + context: context, + builder: + (context) => StackDialog( + title: "Warning!", + message: + "Skipping this process can completely" + " break your wallet. It is only meant to be done in" + " emergency situations where the migration fails" + " and will not let you continue. Still skip?", + leftButton: SecondaryButton( + label: "Cancel", + onPressed: + Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + rightButton: SecondaryButton( + label: "Ok", + onPressed: () { + Navigator.of( + context, + rootNavigator: true, + ).pop(); + setState( + () => _rescanningOnOpen = false, + ); + }, + ), + ), + ); + }, + ), ), ), ], @@ -605,15 +617,11 @@ class _WalletViewState extends ConsumerState { title: Row( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: Text( ref.watch(pWalletName(walletId)), @@ -625,15 +633,8 @@ class _WalletViewState extends ConsumerState { ), actions: [ const Padding( - padding: EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: SmallTorIcon(), - ), + padding: EdgeInsets.only(top: 10, bottom: 10, right: 10), + child: AspectRatio(aspectRatio: 1, child: SmallTorIcon()), ), Padding( padding: const EdgeInsets.only( @@ -649,9 +650,10 @@ class _WalletViewState extends ConsumerState { key: const Key("walletViewRadioButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: _buildNetworkIcon(_currentSyncStatus), onPressed: () { Navigator.of(context).pushNamed( @@ -680,91 +682,105 @@ class _WalletViewState extends ConsumerState { key: const Key("walletViewAlertsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: ref.watch( - notificationsProvider.select( - (value) => - value.hasUnreadNotificationsFor(walletId), - ), - ) - ? SvgPicture.file( - File( - ref.watch( - themeProvider.select( - (value) => value.assets.bellNew, - ), - ), - ), - width: 20, - height: 20, - color: ref.watch( + color: + Theme.of( + context, + ).extension()!.background, + icon: + ref.watch( notificationsProvider.select( - (value) => - value.hasUnreadNotificationsFor( - walletId, - ), + (value) => value + .hasUnreadNotificationsFor(walletId), ), ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ) - : SvgPicture.asset( - Assets.svg.bell, - width: 20, - height: 20, - color: ref.watch( - notificationsProvider.select( - (value) => - value.hasUnreadNotificationsFor( - walletId, + ? SvgPicture.file( + File( + ref.watch( + themeProvider.select( + (value) => value.assets.bellNew, + ), ), ), + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => value + .hasUnreadNotificationsFor( + walletId, + ), + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ), + : SvgPicture.asset( + Assets.svg.bell, + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => value + .hasUnreadNotificationsFor( + walletId, + ), + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, + ), onPressed: () { // reset unread state ref.refresh(unreadNotificationsStateProvider); Navigator.of(context) .pushNamed( - NotificationsView.routeName, - arguments: walletId, - ) + NotificationsView.routeName, + arguments: walletId, + ) .then((_) { - final Set unreadNotificationIds = ref - .read(unreadNotificationsStateProvider.state) - .state; - if (unreadNotificationIds.isEmpty) return; - - final List> futures = []; - for (int i = 0; - i < unreadNotificationIds.length - 1; - i++) { - futures.add( - ref.read(notificationsProvider).markAsRead( - unreadNotificationIds.elementAt(i), - false, - ), - ); - } - - // wait for multiple to update if any - Future.wait(futures).then((_) { - // only notify listeners once - ref.read(notificationsProvider).markAsRead( - unreadNotificationIds.last, - true, + final Set unreadNotificationIds = + ref + .read( + unreadNotificationsStateProvider + .state, + ) + .state; + if (unreadNotificationIds.isEmpty) return; + + final List> futures = []; + for ( + int i = 0; + i < unreadNotificationIds.length - 1; + i++ + ) { + futures.add( + ref + .read(notificationsProvider) + .markAsRead( + unreadNotificationIds.elementAt(i), + false, + ), ); - }); - }); + } + + // wait for multiple to update if any + Future.wait(futures).then((_) { + // only notify listeners once + ref + .read(notificationsProvider) + .markAsRead( + unreadNotificationIds.last, + true, + ); + }); + }); }, ), ), @@ -783,14 +799,16 @@ class _WalletViewState extends ConsumerState { key: const Key("walletViewSettingsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.bars, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -818,29 +836,25 @@ class _WalletViewState extends ConsumerState { Theme.of(context).extension()!.background, child: Column( children: [ - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: WalletSummary( walletId: walletId, aspectRatio: 1.75, - initialSyncStatus: ref - .watch(pWallets) - .getWallet(walletId) - .refreshMutex - .isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, + initialSyncStatus: + ref + .watch(pWallets) + .getWallet(walletId) + .refreshMutex + .isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, ), ), ), - if (isSparkWallet) - const SizedBox( - height: 10, - ), + if (isSparkWallet) const SizedBox(height: 10), if (isSparkWallet) Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -856,51 +870,59 @@ class _WalletViewState extends ConsumerState { onPressed: () async { await showDialog( context: context, - builder: (context) => StackDialog( - title: "Attention!", - message: - "You're about to anonymize all of your public funds.", - leftButton: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text( - "Cancel", - style: STextStyles.button(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + builder: + (context) => StackDialog( + title: "Attention!", + message: + "You're about to anonymize all of your public funds.", + leftButton: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + "Cancel", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), + ), ), - ), - ), - rightButton: TextButton( - onPressed: () async { - Navigator.of(context).pop(); + rightButton: TextButton( + onPressed: () async { + Navigator.of(context).pop(); - unawaited(attemptAnonymize()); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle( - context, + unawaited(attemptAnonymize()); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle( + context, + ), + child: Text( + "Continue", + style: STextStyles.button( + context, + ), ), - child: Text( - "Continue", - style: - STextStyles.button(context), + ), ), - ), - ), ); }, child: Text( "Anonymize funds", - style: - STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), ), ), @@ -908,9 +930,7 @@ class _WalletViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( @@ -918,11 +938,13 @@ class _WalletViewState extends ConsumerState { children: [ Text( "Transactions", - style: - STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, ), ), CustomTextButton( @@ -943,9 +965,7 @@ class _WalletViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -970,11 +990,7 @@ class _WalletViewState extends ConsumerState { Colors.transparent, Colors.white, ], - stops: [ - 0.0, - 0.8, - 1.0, - ], + stops: [0.0, 0.8, 1.0], ).createShader(bounds); }, child: Container( @@ -989,17 +1005,20 @@ class _WalletViewState extends ConsumerState { CrossAxisAlignment.stretch, children: [ Expanded( - child: ref - .read(pWallets) - .getWallet(widget.walletId) - .isarTransactionVersion == - 2 - ? TransactionsV2List( - walletId: widget.walletId, - ) - : TransactionsList( - walletId: walletId, - ), + child: + ref + .read(pWallets) + .getWallet( + widget.walletId, + ) + .isarTransactionVersion == + 2 + ? TransactionsV2List( + walletId: widget.walletId, + ) + : TransactionsList( + walletId: walletId, + ), ), ], ), @@ -1059,10 +1078,7 @@ class _WalletViewState extends ConsumerState { wallet is BitcoinFrostWallet ? FrostSendView.routeName : SendView.routeName, - arguments: ( - walletId: walletId, - coin: coin, - ), + arguments: (walletId: walletId, coin: coin), ); }, ), @@ -1089,10 +1105,11 @@ class _WalletViewState extends ConsumerState { moreItems: [ if (ref.watch( pWallets.select( - (value) => value - .getWallet(widget.walletId) - .cryptoCurrency - .hasTokenSupport, + (value) => + value + .getWallet(widget.walletId) + .cryptoCurrency + .hasTokenSupport, ), )) WalletNavigationBarItemData( @@ -1111,9 +1128,10 @@ class _WalletViewState extends ConsumerState { Assets.svg.monkey, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .bottomNavIconIcon, + color: + Theme.of( + context, + ).extension()!.bottomNavIconIcon, ), label: "MonKey", onTap: () { @@ -1185,6 +1203,17 @@ class _WalletViewState extends ConsumerState { ); }, ), + if (wallet is SparkInterface) + WalletNavigationBarItemData( + label: "Names", + icon: const PaynymNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + SparkNamesHomeView.routeName, + arguments: widget.walletId, + ); + }, + ), if (!viewOnly && wallet is PaynymInterface) WalletNavigationBarItemData( label: "PayNym", @@ -1193,14 +1222,14 @@ class _WalletViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => const LoadingIndicator( - width: 100, - ), + builder: + (context) => const LoadingIndicator(width: 100), ), ); - final wallet = - ref.read(pWallets).getWallet(widget.walletId); + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); final paynymInterface = wallet as PaynymInterface; @@ -1219,10 +1248,10 @@ class _WalletViewState extends ConsumerState { // check if account exists and for matching code to see if claimed if (account.value != null && - account.value!.nonSegwitPaymentCode.claimed - // && - // account.value!.segwit - ) { + account.value!.nonSegwitPaymentCode.claimed + // && + // account.value!.segwit + ) { ref.read(myPaynymAccountStateProvider.state).state = account.value!; diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 78a36d8d7..0cfab7c16 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -21,6 +21,7 @@ import '../../../../pages/monkey/monkey_view.dart'; import '../../../../pages/namecoin_names/namecoin_names_home_view.dart'; import '../../../../pages/paynym/paynym_claim_view.dart'; import '../../../../pages/paynym/paynym_home_view.dart'; +import '../../../../pages/spark_names/spark_names_home_view.dart'; import '../../../../providers/desktop/current_desktop_menu_item.dart'; import '../../../../providers/global/paynym_api_provider.dart'; import '../../../../providers/providers.dart'; @@ -99,6 +100,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { onFusionPressed: _onFusionPressed, onChurnPressed: _onChurnPressed, onNamesPressed: _onNamesPressed, + onSparkNamesPressed: _onSparkNamesPressed, ), ); } @@ -371,6 +373,14 @@ class _DesktopWalletFeaturesState extends ConsumerState { ).pushNamed(NamecoinNamesHomeView.routeName, arguments: widget.walletId); } + void _onSparkNamesPressed() { + Navigator.of(context, rootNavigator: true).pop(); + + Navigator.of( + context, + ).pushNamed(SparkNamesHomeView.routeName, arguments: widget.walletId); + } + @override Widget build(BuildContext context) { final wallet = ref.watch(pWallets).getWallet(widget.walletId); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 1ee0447b3..e16766deb 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -67,6 +67,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { required this.onFusionPressed, required this.onChurnPressed, required this.onNamesPressed, + required this.onSparkNamesPressed, }); final String walletId; @@ -82,6 +83,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { final VoidCallback? onFusionPressed; final VoidCallback? onChurnPressed; final VoidCallback? onNamesPressed; + final VoidCallback? onSparkNamesPressed; @override ConsumerState createState() => _MoreFeaturesDialogState(); @@ -492,6 +494,13 @@ class _MoreFeaturesDialogState extends ConsumerState { iconAsset: Assets.svg.robotHead, onPressed: () async => widget.onNamesPressed?.call(), ), + if (wallet is SparkInterface) + _MoreFeaturesItem( + label: "Names", + detail: "Spark names", + iconAsset: Assets.svg.robotHead, + onPressed: () async => widget.onSparkNamesPressed?.call(), + ), if (wallet is SparkInterface && !isViewOnly) _MoreFeaturesClearSparkCacheItem( cryptoCurrency: wallet.cryptoCurrency, diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 6695a53b8..a07ebf7e1 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -147,6 +147,8 @@ import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_setting import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart'; +import 'pages/spark_names/buy_spark_name_view.dart'; +import 'pages/spark_names/spark_names_home_view.dart'; import 'pages/special/firo_rescan_recovery_error_dialog.dart'; import 'pages/stack_privacy_calls.dart'; import 'pages/token_view/my_tokens_view.dart'; @@ -253,12 +255,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreatePinView( - popOnSuccess: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreatePinView(popOnSuccess: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -285,14 +283,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChooseCoinView( - title: args.item1, - coinAdditional: args.item2, - nextRouteName: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ChooseCoinView( + title: args.item1, + coinAdditional: args.item2, + nextRouteName: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -301,12 +298,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ManageExplorerView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ManageExplorerView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -315,12 +308,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FiroRescanRecoveryErrorView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FiroRescanRecoveryErrorView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -343,23 +332,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditWalletTokensView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditWalletTokensView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditWalletTokensView( - walletId: args.item1, - contractsToMarkSelected: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditWalletTokensView( + walletId: args.item1, + contractsToMarkSelected: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -368,12 +352,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopTokenView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopTokenView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -382,12 +362,8 @@ class RouteGenerator { if (args is EthTokenEntity) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SelectWalletForTokenView( - entity: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SelectWalletForTokenView(entity: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -396,21 +372,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const AddCustomTokenView(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case WalletsOverview.routeName: if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletsOverview( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletsOverview(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -419,13 +389,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenContractDetailsView( - contractAddress: args.item1, - walletId: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenContractDetailsView( + contractAddress: args.item1, + walletId: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -434,13 +403,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SingleFieldEditView( - initialValue: args.item1, - label: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SingleFieldEditView( + initialValue: args.item1, + label: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -449,66 +417,50 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MonkeyView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => MonkeyView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case CreateNewFrostMsWalletView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreateNewFrostMsWalletView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CreateNewFrostMsWalletView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreFrostMsWalletView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreFrostMsWalletView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreFrostMsWalletView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case SelectNewFrostImportTypeView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SelectNewFrostImportTypeView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SelectNewFrostImportTypeView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -517,21 +469,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const FrostStepScaffold(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case FrostMSWalletOptionsView.routeName: if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostMSWalletOptionsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FrostMSWalletOptionsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -540,12 +486,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostParticipantsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FrostParticipantsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -554,12 +496,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => InitiateResharingView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => InitiateResharingView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -568,31 +506,23 @@ class RouteGenerator { if (args is ({String walletId, Map resharers})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CompleteReshareConfigView( - walletId: args.walletId, - resharers: args.resharers, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CompleteReshareConfigView( + walletId: args.walletId, + resharers: args.resharers, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case FrostSendView.routeName: - if (args is ({ - String walletId, - CryptoCurrency coin, - })) { + if (args is ({String walletId, CryptoCurrency coin})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostSendView( - walletId: args.walletId, - coin: args.coin, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => FrostSendView(walletId: args.walletId, coin: args.coin), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -616,27 +546,22 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinControlView( - walletId: args.item1, - type: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CoinControlView(walletId: args.item1, type: args.item2), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple4?>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinControlView( - walletId: args.item1, - type: args.item2, - requestedTotal: args.item3, - selectedUTXOs: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CoinControlView( + walletId: args.item1, + type: args.item2, + requestedTotal: args.item3, + selectedUTXOs: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -645,12 +570,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => OrdinalsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => OrdinalsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -659,12 +580,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopOrdinalsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopOrdinalsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -673,13 +590,12 @@ class RouteGenerator { if (args is ({Ordinal ordinal, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => OrdinalDetailsView( - walletId: args.walletId, - ordinal: args.ordinal, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => OrdinalDetailsView( + walletId: args.walletId, + ordinal: args.ordinal, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -688,13 +604,12 @@ class RouteGenerator { if (args is ({Ordinal ordinal, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopOrdinalDetailsView( - walletId: args.walletId, - ordinal: args.ordinal, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DesktopOrdinalDetailsView( + walletId: args.walletId, + ordinal: args.ordinal, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -710,13 +625,10 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => UtxoDetailsView( - walletId: args.item2, - utxoId: args.item1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => + UtxoDetailsView(walletId: args.item2, utxoId: args.item1), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -725,13 +637,8 @@ class RouteGenerator { if (args is (Id, String)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NameDetailsView( - walletId: args.$2, - utxoId: args.$1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NameDetailsView(walletId: args.$2, utxoId: args.$1), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -740,12 +647,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => PaynymClaimView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => PaynymClaimView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -754,12 +657,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => PaynymHomeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => PaynymHomeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -768,12 +667,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddNewPaynymFollowView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddNewPaynymFollowView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -782,12 +677,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CashFusionView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CashFusionView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -796,12 +687,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NamecoinNamesHomeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NamecoinNamesHomeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -810,13 +697,132 @@ class RouteGenerator { if (args is ({String walletId, UTXO utxo})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ManageDomainView( - walletId: args.walletId, - utxo: args.utxo, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => + ManageDomainView(walletId: args.walletId, utxo: args.utxo), + settings: RouteSettings(name: settings.name), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + case SparkNamesHomeView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => SparkNamesHomeView(walletId: args), + settings: RouteSettings(name: settings.name), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + + case BuySparkNameView.routeName: + if (args is ({String walletId, String name})) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => + BuySparkNameView(walletId: args.walletId, name: args.name), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -825,12 +831,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FusionProgressView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FusionProgressView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -839,12 +841,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChurningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChurningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -853,12 +851,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChurningProgressView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChurningProgressView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -867,12 +861,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopCashFusionView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopCashFusionView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -881,12 +871,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopChurningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopChurningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -902,12 +888,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddressBookView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddressBookView(coin: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -1011,13 +993,8 @@ class RouteGenerator { if (args is (String, ({List xpubs, String fingerprint}))) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => XPubView( - walletId: args.$1, - xpubData: args.$2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => XPubView(walletId: args.$1, xpubData: args.$2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1026,12 +1003,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChangeRepresentativeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChangeRepresentativeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1117,12 +1090,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreFromEncryptedStringView( - encrypted: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => RestoreFromEncryptedStringView(encrypted: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1138,12 +1107,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditCoinUnitsView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditCoinUnitsView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1173,12 +1138,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinNodesView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CoinNodesView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1187,14 +1148,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NodeDetailsView( - coin: args.item1, - nodeId: args.item2, - popRouteName: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NodeDetailsView( + coin: args.item1, + nodeId: args.item2, + popRouteName: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1203,13 +1163,9 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditNoteView( - txid: args.item1, - walletId: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditNoteView(txid: args.item1, walletId: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1218,12 +1174,8 @@ class RouteGenerator { if (args is int) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditAddressLabelView( - addressLabelId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditAddressLabelView(addressLabelId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1232,13 +1184,9 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditTradeNoteView( - tradeId: args.item1, - note: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditTradeNoteView(tradeId: args.item1, note: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1248,15 +1196,14 @@ class RouteGenerator { is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddEditNodeView( - viewType: args.item1, - coin: args.item2, - nodeId: args.item3, - routeOnSuccessOrDelete: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AddEditNodeView( + viewType: args.item1, + coin: args.item2, + nodeId: args.item3, + routeOnSuccessOrDelete: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1265,12 +1212,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ContactDetailsView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ContactDetailsView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1279,12 +1222,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddNewContactAddressView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddNewContactAddressView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1293,12 +1232,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditContactNameEmojiView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditContactNameEmojiView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1307,13 +1242,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditContactAddressView( - contactId: args.item1, - addressEntry: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditContactAddressView( + contactId: args.item1, + addressEntry: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1322,23 +1256,20 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const SystemBrightnessThemeSelectionView(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case WalletNetworkSettingsView.routeName: if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletNetworkSettingsView( - walletId: args.item1, - initialSyncStatus: args.item2, - initialNodeStatus: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletNetworkSettingsView( + walletId: args.item1, + initialSyncStatus: args.item2, + initialNodeStatus: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1347,91 +1278,88 @@ class RouteGenerator { if (args is ({String walletId, List mnemonic})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - frostWalletData: args.frostWalletData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + frostWalletData: args.frostWalletData, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - KeyDataInterface? keyData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + KeyDataInterface? keyData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - KeyDataInterface? keyData, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - frostWalletData: args.frostWalletData, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + KeyDataInterface? keyData, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + frostWalletData: args.frostWalletData, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case MobileKeyDataView.routeName: - if (args is ({ - String walletId, - KeyDataInterface keyData, - })) { + if (args is ({String walletId, KeyDataInterface keyData})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MobileKeyDataView( - walletId: args.walletId, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => MobileKeyDataView( + walletId: args.walletId, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1440,12 +1368,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletSettingsWalletSettingsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletSettingsWalletSettingsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1454,12 +1378,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RenameWalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => RenameWalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1468,12 +1388,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletWarningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DeleteWalletWarningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1482,12 +1398,8 @@ class RouteGenerator { if (args is AddWalletListEntity) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreateOrRestoreWalletView( - entity: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreateOrRestoreWalletView(entity: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1496,13 +1408,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NameYourWalletView( - addWalletType: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NameYourWalletView( + addWalletType: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1511,13 +1422,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletRecoveryPhraseWarningView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletRecoveryPhraseWarningView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1526,13 +1436,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreOptionsView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreOptionsView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1541,13 +1450,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletOptionsView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletOptionsView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1557,39 +1465,38 @@ class RouteGenerator { is Tuple6) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreWalletView( - walletName: args.item1, - coin: args.item2, - seedWordsLength: args.item3, - restoreFromDate: args.item4, - mnemonicPassphrase: args.item5, - enableLelantusScanning: args.item6 ?? false, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreWalletView( + walletName: args.item1, + coin: args.item2, + seedWordsLength: args.item3, + restoreFromDate: args.item4, + mnemonicPassphrase: args.item5, + enableLelantusScanning: args.item6 ?? false, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreViewOnlyWalletView.routeName: - if (args is ({ - String walletName, - CryptoCurrency coin, - DateTime? restoreFromDate, - bool enableLelantusScanning, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreViewOnlyWalletView( - walletName: args.walletName, - coin: args.coin, - restoreFromDate: args.restoreFromDate, - enableLelantusScanning: args.enableLelantusScanning, - ), - settings: RouteSettings( - name: settings.name, - ), + if (args + is ({ + String walletName, + CryptoCurrency coin, + DateTime? restoreFromDate, + bool enableLelantusScanning, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => RestoreViewOnlyWalletView( + walletName: args.walletName, + coin: args.coin, + restoreFromDate: args.restoreFromDate, + enableLelantusScanning: args.enableLelantusScanning, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1598,13 +1505,12 @@ class RouteGenerator { if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletRecoveryPhraseView( - wallet: args.item1, - mnemonic: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletRecoveryPhraseView( + wallet: args.item1, + mnemonic: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1613,13 +1519,12 @@ class RouteGenerator { if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => VerifyRecoveryPhraseView( - wallet: args.item1, - mnemonic: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => VerifyRecoveryPhraseView( + wallet: args.item1, + mnemonic: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1634,12 +1539,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1648,54 +1549,49 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionDetailsView( - transaction: args.item1, - coin: args.item2, - walletId: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TransactionDetailsView( + transaction: args.item1, + coin: args.item2, + walletId: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case TransactionV2DetailsView.routeName: - if (args is ({ - TransactionV2 tx, - CryptoCurrency coin, - String walletId - })) { + if (args + is ({TransactionV2 tx, CryptoCurrency coin, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionV2DetailsView( - transaction: args.tx, - coin: args.coin, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TransactionV2DetailsView( + transaction: args.tx, + coin: args.coin, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case FusionGroupDetailsView.routeName: - if (args is ({ - List transactions, - CryptoCurrency coin, - String walletId - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FusionGroupDetailsView( - transactions: args.transactions, - coin: args.coin, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + if (args + is ({ + List transactions, + CryptoCurrency coin, + String walletId, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => FusionGroupDetailsView( + transactions: args.transactions, + coin: args.coin, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1704,12 +1600,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AllTransactionsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1718,24 +1610,19 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsV2View( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AllTransactionsV2View(walletId: args), + settings: RouteSettings(name: settings.name), ); } if (args is ({String walletId, String contractAddress})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsV2View( - walletId: args.walletId, - contractAddress: args.contractAddress, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AllTransactionsV2View( + walletId: args.walletId, + contractAddress: args.contractAddress, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1744,12 +1631,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionSearchFilterView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => TransactionSearchFilterView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1758,23 +1641,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ReceiveView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ReceiveView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ReceiveView( - walletId: args.item1, - tokenContract: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ReceiveView( + walletId: args.item1, + tokenContract: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1783,12 +1661,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletAddressesView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletAddressesView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1797,13 +1671,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddressDetailsView( - walletId: args.item2, - addressId: args.item1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AddressDetailsView( + walletId: args.item2, + addressId: args.item1, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1812,49 +1685,37 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SendView(walletId: args.item1, coin: args.item2), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - autoFillData: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendView( + walletId: args.item1, + coin: args.item2, + autoFillData: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - accountLite: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendView( + walletId: args.item1, + coin: args.item2, + accountLite: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } else if (args is ({CryptoCurrency coin, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.walletId, - coin: args.coin, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SendView(walletId: args.walletId, coin: args.coin), + settings: RouteSettings(name: settings.name), ); } @@ -1864,14 +1725,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenSendView( - walletId: args.item1, - coin: args.item2, - tokenContract: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenSendView( + walletId: args.item1, + coin: args.item2, + tokenContract: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1880,14 +1740,13 @@ class RouteGenerator { if (args is (TxData, String, VoidCallback)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: args.$1, - walletId: args.$2, - onSuccess: args.$3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ConfirmTransactionView( + txData: args.$1, + walletId: args.$2, + onSuccess: args.$3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1896,13 +1755,12 @@ class RouteGenerator { if (args is (TxData, String)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ConfirmNameTransactionView( - txData: args.$1, - walletId: args.$2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ConfirmNameTransactionView( + txData: args.$1, + walletId: args.$2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1911,40 +1769,38 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Stack( - children: [ - WalletInitiatedExchangeView( - walletId: args.item1, - coin: args.item2, + builder: + (_) => Stack( + children: [ + WalletInitiatedExchangeView( + walletId: args.item1, + coin: args.item2, + ), + // ExchangeLoadingOverlayView( + // unawaitedLoad: args.item3, + // ), + ], ), - // ExchangeLoadingOverlayView( - // unawaitedLoad: args.item3, - // ), - ], - ), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Stack( - children: [ - WalletInitiatedExchangeView( - walletId: args.item1, - coin: args.item2, - contract: args.item3, + builder: + (_) => Stack( + children: [ + WalletInitiatedExchangeView( + walletId: args.item1, + coin: args.item2, + contract: args.item3, + ), + // ExchangeLoadingOverlayView( + // unawaitedLoad: args.item3, + // ), + ], ), - // ExchangeLoadingOverlayView( - // unawaitedLoad: args.item3, - // ), - ], - ), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1953,30 +1809,30 @@ class RouteGenerator { if (args is String?) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NotificationsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NotificationsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case WalletSettingsView.routeName: - if (args is Tuple4) { + if (args + is Tuple4< + String, + CryptoCurrency, + WalletSyncStatus, + NodeConnectionStatus + >) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletSettingsView( - walletId: args.item1, - coin: args.item2, - initialSyncStatus: args.item3, - initialNodeStatus: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletSettingsView( + walletId: args.item1, + coin: args.item2, + initialSyncStatus: args.item3, + initialNodeStatus: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1985,34 +1841,34 @@ class RouteGenerator { if (args is ({String walletId, List mnemonicWords})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletRecoveryPhraseView( - mnemonic: args.mnemonicWords, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DeleteWalletRecoveryPhraseView( + mnemonic: args.mnemonicWords, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonicWords, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletRecoveryPhraseView( - mnemonic: args.mnemonicWords, - walletId: args.walletId, - frostWalletData: args.frostWalletData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonicWords, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => DeleteWalletRecoveryPhraseView( + mnemonic: args.mnemonicWords, + walletId: args.walletId, + frostWalletData: args.frostWalletData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2021,13 +1877,12 @@ class RouteGenerator { if (args is ({String walletId, ViewOnlyWalletData data})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteViewOnlyWalletKeysView( - data: args.data, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DeleteViewOnlyWalletKeysView( + data: args.data, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2038,12 +1893,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step1View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step1View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2052,12 +1903,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step2View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step2View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2066,12 +1913,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step3View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step3View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2080,12 +1923,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step4View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step4View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2094,15 +1933,14 @@ class RouteGenerator { if (args is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TradeDetailsView( - tradeId: args.item1, - transactionIfSentFromStack: args.item2, - walletId: args.item3, - walletName: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TradeDetailsView( + tradeId: args.item1, + transactionIfSentFromStack: args.item2, + walletId: args.item3, + walletName: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2111,12 +1949,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChooseFromStackView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChooseFromStackView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2125,15 +1959,14 @@ class RouteGenerator { if (args is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendFromView( - coin: args.item1, - amount: args.item2, - trade: args.item4, - address: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendFromView( + coin: args.item1, + amount: args.item2, + trade: args.item4, + address: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2142,13 +1975,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => GenerateUriQrCodeView( - coin: args.item1, - receivingAddress: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => GenerateUriQrCodeView( + coin: args.item1, + receivingAddress: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2157,12 +1989,8 @@ class RouteGenerator { if (args is SimplexQuote) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyQuotePreviewView( - quote: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => BuyQuotePreviewView(quote: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2172,9 +2000,7 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => LelantusSettingsView(walletId: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2184,9 +2010,7 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => RbfSettingsView(walletId: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2195,12 +2019,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SparkInfoView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SparkInfoView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2209,12 +2029,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditRefreshHeightView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditRefreshHeightView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2223,13 +2039,12 @@ class RouteGenerator { if (args is ({String walletId, String domainName})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyDomainView( - walletId: args.walletId, - domainName: args.domainName, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => BuyDomainView( + walletId: args.walletId, + domainName: args.domainName, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2239,12 +2054,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreatePasswordView( - restoreFromSWB: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreatePasswordView(restoreFromSWB: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -2271,12 +2082,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeletePasswordWarningView( - shouldCreateNew: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DeletePasswordWarningView(shouldCreateNew: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2314,21 +2121,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => BuyInWalletView(coin: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyInWalletView( - coin: args.item1, - contract: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => BuyInWalletView(coin: args.item1, contract: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2365,12 +2166,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopWalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopWalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2379,12 +2176,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopWalletAddressesView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopWalletAddressesView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2393,12 +2186,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => LelantusCoinsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => LelantusCoinsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2407,12 +2196,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SparkCoinsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SparkCoinsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2421,12 +2206,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopCoinControlView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopCoinControlView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2435,12 +2216,8 @@ class RouteGenerator { if (args is TransactionV2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BoostTransactionView( - transaction: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => BoostTransactionView(transaction: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2530,27 +2307,27 @@ class RouteGenerator { ); case WalletKeysDesktopPopup.routeName: - if (args is ({ - List mnemonic, - String walletId, - ({String keys, String config})? frostData - })) { + if (args + is ({ + List mnemonic, + String walletId, + ({String keys, String config})? frostData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, walletId: args.walletId, frostData: args.frostData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); - } else if (args is ({ - List mnemonic, - String walletId, - ({String keys, String config})? frostData, - KeyDataInterface? keyData, - })) { + } else if (args + is ({ + List mnemonic, + String walletId, + ({String keys, String config})? frostData, + KeyDataInterface? keyData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, @@ -2558,24 +2335,21 @@ class RouteGenerator { frostData: args.frostData, keyData: args.keyData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); - } else if (args is ({ - List mnemonic, - String walletId, - KeyDataInterface? keyData, - })) { + } else if (args + is ({ + List mnemonic, + String walletId, + KeyDataInterface? keyData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, walletId: args.walletId, keyData: args.keyData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2583,12 +2357,8 @@ class RouteGenerator { case UnlockWalletKeysDesktop.routeName: if (args is String) { return FadePageRoute( - UnlockWalletKeysDesktop( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + UnlockWalletKeysDesktop(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2605,12 +2375,8 @@ class RouteGenerator { case DesktopDeleteWalletDialog.routeName: if (args is String) { return FadePageRoute( - DesktopDeleteWalletDialog( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + DesktopDeleteWalletDialog(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2627,12 +2393,8 @@ class RouteGenerator { case DesktopAttentionDeleteWallet.routeName: if (args is String) { return FadePageRoute( - DesktopAttentionDeleteWallet( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + DesktopAttentionDeleteWallet(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2649,13 +2411,8 @@ class RouteGenerator { case DeleteWalletKeysPopup.routeName: if (args is Tuple2>) { return FadePageRoute( - DeleteWalletKeysPopup( - walletId: args.item1, - words: args.item2, - ), - RouteSettings( - name: settings.name, - ), + DeleteWalletKeysPopup(walletId: args.item1, words: args.item2), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2672,12 +2429,8 @@ class RouteGenerator { case QRCodeDesktopPopupContent.routeName: if (args is String) { return FadePageRoute( - QRCodeDesktopPopupContent( - value: args, - ), - RouteSettings( - name: settings.name, - ), + QRCodeDesktopPopupContent(value: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2695,12 +2448,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MyTokensView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => MyTokensView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2723,23 +2472,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => TokenView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is ({String walletId, bool popPrevious})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenView( - walletId: args.walletId, - popPrevious: args.popPrevious, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenView( + walletId: args.walletId, + popPrevious: args.popPrevious, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2785,13 +2529,12 @@ class RouteGenerator { final end = Offset.zero; final curve = Curves.easeInOut; - final tween = - Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + final tween = Tween( + begin: begin, + end: end, + ).chain(CurveTween(curve: curve)); - return SlideTransition( - position: animation.drive(tween), - child: child, - ); + return SlideTransition(position: animation.drive(tween), child: child); }, ); } @@ -2835,10 +2578,7 @@ class FadePageRoute extends PageRoute { Animation animation, Animation secondaryAnimation, ) { - return FadeTransition( - opacity: animation, - child: child, - ); + return FadeTransition(opacity: animation, child: child); } @override diff --git a/lib/wallets/crypto_currency/coins/firo.dart b/lib/wallets/crypto_currency/coins/firo.dart index 26957600d..79ed783f8 100644 --- a/lib/wallets/crypto_currency/coins/firo.dart +++ b/lib/wallets/crypto_currency/coins/firo.dart @@ -236,22 +236,9 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { ); case CryptoCurrencyNetwork.test: - // NodeModel( - // host: "firo-testnet.stackwallet.com", - // port: 50002, - // name: DefaultNodes.defaultName, - // id: _nodeId(Coin.firoTestNet), - // useSSL: true, - // enabled: true, - // coinName: Coin.firoTestNet.name, - // isFailover: true, - // isDown: false, - // ); - - // TODO revert to above eventually return NodeModel( - host: "95.179.164.13", - port: 51002, + host: "firo-testnet.stackwallet.com", + port: 50002, name: DefaultNodes.defaultName, id: DefaultNodes.buildId(this), useSSL: true, diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 94474e390..13430294b 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -64,15 +64,17 @@ class TxData { final tezart.OperationsList? tezosOperationsList; // firo spark specific - final List< - ({ - String address, - Amount amount, - String memo, - bool isChange, - })>? sparkRecipients; + final List<({String address, Amount amount, String memo, bool isChange})>? + sparkRecipients; final List? sparkMints; final List? usedSparkCoins; + final ({ + String additionalInfo, + String name, + Address sparkAddress, + int validBlocks, + })? + sparkNameInfo; // xelis specific final String? otherData; @@ -122,6 +124,7 @@ class TxData { this.tempTx, this.ignoreCachedBalanceChecks = false, this.opNameState, + this.sparkNameInfo, }); Amount? get amount { @@ -201,9 +204,10 @@ class TxData { } } - int? get estimatedSatsPerVByte => fee != null && vSize != null - ? (fee!.raw ~/ BigInt.from(vSize!)).toInt() - : null; + int? get estimatedSatsPerVByte => + fee != null && vSize != null + ? (fee!.raw ~/ BigInt.from(vSize!)).toInt() + : null; TxData copyWith({ FeeRateType? feeRateType, @@ -237,19 +241,20 @@ class TxData { TransactionSubType? txSubType, List>? mintsMapLelantus, tezart.OperationsList? tezosOperationsList, - List< - ({ - String address, - Amount amount, - String memo, - bool isChange, - })>? - sparkRecipients, + List<({String address, Amount amount, String memo, bool isChange})>? + sparkRecipients, List? sparkMints, List? usedSparkCoins, TransactionV2? tempTx, bool? ignoreCachedBalanceChecks, NameOpState? opNameState, + ({ + String additionalInfo, + String name, + Address sparkAddress, + int validBlocks, + })? + sparkNameInfo, }) { return TxData( feeRateType: feeRateType ?? this.feeRateType, @@ -290,11 +295,13 @@ class TxData { ignoreCachedBalanceChecks: ignoreCachedBalanceChecks ?? this.ignoreCachedBalanceChecks, opNameState: opNameState ?? this.opNameState, + sparkNameInfo: sparkNameInfo ?? this.sparkNameInfo, ); } @override - String toString() => 'TxData{' + String toString() => + 'TxData{' 'feeRateType: $feeRateType, ' 'feeRateAmount: $feeRateAmount, ' 'satsPerVByte: $satsPerVByte, ' @@ -331,5 +338,6 @@ class TxData { 'tempTx: $tempTx, ' 'ignoreCachedBalanceChecks: $ignoreCachedBalanceChecks, ' 'opNameState: $opNameState, ' + 'sparkNameInfo: $sparkNameInfo, ' '}'; } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 102d6a753..d2d0a058c 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -26,6 +26,7 @@ import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/extensions/extensions.dart'; import '../../../utilities/logger.dart'; import '../../../utilities/prefs.dart'; +import '../../crypto_currency/crypto_currency.dart'; import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../../isar/models/spark_coin.dart'; import '../../isar/models/wallet_info.dart'; @@ -639,6 +640,26 @@ mixin SparkInterface } extractedTx.setPayload(spend.serializedSpendPayload); + + if (txData.sparkNameInfo != null) { + // this is name reg tx + + final nameScript = LibSpark.createSparkNameScript( + sparkNameValidityBlocks: txData.sparkNameInfo!.validBlocks, + name: txData.sparkNameInfo!.name, + additionalInfo: txData.sparkNameInfo!.additionalInfo, + scalarHex: extractedTx.getHash().toHex, + privateKeyHex: privateKey.toHex, + spendKeyIndex: kDefaultSparkIndex, + diversifier: txData.sparkNameInfo!.sparkAddress.derivationIndex, + isTestNet: cryptoCurrency.network != CryptoCurrencyNetwork.main, + ); + + extractedTx.setPayload( + Uint8List.fromList([...spend.serializedSpendPayload, ...nameScript]), + ); + } + final rawTxHex = extractedTx.toHex(); if (isSendAll) { @@ -1975,6 +1996,80 @@ mixin SparkInterface return txData.copyWith(sparkMints: await Future.wait(futures)); } + Future prepareSparkNameTransaction({ + required String name, + required String address, + required int years, + required String additionalInfo, + }) async { + if (years < 1 || years > kMaxNameRegistrationLengthYears) { + throw Exception("Invalid spark name registration period years: $years"); + } + + if (name.isEmpty || name.length > kMaxNameLength) { + throw Exception("Invalid spark name length: ${name.length}"); + } + if (!RegExp(kNameRegexString).hasMatch(name)) { + throw Exception("Invalid symbols found in spark name: $name"); + } + + if (additionalInfo.toUint8ListFromUtf8.length > + kMaxAdditionalInfoLengthBytes) { + throw Exception( + "Additional info exceeds $kMaxAdditionalInfoLengthBytes bytes.", + ); + } + + final sparkAddress = await mainDB.getAddress(walletId, address); + if (sparkAddress == null) { + throw Exception("Address '$address' not found in local DB."); + } + if (sparkAddress.type != AddressType.spark) { + throw Exception("Address '$address' is not a spark address."); + } + + final data = ( + name: name, + additionalInfo: additionalInfo, + validBlocks: years * 365 * 24 * 24, + sparkAddress: sparkAddress, + ); + + final String destinationAddress; + switch (cryptoCurrency.network) { + case CryptoCurrencyNetwork.main: + destinationAddress = kStage3DevelopmentFundAddressMainNet; + break; + + case CryptoCurrencyNetwork.test: + destinationAddress = kStage3DevelopmentFundAddressTestNet; + break; + + default: + throw Exception( + "Invalid network '${cryptoCurrency.network}' for spark name registration.", + ); + } + + final txData = await prepareSendSpark( + txData: TxData( + sparkNameInfo: data, + recipients: [ + ( + address: destinationAddress, + amount: Amount.fromDecimal( + Decimal.fromInt(kStandardSparkNamesFee[name.length] * years), + fractionDigits: cryptoCurrency.fractionDigits, + ), + isChange: false, + ), + ], + ), + ); + + return txData; + } + @override Future updateBalance() async { // call to super to update transparent balance (and lelantus balance if From b1111d761052bb412ed26284aed5ed7d6dde7ddd Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 3 Apr 2025 13:07:35 -0600 Subject: [PATCH 004/206] eth nonce in tx details view fix and a bunch of autoformat changes --- .../tx_v2/transaction_v2_details_view.dart | 1956 +++++++++-------- 1 file changed, 1004 insertions(+), 952 deletions(-) diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index 8f0852941..c98876f1d 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -133,43 +133,43 @@ class _TransactionV2DetailsViewState if (mounted) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: null, - maxWidth: 580, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxHeight: null, + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "Boost transaction", - style: STextStyles.desktopH3(context), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Boost transaction", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Flexible( + child: SingleChildScrollView( + child: BoostTransactionView( + transaction: _transaction, + ), ), ), - const DesktopDialogCloseButton(), ], ), - Flexible( - child: SingleChildScrollView( - child: BoostTransactionView( - transaction: _transaction, - ), - ), - ), - ], - ), - ), + ), ); } } else { unawaited( - Navigator.of(context).pushNamed( - BoostTransactionView.routeName, - arguments: _transaction, - ), + Navigator.of( + context, + ).pushNamed(BoostTransactionView.routeName, arguments: _transaction), ); } } finally { @@ -185,13 +185,15 @@ class _TransactionV2DetailsViewState final wallet = ref.read(pWallets).getWallet(walletId); - hasTxKeyProbably = wallet is LibMoneroWallet && + hasTxKeyProbably = + wallet is LibMoneroWallet && (_transaction.type == TransactionType.outgoing || _transaction.type == TransactionType.sentToSelf); if (_transaction.type case TransactionType.sentToSelf || TransactionType.outgoing) { - supportsRbf = _transaction.subType == TransactionSubType.none && + supportsRbf = + _transaction.subType == TransactionSubType.none && wallet is RbfInterface; } else { supportsRbf = false; @@ -240,81 +242,85 @@ class _TransactionV2DetailsViewState ); break; } - data = _transaction.outputs - .map( - (e) => ( - addresses: e.addresses, - amount: Amount( - rawValue: e.value, - fractionDigits: coin.fractionDigits, + data = + _transaction.outputs + .map( + (e) => ( + addresses: e.addresses, + amount: Amount( + rawValue: e.value, + fractionDigits: coin.fractionDigits, + ), + ), ) - ), - ) - .toList(); + .toList(); } else if (_transaction.subType == TransactionSubType.cashFusion) { amount = _transaction.getAmountReceivedInThisWallet( fractionDigits: fractionDigits, ); - data = _transaction.outputs - .where((e) => e.walletOwns) - .map( - (e) => ( - addresses: e.addresses, - amount: Amount( - rawValue: e.value, - fractionDigits: coin.fractionDigits, - ) - ), - ) - .toList(); - } else { - switch (_transaction.type) { - case TransactionType.outgoing: - amount = _transaction.getAmountSentFromThisWallet( - fractionDigits: fractionDigits, - ); - data = _transaction.outputs - .where((e) => !e.walletOwns) + data = + _transaction.outputs + .where((e) => e.walletOwns) .map( (e) => ( addresses: e.addresses, amount: Amount( rawValue: e.value, fractionDigits: coin.fractionDigits, - ) + ), ), ) .toList(); + } else { + switch (_transaction.type) { + case TransactionType.outgoing: + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits, + ); + data = + _transaction.outputs + .where((e) => !e.walletOwns) + .map( + (e) => ( + addresses: e.addresses, + amount: Amount( + rawValue: e.value, + fractionDigits: coin.fractionDigits, + ), + ), + ) + .toList(); break; case TransactionType.incoming: case TransactionType.sentToSelf: if (_transaction.subType == TransactionSubType.sparkMint || _transaction.subType == TransactionSubType.sparkSpend) { - _sparkMemo = ref - .read(mainDBProvider) - .isar - .sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .filter() - .memoIsNotEmpty() - .and() - .heightEqualTo(_transaction.height) - .anyOf( - _transaction.outputs - .where( - (e) => - e.walletOwns && - e.addresses.isEmpty && - e.scriptPubKeyHex.length >= 488, - ) - .map((e) => e.scriptPubKeyHex.substring(2, 488)) - .toList(), - (q, element) => q.serializedCoinB64StartsWith(element), - ) - .memoProperty() - .findFirstSync(); + _sparkMemo = + ref + .read(mainDBProvider) + .isar + .sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .filter() + .memoIsNotEmpty() + .and() + .heightEqualTo(_transaction.height) + .anyOf( + _transaction.outputs + .where( + (e) => + e.walletOwns && + e.addresses.isEmpty && + e.scriptPubKeyHex.length >= 488, + ) + .map((e) => e.scriptPubKeyHex.substring(2, 488)) + .toList(), + (q, element) => q.serializedCoinB64StartsWith(element), + ) + .memoProperty() + .findFirstSync(); } if (_transaction.subType == TransactionSubType.sparkMint) { @@ -338,36 +344,38 @@ class _TransactionV2DetailsViewState fractionDigits: fractionDigits, ); } - data = _transaction.outputs - .where((e) => e.walletOwns) - .map( - (e) => ( - addresses: e.addresses, - amount: Amount( - rawValue: e.value, - fractionDigits: coin.fractionDigits, + data = + _transaction.outputs + .where((e) => e.walletOwns) + .map( + (e) => ( + addresses: e.addresses, + amount: Amount( + rawValue: e.value, + fractionDigits: coin.fractionDigits, + ), + ), ) - ), - ) - .toList(); + .toList(); break; case TransactionType.unknown: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, ); - data = _transaction.inputs - .where((e) => e.walletOwns) - .map( - (e) => ( - addresses: e.addresses, - amount: Amount( - rawValue: e.value, - fractionDigits: coin.fractionDigits, + data = + _transaction.inputs + .where((e) => e.walletOwns) + .map( + (e) => ( + addresses: e.addresses, + amount: Amount( + rawValue: e.value, + fractionDigits: coin.fractionDigits, + ), + ), ) - ), - ) - .toList(); + .toList(); break; } } @@ -381,24 +389,29 @@ class _TransactionV2DetailsViewState } String whatIsIt(TransactionV2 tx, int height) => tx.statusLabel( - currentChainHeight: height, - minConfirms: minConfirms, - minCoinbaseConfirms: ref + currentChainHeight: height, + minConfirms: minConfirms, + minCoinbaseConfirms: + ref .read(pWallets) .getWallet(walletId) .cryptoCurrency .minCoinbaseConfirms, - ); + ); Future fetchContactNameFor(String address) async { if (address.isEmpty) { return address; } try { - final contacts = ref.read(addressBookServiceProvider).contacts.where( - (element) => element.addresses - .where((element) => element.address == address) - .isNotEmpty, + final contacts = ref + .read(addressBookServiceProvider) + .contacts + .where( + (element) => + element.addresses + .where((element) => element.address == address) + .isNotEmpty, ); if (contacts.isNotEmpty) { return contacts.first.name; @@ -406,7 +419,7 @@ class _TransactionV2DetailsViewState return address; } } catch (e, s) { - Logging.instance.w("$e\n$s", error: e, stackTrace: s,); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); return address; } } @@ -427,8 +440,9 @@ class _TransactionV2DetailsViewState builder: (_, ref, __) { return Checkbox( value: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.hideBlockExplorerWarning), + prefsChangeNotifierProvider.select( + (value) => value.hideBlockExplorerWarning, + ), ), onChanged: (value) { if (value is bool) { @@ -454,23 +468,21 @@ class _TransactionV2DetailsViewState child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), onPressed: () { Navigator.of(context).pop(true); }, - child: Text( - "Continue", - style: STextStyles.button(context), - ), + child: Text("Continue", style: STextStyles.button(context)), ), ); } else { @@ -484,10 +496,7 @@ class _TransactionV2DetailsViewState Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Attention", - style: STextStyles.desktopH2(context), - ), + Text("Attention", style: STextStyles.desktopH2(context)), Row( children: [ Consumer( @@ -531,10 +540,7 @@ class _TransactionV2DetailsViewState buttonHeight: ButtonHeight.l, label: "Cancel", onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(false); + Navigator.of(context, rootNavigator: true).pop(false); }, ), const SizedBox(width: 20), @@ -543,10 +549,7 @@ class _TransactionV2DetailsViewState buttonHeight: ButtonHeight.l, label: "Continue", onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(true); + Navigator.of(context, rootNavigator: true).pop(true); }, ), ], @@ -587,36 +590,37 @@ class _TransactionV2DetailsViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - // if (FocusScope.of(context).hasFocus) { - // FocusScope.of(context).unfocus(); - // await Future.delayed(Duration(milliseconds: 50)); - // } - Navigator.of(context).pop(); - }, - ), - title: Text( - "Transaction details", - style: STextStyles.navBarTitle(context), + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Transaction details", + style: STextStyles.navBarTitle(context), + ), ), - ), body: Padding( - padding: isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -633,21 +637,20 @@ class _TransactionV2DetailsViewState ), Flexible( child: Padding( - padding: isDesktop - ? const EdgeInsets.only( - right: 32, - bottom: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), child: ConditionalParent( condition: isDesktop, builder: (child) { return RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, padding: const EdgeInsets.all(0), child: child, ); @@ -655,34 +658,41 @@ class _TransactionV2DetailsViewState child: SingleChildScrollView( primary: isDesktop ? false : null, child: Padding( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), child: Container( - decoration: isDesktop - ? BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, + decoration: + isDesktop + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ), - ) - : null, + ) + : null, child: Padding( - padding: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -695,9 +705,7 @@ class _TransactionV2DetailsViewState currentHeight: currentHeight, coin: coin, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SelectableText( whatIsIt( _transaction, @@ -705,71 +713,51 @@ class _TransactionV2DetailsViewState ), style: STextStyles.desktopTextMedium( - context, - ), + context, + ), ), ], ), Column( - crossAxisAlignment: isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, children: [ SelectableText( "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.titleBold12( - context, - ), - ), - const SizedBox( - height: 2, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.titleBold12( + context, + ), ), + const SizedBox(height: 2), if (ref.watch( prefsChangeNotifierProvider.select( (value) => value.externalCalls, ), )) SelectableText( - "$amountPrefix${(amount.decimal * ref.watch( - priceAnd24hChangeNotifierProvider - .select( - (value) => value - .getPrice( - coin, - ) - .item1, - ), - )).toAmount(fractionDigits: 2).fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider - .select( - (value) => value.locale, + "$amountPrefix${(amount.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1))).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, ), - ), - )} ${ref.watch( - prefsChangeNotifierProvider - .select( - (value) => value.currency, - ), - )}", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), ), ], ), @@ -787,52 +775,58 @@ class _TransactionV2DetailsViewState isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Status", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall(context) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle(context), ), // Flexible( // child: FittedBox( // fit: BoxFit.scaleDown, // child: SelectableText( - whatIsIt( - _transaction, - currentHeight, - ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: _transaction.type == - TransactionType - .outgoing && - _transaction.subType != - TransactionSubType - .cashFusion - ? Theme.of(context) - .extension()! - .accentColorOrange - : Theme.of(context) - .extension()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12(context), + whatIsIt(_transaction, currentHeight), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing && + _transaction + .subType != + TransactionSubType + .cashFusion + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), ), // ), // ), @@ -847,9 +841,7 @@ class _TransactionV2DetailsViewState TransactionSubType.mint)) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (!((coin is Monero || coin is Wownero) && _transaction.type == TransactionType.outgoing) && @@ -857,9 +849,10 @@ class _TransactionV2DetailsViewState _transaction.subType == TransactionSubType.mint)) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -925,19 +918,17 @@ class _TransactionV2DetailsViewState }, child: Text( outputLabel, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -952,11 +943,13 @@ class _TransactionV2DetailsViewState builder: ( builderContext, AsyncSnapshot - snapshot, + snapshot, ) { String - addressOrContactName = - data.first.addresses + addressOrContactName = + data + .first + .addresses .first; if (snapshot.connectionState == ConnectionState @@ -967,92 +960,95 @@ class _TransactionV2DetailsViewState } return SelectableText( addressOrContactName, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, ) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + : STextStyles.itemSubtitle12( + context, + ), ); }, ) else - for (int i = 0; - i < data.length; - i++) + for ( + int i = 0; + i < data.length; + i++ + ) ConditionalParent( condition: i > 0, - builder: (child) => Column( - crossAxisAlignment: - CrossAxisAlignment - .stretch, - children: [ - const _Divider(), - child, - ], - ), + builder: + (child) => Column( + crossAxisAlignment: + CrossAxisAlignment + .stretch, + children: [ + const _Divider(), + child, + ], + ), child: Padding( padding: const EdgeInsets.all( - 8.0, - ), + 8.0, + ), child: Column( crossAxisAlignment: CrossAxisAlignment .start, children: [ - ...data[i] - .addresses - .map( - (e) { - return FutureBuilder( - future: - fetchContactNameFor( - e, - ), - builder: ( - builderContext, - AsyncSnapshot< - String> - snapshot, - ) { - final String - addressOrContactName; - if (snapshot.connectionState == - ConnectionState - .done && + ...data[i].addresses.map(( + e, + ) { + return FutureBuilder( + future: + fetchContactNameFor( + e, + ), + builder: ( + builderContext, + AsyncSnapshot< + String + > + snapshot, + ) { + final String + addressOrContactName; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot + .hasData) { + addressOrContactName = snapshot - .hasData) { - addressOrContactName = - snapshot - .data!; - } else { - addressOrContactName = - e; - } - - return OutputCard( - address: - addressOrContactName, - amount: data[ - i] - .amount, - coin: coin, - ); - }, - ); - }, - ), + .data!; + } else { + addressOrContactName = + e; + } + + return OutputCard( + address: + addressOrContactName, + amount: + data[i] + .amount, + coin: coin, + ); + }, + ); + }), ], ), ), @@ -1072,14 +1068,13 @@ class _TransactionV2DetailsViewState if (coin is Epiccash) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is Epiccash) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1092,33 +1087,33 @@ class _TransactionV2DetailsViewState children: [ Text( "On chain note", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox( - height: 8, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), + const SizedBox(height: 8), SelectableText( _transaction.onChainNote ?? "", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1132,13 +1127,12 @@ class _TransactionV2DetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -1150,94 +1144,96 @@ class _TransactionV2DetailsViewState (coin is Epiccash) ? "Local Note" : "Note ", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), isDesktop ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, - ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension< - StackColors>()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.link2( - context, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, ), - ], - ), + ), + ], ), + ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SelectableText( ref .watch( - pTransactionNote( - ( - txid: (coin is Epiccash) - ? _transaction.slateId - .toString() - : _transaction.txid, - walletId: walletId - ), - ), + pTransactionNote(( + txid: + (coin is Epiccash) + ? _transaction.slateId + .toString() + : _transaction.txid, + walletId: walletId, + )), ) ?.value ?? "", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1245,14 +1241,13 @@ class _TransactionV2DetailsViewState if (_sparkMemo != null) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (_sparkMemo != null) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -1260,45 +1255,47 @@ class _TransactionV2DetailsViewState children: [ Text( "Memo", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SelectableText( _sparkMemo!, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1310,34 +1307,36 @@ class _TransactionV2DetailsViewState children: [ Text( "Date", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 2, - ), + if (isDesktop) const SizedBox(height: 2), if (isDesktop) SelectableText( Format.extractDateFrom( _transaction.timestamp, ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1346,16 +1345,21 @@ class _TransactionV2DetailsViewState Format.extractDateFrom( _transaction.timestamp, ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton( @@ -1367,39 +1371,39 @@ class _TransactionV2DetailsViewState ), ), if (coin is! NanoCurrency && - !(coin is Xelis && _transaction.type == TransactionType.incoming) - ) + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is! NanoCurrency && - !(coin is Xelis && _transaction.type == TransactionType.incoming) - ) + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Builder( builder: (context) { - final String feeString = showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms, - ) - ? ref - .watch(pAmountFormatter(coin)) - .format( - fee, + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, ) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format( - fee, - ); + ? ref + .watch( + pAmountFormatter(coin), + ) + .format(fee) + : "Pending" + : ref + .watch(pAmountFormatter(coin)) + .format(fee); return Row( mainAxisAlignment: @@ -1413,41 +1417,38 @@ class _TransactionV2DetailsViewState children: [ Text( "Transaction fee", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( feeString, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (supportsRbf && !confirmedTxn) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (supportsRbf && !confirmedTxn) CustomTextButton( text: "Boost transaction", @@ -1458,19 +1459,21 @@ class _TransactionV2DetailsViewState if (!isDesktop) SelectableText( feeString, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: feeString), @@ -1481,9 +1484,7 @@ class _TransactionV2DetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), Builder( builder: (context) { final String height; @@ -1494,10 +1495,11 @@ class _TransactionV2DetailsViewState if (widget.coin is Bitcoincash || widget.coin is Ecash) { - height = _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; confirmations = confirms.toString(); } else if (widget.coin is Epiccash && _transaction.slateId == null) { @@ -1505,16 +1507,18 @@ class _TransactionV2DetailsViewState height = "Unknown"; } else { final confirmed = _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms); + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, + ); if (widget.coin is! Epiccash && confirmed) { height = "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; } else { - height = confirms > 0 - ? "${_transaction.height}" - : "Pending"; + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; } confirmations = confirms.toString(); @@ -1523,9 +1527,10 @@ class _TransactionV2DetailsViewState return Column( children: [ RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1538,56 +1543,58 @@ class _TransactionV2DetailsViewState children: [ Text( "Block height", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( height, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), if (!isDesktop) SelectableText( height, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: height), @@ -1596,13 +1603,12 @@ class _TransactionV2DetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1615,56 +1621,58 @@ class _TransactionV2DetailsViewState children: [ Text( "Confirmations", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( confirmations, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), if (!isDesktop) SelectableText( confirmations, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: height), @@ -1675,18 +1683,65 @@ class _TransactionV2DetailsViewState ); }, ), - - if (kDebugMode) + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) isDesktop ? const _Divider() - : const SizedBox( - height: 12, + : const SizedBox(height: 12), + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Nonce", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), + SelectableText( + _transaction.nonce.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (kDebugMode) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), if (kDebugMode) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1694,25 +1749,32 @@ class _TransactionV2DetailsViewState children: [ Text( "Tx sub type", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), SelectableText( _transaction.subType.toString(), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1720,9 +1782,7 @@ class _TransactionV2DetailsViewState if (hasTxKeyProbably) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (hasTxKeyProbably) TxKeyWidget( walletId: walletId, @@ -1730,13 +1790,12 @@ class _TransactionV2DetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1749,61 +1808,61 @@ class _TransactionV2DetailsViewState children: [ ConditionalParent( condition: !isDesktop, - builder: (child) => Row( - children: [ - Expanded(child: child), - SimpleCopyButton( - data: _transaction.txid, + builder: + (child) => Row( + children: [ + Expanded(child: child), + SimpleCopyButton( + data: _transaction.txid, + ), + ], ), - ], - ), child: Text( "Transaction ID", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), // Flexible( // child: FittedBox( // fit: BoxFit.scaleDown, // child: SelectableText( _transaction.txid, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (coin is! Epiccash) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is! Epiccash) CustomTextButton( text: "Open in block explorer", onTap: () async { final uri = getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); + coin: coin, + txid: _transaction.txid, + ); if (ref .read( @@ -1813,8 +1872,8 @@ class _TransactionV2DetailsViewState false) { final shouldContinue = await showExplorerWarning( - "${uri.scheme}://${uri.host}", - ); + "${uri.scheme}://${uri.host}", + ); if (!shouldContinue) { return; @@ -1829,21 +1888,22 @@ class _TransactionV2DetailsViewState try { await launchUrl( uri, - mode: LaunchMode - .externalApplication, + mode: + LaunchMode + .externalApplication, ); } catch (_) { if (mounted) { unawaited( showDialog( context: context, - builder: (_) => - StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), + builder: + (_) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), ), ); } @@ -1864,14 +1924,9 @@ class _TransactionV2DetailsViewState ], ), ), + if (isDesktop) const SizedBox(width: 12), if (isDesktop) - const SizedBox( - width: 12, - ), - if (isDesktop) - IconCopyButton( - data: _transaction.txid, - ), + IconCopyButton(data: _transaction.txid), ], ), ), @@ -1955,14 +2010,13 @@ class _TransactionV2DetailsViewState if (coin is Epiccash) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is Epiccash) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1974,14 +2028,14 @@ class _TransactionV2DetailsViewState children: [ Text( "Slate ID", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), // Flexible( // child: FittedBox( @@ -1989,27 +2043,27 @@ class _TransactionV2DetailsViewState // child: SelectableText( _transaction.slateId ?? "Unknown", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), // ), // ), ], ), - if (isDesktop) - const SizedBox( - width: 12, - ), + if (isDesktop) const SizedBox(width: 12), if (isDesktop) IconCopyButton( data: _transaction.slateId ?? "Unknown", @@ -2017,10 +2071,7 @@ class _TransactionV2DetailsViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), // if (whatIsIt( // _transaction, // currentHeight, @@ -2042,101 +2093,106 @@ class _TransactionV2DetailsViewState ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, - floatingActionButton: (coin is Epiccash && - _transaction.getConfirmations(currentHeight) < 1 && - _transaction.isCancelled == false) - ? ConditionalParent( - condition: isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - vertical: 16, - ), - child: child, - ), - child: SizedBox( - width: MediaQuery.of(context).size.width - 32, - child: TextButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - Theme.of(context).extension()!.textError, + floatingActionButton: + (coin is Epiccash && + _transaction.getConfirmations(currentHeight) < 1 && + _transaction.isCancelled == false) + ? ConditionalParent( + condition: isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 16, + ), + child: child, ), - ), - onPressed: () async { - final wallet = ref.read(pWallets).getWallet(walletId); + child: SizedBox( + width: MediaQuery.of(context).size.width - 32, + child: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Theme.of(context).extension()!.textError, + ), + ), + onPressed: () async { + final wallet = ref.read(pWallets).getWallet(walletId); + + if (wallet is EpiccashWallet) { + final String? id = _transaction.slateId; + if (id == null) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Could not find Epic transaction ID", + context: context, + ), + ); + return; + } - if (wallet is EpiccashWallet) { - final String? id = _transaction.slateId; - if (id == null) { unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Could not find Epic transaction ID", + showDialog( + barrierDismissible: false, context: context, + builder: + (_) => + const CancellingTransactionProgressDialog(), ), ); - return; - } - unawaited( - showDialog( - barrierDismissible: false, - context: context, - builder: (_) => - const CancellingTransactionProgressDialog(), - ), - ); - - final result = - await wallet.cancelPendingTransactionAndPost(id); - if (mounted) { - // pop progress dialog - Navigator.of(context).pop(); - - if (result.isEmpty) { - await showDialog( - context: context, - builder: (_) => StackOkDialog( - title: "Transaction cancelled", - onOkPressed: (_) { - wallet.refresh(); - Navigator.of(context).popUntil( - ModalRoute.withName( - WalletView.routeName, + final result = await wallet + .cancelPendingTransactionAndPost(id); + if (mounted) { + // pop progress dialog + Navigator.of(context).pop(); + + if (result.isEmpty) { + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Transaction cancelled", + onOkPressed: (_) { + wallet.refresh(); + Navigator.of(context).popUntil( + ModalRoute.withName( + WalletView.routeName, + ), + ); + }, ), - ); - }, - ), - ); - } else { - await showDialog( - context: context, - builder: (_) => StackOkDialog( - title: "Failed to cancel transaction", - message: result, - ), - ); + ); + } else { + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Failed to cancel transaction", + message: result, + ), + ); + } } + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "ERROR: Wallet type is not Epic Cash", + context: context, + ), + ); + return; } - } else { - unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "ERROR: Wallet type is not Epic Cash", - context: context, - ), - ); - return; - } - }, - child: Text( - "Cancel Transaction", - style: STextStyles.button(context), + }, + child: Text( + "Cancel Transaction", + style: STextStyles.button(context), + ), ), ), - ), - ) - : null, + ) + : null, ), ); } @@ -2161,38 +2217,44 @@ class OutputCard extends ConsumerWidget { children: [ Text( "Address", - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.itemSubtitle(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.itemSubtitle(context), ), SelectableText( address, - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context).extension()!.textDark, - ) - : STextStyles.itemSubtitle12(context), - ), - const SizedBox( - height: 10, + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( + color: Theme.of(context).extension()!.textDark, + ) + : STextStyles.itemSubtitle12(context), ), + const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Amount", - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.itemSubtitle(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.itemSubtitle(context), ), SelectableText( ref.watch(pAmountFormatter(coin)).format(amount), - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ) + : STextStyles.itemSubtitle12(context), ), ], ), @@ -2214,10 +2276,7 @@ class _Divider extends StatelessWidget { } class IconCopyButton extends StatelessWidget { - const IconCopyButton({ - super.key, - required this.data, - }); + const IconCopyButton({super.key, required this.data}); final String data; @@ -2231,9 +2290,7 @@ class IconCopyButton extends StatelessWidget { Theme.of(context).extension()!.buttonBackSecondary, elevation: 0, hoverElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), onPressed: () async { await Clipboard.setData(ClipboardData(text: data)); if (context.mounted) { @@ -2260,10 +2317,7 @@ class IconCopyButton extends StatelessWidget { } class IconPencilButton extends StatelessWidget { - const IconPencilButton({ - super.key, - this.onPressed, - }); + const IconPencilButton({super.key, this.onPressed}); final VoidCallback? onPressed; @@ -2277,9 +2331,7 @@ class IconPencilButton extends StatelessWidget { Theme.of(context).extension()!.buttonBackSecondary, elevation: 0, hoverElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), onPressed: () => onPressed?.call(), child: Padding( padding: const EdgeInsets.all(5), From 637fb66233fa050c1376c7b94ea4288ec77b038b Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 3 Apr 2025 18:22:22 -0600 Subject: [PATCH 005/206] don't display fist price if fetch failed --- .../confirm_change_now_send.dart | 635 +++---- .../confirm_name_transaction_view.dart | 660 +++---- .../send_view/confirm_transaction_view.dart | 874 +++++---- lib/pages/send_view/send_view.dart | 1446 ++++++++------- lib/pages/send_view/token_send_view.dart | 572 +++--- .../sub_widgets/my_token_select_item.dart | 168 +- .../token_view/sub_widgets/token_summary.dart | 222 +-- .../sub_widgets/wallet_summary_info.dart | 95 +- .../all_transactions_view.dart | 619 +++---- .../transaction_details_view.dart | 1620 +++++++++-------- .../tx_v2/all_transactions_v2_view.dart | 621 +++---- .../tx_v2/transaction_v2_card.dart | 131 +- .../tx_v2/transaction_v2_details_view.dart | 68 +- .../sub_widgets/favorite_card.dart | 209 +-- .../sub_widgets/wallet_list_item.dart | 112 +- .../paynym/desktop_paynym_send_dialog.dart | 73 +- .../my_stack_view/wallet_summary_table.dart | 160 +- .../wallet_view/sub_widgets/desktop_send.dart | 1026 +++++------ .../sub_widgets/desktop_token_send.dart | 522 +++--- .../sub_widgets/desktop_wallet_summary.dart | 6 +- .../firo_desktop_wallet_summary.dart | 14 +- lib/services/price.dart | 107 +- lib/services/price_service.dart | 26 +- lib/widgets/transaction_card.dart | 111 +- .../transaction_card_test.mocks.dart | 739 ++++---- 25 files changed, 5185 insertions(+), 5651 deletions(-) diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index 999fca764..6b118a438 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -98,11 +98,7 @@ class _ConfirmChangeNowSendViewState ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); late String txid; Future txidFuture; @@ -118,10 +114,7 @@ class _ConfirmChangeNowSendViewState unawaited(wallet.refresh()); - final results = await Future.wait([ - txidFuture, - time, - ]); + final results = await Future.wait([txidFuture, time]); sendProgressController.triggerSuccess?.call(); await Future.delayed(const Duration(seconds: 5)); @@ -129,15 +122,15 @@ class _ConfirmChangeNowSendViewState txid = (results.first as TxData).txid!; // save note - await ref.read(mainDBProvider).putTransactionNote( - TransactionNote( - walletId: walletId, - txid: txid, - value: note, - ), + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), ); - await ref.read(tradeSentFromStackLookupProvider).save( + await ref + .read(tradeSentFromStackLookupProvider) + .save( tradeWalletLookup: TradeWalletLookup( uuid: const Uuid().v1(), txid: txid, @@ -162,7 +155,11 @@ class _ConfirmChangeNowSendViewState Navigator.of(context).popUntil(ModalRoute.withName(routeOnSuccessName)); } } catch (e, s) { - Logging.instance.e("Broadcast transaction failed: ", error: e, stackTrace: s); + Logging.instance.e( + "Broadcast transaction failed: ", + error: e, + stackTrace: s, + ); // pop sending dialog Navigator.of(context).pop(); @@ -182,9 +179,10 @@ class _ConfirmChangeNowSendViewState child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), ), onPressed: () { @@ -205,46 +203,44 @@ class _ConfirmChangeNowSendViewState if (Util.isDesktop) { unlocked = await showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - DesktopDialogCloseButton(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: DesktopAuthSend( - coin: coin, - ), - ), - ], - ), - ), + ), ); } else { unlocked = await Navigator.push( context, RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - popOnSuccess: true, - routeOnSuccessArguments: true, - routeOnSuccess: "", - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: "Authenticate to send transaction", - biometricsAuthenticationTitle: "Confirm Transaction", - ), + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: "Authenticate to send transaction", + biometricsAuthenticationTitle: "Confirm Transaction", + ), settings: const RouteSettings(name: "/confirmsendlockscreen"), ), ); @@ -292,11 +288,7 @@ class _ConfirmChangeNowSendViewState body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -318,205 +310,195 @@ class _ConfirmChangeNowSendViewState }, child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxHeight: double.infinity, - maxWidth: 580, - child: Column( - children: [ - Row( + builder: + (child) => DesktopDialog( + maxHeight: double.infinity, + maxWidth: 580, + child: Column( children: [ - const SizedBox( - width: 6, - ), - const AppBarBackButton( - isCompact: true, - iconSize: 23, - ), - const SizedBox( - width: 12, - ), - Text( - "Confirm ${ref.watch(pWalletCoin(walletId)).ticker} transaction", - style: STextStyles.desktopH3(context), + Row( + children: [ + const SizedBox(width: 6), + const AppBarBackButton(isCompact: true, iconSize: 23), + const SizedBox(width: 12), + Text( + "Confirm ${ref.watch(pWalletCoin(walletId)).ticker} transaction", + style: STextStyles.desktopH3(context), + ), + ], ), - ], - ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Column( - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - borderColor: Theme.of(context) - .extension()! - .background, - child: child, - ), - const SizedBox( - height: 16, + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, ), - Row( + child: Column( children: [ - Text( - "Transaction fee", - style: - STextStyles.desktopTextExtraExtraSmall(context), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: child, ), - ], - ), - const SizedBox( - height: 10, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - ref - .watch( - pAmountFormatter( - ref.watch(pWalletCoin(walletId)), - ), - ) - .format(widget.txData.fee!), - style: - STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - ], - ), - ), - const SizedBox( - height: 16, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Total amount", - style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + const SizedBox(height: 16), + Row( + children: [ + Text( + "Transaction fee", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), - ), - Builder( - builder: (context) { - final coin = ref.read(pWalletCoin(walletId)); - final fee = widget.txData.fee!; - final amount = widget.txData.amountWithoutChange!; - final total = amount + fee; - - return Text( - ref.watch(pAmountFormatter(coin)).format(total), - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + ], + ), + const SizedBox(height: 10), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + ref + .watch( + pAmountFormatter( + ref.watch(pWalletCoin(walletId)), + ), + ) + .format(widget.txData.fee!), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), - textAlign: TextAlign.right, - ); - }, - ), - ], - ), - ), - const SizedBox( - height: 16, - ), - Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: ButtonHeight.l, - onPressed: Navigator.of(context).pop, + ), + ], ), ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Send", - buttonHeight: isDesktop ? ButtonHeight.l : null, - onPressed: _confirmSend, + const SizedBox(height: 16), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Total amount", + style: STextStyles.titleBold12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + ), + Builder( + builder: (context) { + final coin = ref.read(pWalletCoin(walletId)); + final fee = widget.txData.fee!; + final amount = + widget.txData.amountWithoutChange!; + final total = amount + fee; + + return Text( + ref + .watch(pAmountFormatter(coin)) + .format(total), + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + textAlign: TextAlign.right, + ); + }, + ), + ], ), ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: Navigator.of(context).pop, + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Send", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: _confirmSend, + ), + ), + ], + ), ], ), - ], - ), + ), + ], ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Container( - decoration: BoxDecoration( - color: Theme.of(context).extension()!.background, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, + builder: + (child) => Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.background, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Row(children: [child]), ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - child, - ], - ), - ), - ), child: Text( "Send ${ref.watch(pWalletCoin(walletId)).ticker}", - style: isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.pageTitleH1(context), + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.pageTitleH1(context), ), ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Send from", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Send from", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( ref.watch(pWalletName(walletId)), style: STextStyles.itemSubtitle12(context), @@ -526,13 +508,10 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -541,9 +520,7 @@ class _ConfirmChangeNowSendViewState "${trade.exchangeName} address", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( widget.txData.recipients!.first.address, style: STextStyles.itemSubtitle12(context), @@ -553,68 +530,72 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - ), + Text("Amount", style: STextStyles.smallMed12(context)), ConditionalParent( condition: isDesktop, - builder: (child) => Row( - children: [ - child, - Builder( - builder: (context) { - final coin = ref.watch(pWalletCoin(walletId)); - final price = ref.watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin)), - ); - final amountWithoutChange = - widget.txData.amountWithoutChange!; - final value = - (price.item1 * amountWithoutChange.decimal) - .toAmount(fractionDigits: 2); - final currency = ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), - ); - final locale = ref.watch( - localeServiceChangeNotifierProvider.select( - (value) => value.locale, - ), - ); - - return Text( - " | ${value.fiatString(locale: locale)} $currency", - style: STextStyles.desktopTextExtraExtraSmall( - context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - ); - }, + builder: + (child) => Row( + children: [ + child, + Builder( + builder: (context) { + final coin = ref.watch(pWalletCoin(walletId)); + final price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ); + final String extra; + if (price == null) { + extra = ""; + } else { + final amountWithoutChange = + widget.txData.amountWithoutChange!; + final value = (price.value * + amountWithoutChange.decimal) + .toAmount(fractionDigits: 2); + final currency = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), + ); + final locale = ref.watch( + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), + ); + + extra = + " | ${value.fiatString(locale: locale)} $currency"; + } + + return Text( + extra, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle2, + ), + ); + }, + ), + ], ), - ], - ), child: Text( ref .watch( - pAmountFormatter( - ref.watch(pWalletCoin(walletId)), - ), + pAmountFormatter(ref.watch(pWalletCoin(walletId))), ) .format((widget.txData.amountWithoutChange!)), style: STextStyles.itemSubtitle12(context), @@ -626,13 +607,10 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -646,9 +624,7 @@ class _ConfirmChangeNowSendViewState .watch( pAmountFormatter(ref.read(pWalletCoin(walletId))), ) - .format( - widget.txData.fee!, - ), + .format(widget.txData.fee!), style: STextStyles.itemSubtitle12(context), textAlign: TextAlign.right, ), @@ -657,24 +633,16 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Note", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Note", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( widget.txData.note ?? "", style: STextStyles.itemSubtitle12(context), @@ -684,21 +652,15 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Trade ID", - style: STextStyles.smallMed12(context), - ), + Text("Trade ID", style: STextStyles.smallMed12(context)), Text( trade.tradeId, style: STextStyles.itemSubtitle12(context), @@ -707,24 +669,23 @@ class _ConfirmChangeNowSendViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), if (!isDesktop) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Total amount", style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + color: + Theme.of( + context, + ).extension()!.textConfirmTotalAmount, ), ), Builder( @@ -737,9 +698,10 @@ class _ConfirmChangeNowSendViewState return Text( ref.watch(pAmountFormatter(coin)).format(total), style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, ), textAlign: TextAlign.right, ); @@ -748,10 +710,7 @@ class _ConfirmChangeNowSendViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), if (!isDesktop) const Spacer(), if (!isDesktop) PrimaryButton( diff --git a/lib/pages/namecoin_names/confirm_name_transaction_view.dart b/lib/pages/namecoin_names/confirm_name_transaction_view.dart index ec0fc926a..61e8646ab 100644 --- a/lib/pages/namecoin_names/confirm_name_transaction_view.dart +++ b/lib/pages/namecoin_names/confirm_name_transaction_view.dart @@ -96,11 +96,7 @@ class _ConfirmNameTransactionViewState ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); final List txids = []; Future txDataFuture; @@ -111,10 +107,7 @@ class _ConfirmNameTransactionViewState txDataFuture = wallet.confirmSend(txData: widget.txData); // await futures in parallel - final futureResults = await Future.wait([ - txDataFuture, - time, - ]); + final futureResults = await Future.wait([txDataFuture, time]); final txData = (futureResults.first as TxData); @@ -126,7 +119,9 @@ class _ConfirmNameTransactionViewState Future.delayed(const Duration(seconds: 5)), // associated name data for reg tx - ref.read(secureStoreProvider).write( + ref + .read(secureStoreProvider) + .write( key: nameSaltKeyBuilder( txData.txid!, walletId, @@ -145,12 +140,10 @@ class _ConfirmNameTransactionViewState // save note for (final txid in txids) { - await ref.read(mainDBProvider).putTransactionNote( - TransactionNote( - walletId: walletId, - txid: txid, - value: note, - ), + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), ); } @@ -192,13 +185,8 @@ class _ConfirmNameTransactionViewState mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - niceError, - style: STextStyles.desktopH3(context), - ), - const SizedBox( - height: 24, - ), + Text(niceError, style: STextStyles.desktopH3(context)), + const SizedBox(height: 24), Flexible( child: SingleChildScrollView( child: SelectableText( @@ -207,9 +195,7 @@ class _ConfirmNameTransactionViewState ), ), ), - const SizedBox( - height: 56, - ), + const SizedBox(height: 56), Row( children: [ const Spacer(), @@ -237,9 +223,10 @@ class _ConfirmNameTransactionViewState child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -284,82 +271,79 @@ class _ConfirmNameTransactionViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - // if (FocusScope.of(context).hasFocus) { - // FocusScope.of(context).unfocus(); - // await Future.delayed(Duration(milliseconds: 50)); - // } - Navigator.of(context).pop(); - }, - ), - title: Text( - "Confirm transaction", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Confirm transaction", + style: STextStyles.navBarTitle(context), ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, + ), + body: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.min, - children: [ - Row( + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, children: [ - AppBarBackButton( - size: 40, - iconSize: 24, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(), - ), - Text( - "Confirm transaction", - style: STextStyles.desktopH3(context), + Row( + children: [ + AppBarBackButton( + size: 40, + iconSize: 24, + onPressed: + () => + Navigator.of(context, rootNavigator: true).pop(), + ), + Text( + "Confirm transaction", + style: STextStyles.desktopH3(context), + ), + ], ), + Flexible(child: SingleChildScrollView(child: child)), ], ), - Flexible( - child: SingleChildScrollView( - child: child, - ), - ), - ], - ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, @@ -372,20 +356,13 @@ class _ConfirmNameTransactionViewState "Confirm Name transaction", style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Name", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Name", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( widget.txData.opNameState!.name, style: STextStyles.itemSubtitle12(context), @@ -393,20 +370,13 @@ class _ConfirmNameTransactionViewState ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Value", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Value", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( widget.txData.opNameState!.value, style: STextStyles.itemSubtitle12(context), @@ -414,9 +384,7 @@ class _ConfirmNameTransactionViewState ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -425,9 +393,7 @@ class _ConfirmNameTransactionViewState "Recipient", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( widget.txData.recipients!.first.address, style: STextStyles.itemSubtitle12(context), @@ -435,30 +401,23 @@ class _ConfirmNameTransactionViewState ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - ), + Text("Amount", style: STextStyles.smallMed12(context)), SelectableText( - ref.watch(pAmountFormatter(coin)).format( - amountWithoutChange, - ), + ref + .watch(pAmountFormatter(coin)) + .format(amountWithoutChange), style: STextStyles.itemSubtitle12(context), textAlign: TextAlign.right, ), ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -476,9 +435,7 @@ class _ConfirmNameTransactionViewState ), ), if (widget.txData.fee != null && widget.txData.vSize != null) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.fee != null && widget.txData.vSize != null) RoundedWhiteContainer( child: Row( @@ -488,9 +445,7 @@ class _ConfirmNameTransactionViewState "sats/vByte", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( "~${fee.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle12(context), @@ -500,22 +455,15 @@ class _ConfirmNameTransactionViewState ), if (widget.txData.note != null && widget.txData.note!.isNotEmpty) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.note != null && widget.txData.note!.isNotEmpty) RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Note", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Note", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), SelectableText( widget.txData.note!, style: STextStyles.itemSubtitle12(context), @@ -543,9 +491,10 @@ class _ConfirmNameTransactionViewState children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, borderRadius: BorderRadius.only( topLeft: Radius.circular( Constants.size.circularBorderRadius, @@ -573,9 +522,7 @@ class _ConfirmNameTransactionViewState width: 32, height: 32, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Text( "Send $unit Name transaction", style: STextStyles.desktopTextMedium(context), @@ -596,17 +543,16 @@ class _ConfirmNameTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( widget.txData.opNameState!.name, style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -614,9 +560,10 @@ class _ConfirmNameTransactionViewState ), Container( height: 1, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ), Padding( padding: const EdgeInsets.all(12), @@ -630,17 +577,16 @@ class _ConfirmNameTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( widget.txData.opNameState!.value, style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -652,27 +598,24 @@ class _ConfirmNameTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(left: 32, right: 32), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ SelectableText( "Note (optional)", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -684,11 +627,13 @@ class _ConfirmNameTransactionViewState enableSuggestions: isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), onChanged: (_) => setState(() {}), @@ -704,41 +649,37 @@ class _ConfirmNameTransactionViewState bottom: 12, right: 5, ), - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState( - () => noteController.text = "", - ); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState( + () => noteController.text = "", + ); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ], ), ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 16, - left: 32, - ), + padding: const EdgeInsets.only(top: 16, left: 32), child: Text( "Amount", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -746,19 +687,16 @@ class _ConfirmNameTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: Builder( builder: (context) { final externalCalls = ref.watch( @@ -769,21 +707,21 @@ class _ConfirmNameTransactionViewState String fiatAmount = "N/A"; if (externalCalls) { - final price = ref - .read( - priceAnd24hChangeNotifierProvider, - ) - .getPrice(coin) - .item1; - if (price > Decimal.zero) { + final price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getPrice(coin) + ?.value; + if (price != null && price > Decimal.zero) { fiatAmount = (amountWithoutChange.decimal * price) .toAmount(fractionDigits: 2) .fiatString( - locale: ref - .read( - localeServiceChangeNotifierProvider, - ) - .locale, + locale: + ref + .read( + localeServiceChangeNotifierProvider, + ) + .locale, ); } } @@ -791,30 +729,20 @@ class _ConfirmNameTransactionViewState return Row( children: [ SelectableText( - ref.watch(pAmountFormatter(coin)).format( - amountWithoutChange, - ), - style: STextStyles.itemSubtitle( - context, - ), + ref + .watch(pAmountFormatter(coin)) + .format(amountWithoutChange), + style: STextStyles.itemSubtitle(context), ), if (externalCalls) Text( " | ", - style: STextStyles.itemSubtitle( - context, - ), + style: STextStyles.itemSubtitle(context), ), if (externalCalls) SelectableText( - "~$fiatAmount ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - )}", - style: STextStyles.itemSubtitle( - context, - ), + "~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.itemSubtitle(context), ), ], ); @@ -824,10 +752,7 @@ class _ConfirmNameTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 16, - left: 32, - ), + padding: const EdgeInsets.only(top: 16, left: 32), child: Text( "Recipient", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -835,19 +760,16 @@ class _ConfirmNameTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( widget.txData.recipients!.first.address, style: STextStyles.itemSubtitle(context), @@ -857,10 +779,7 @@ class _ConfirmNameTransactionViewState // todo amoutn here if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 16, - left: 32, - ), + padding: const EdgeInsets.only(top: 16, left: 32), child: Text( "Transaction fee", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -868,19 +787,16 @@ class _ConfirmNameTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( ref.watch(pAmountFormatter(coin)).format(fee!), style: STextStyles.itemSubtitle(context), @@ -891,10 +807,7 @@ class _ConfirmNameTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - top: 16, - left: 32, - ), + padding: const EdgeInsets.only(top: 16, left: 32), child: Text( "sats/vByte", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -904,19 +817,16 @@ class _ConfirmNameTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle(context), @@ -924,74 +834,78 @@ class _ConfirmNameTransactionViewState ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 23 : 12, - ), + SizedBox(height: isDesktop ? 23 : 12), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: RoundedContainer( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 16, - vertical: 18, - ) - : const EdgeInsets.all(12), - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, + padding: + isDesktop + ? const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ) + : const EdgeInsets.all(12), + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( isDesktop ? "Total amount to send" : "Total amount", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.titleBold12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), ), SelectableText( ref .watch(pAmountFormatter(coin)) .format(amountWithoutChange + fee!), - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), textAlign: TextAlign.right, ), ], ), ), ), - SizedBox( - height: isDesktop ? 28 : 16, - ), + SizedBox(height: isDesktop ? 28 : 16), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: PrimaryButton( label: "Send", buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -1001,31 +915,28 @@ class _ConfirmNameTransactionViewState if (isDesktop) { unlocked = await showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - DesktopDialogCloseButton(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: DesktopAuthSend( - coin: coin, - ), - ), - ], - ), - ), + ), ); } else { unlocked = await Navigator.push( @@ -1033,18 +944,21 @@ class _ConfirmNameTransactionViewState RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - popOnSuccess: true, - routeOnSuccessArguments: true, - routeOnSuccess: "", - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to send transaction", - biometricsAuthenticationTitle: "Confirm Transaction", + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: + "Confirm Transaction", + ), + settings: const RouteSettings( + name: "/confirmsendlockscreen", ), - settings: - const RouteSettings(name: "/confirmsendlockscreen"), ), ); } @@ -1057,9 +971,10 @@ class _ConfirmNameTransactionViewState unawaited( showFloatingFlushBar( type: FlushBarType.warning, - message: Util.isDesktop - ? "Invalid passphrase" - : "Invalid PIN", + message: + Util.isDesktop + ? "Invalid passphrase" + : "Invalid PIN", context: context, ), ); @@ -1069,10 +984,7 @@ class _ConfirmNameTransactionViewState }, ), ), - if (isDesktop) - const SizedBox( - height: 32, - ), + if (isDesktop) const SizedBox(height: 32), ], ), ), diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 5090645e3..33f07dbd5 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -118,11 +118,7 @@ class _ConfirmTransactionViewState ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); final List txids = []; Future txDataFuture; @@ -131,11 +127,13 @@ class _ConfirmTransactionViewState try { if (widget.isTokenTx) { - txDataFuture = - ref.read(pCurrentTokenWallet)!.confirmSend(txData: widget.txData); + txDataFuture = ref + .read(pCurrentTokenWallet)! + .confirmSend(txData: widget.txData); } else if (widget.isPaynymNotificationTransaction) { - txDataFuture = (wallet as PaynymInterface) - .broadcastNotificationTx(txData: widget.txData); + txDataFuture = (wallet as PaynymInterface).broadcastNotificationTx( + txData: widget.txData, + ); } else if (widget.isPaynymTransaction) { txDataFuture = wallet.confirmSend(txData: widget.txData); } else { @@ -145,8 +143,9 @@ class _ConfirmTransactionViewState if (widget.txData.sparkMints == null) { txDataFuture = wallet.confirmSend(txData: widget.txData); } else { - txDataFuture = - wallet.confirmSparkMintTransactions(txData: widget.txData); + txDataFuture = wallet.confirmSparkMintTransactions( + txData: widget.txData, + ); } break; @@ -171,10 +170,7 @@ class _ConfirmTransactionViewState } } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); sendProgressController.triggerSuccess?.call(); await Future.delayed(const Duration(seconds: 5)); @@ -189,12 +185,10 @@ class _ConfirmTransactionViewState // save note for (final txid in txids) { - await ref.read(mainDBProvider).putTransactionNote( - TransactionNote( - walletId: walletId, - txid: txid, - value: note, - ), + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), ); } @@ -207,16 +201,17 @@ class _ConfirmTransactionViewState widget.onSuccess.call(); // pop back to wallet - if (mounted) { + if (context.mounted) { if (widget.onSuccessInsteadOfRouteOnSuccess == null) { - Navigator.of(context) - .popUntil(ModalRoute.withName(routeOnSuccessName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(routeOnSuccessName)); } else { widget.onSuccessInsteadOfRouteOnSuccess!.call(); } } } on BadEpicHttpAddressException catch (_) { - if (mounted) { + if (context.mounted) { // pop building dialog Navigator.of(context).pop(); unawaited( @@ -233,80 +228,79 @@ class _ConfirmTransactionViewState //todo: comeback to this debugPrint("$e\n$s"); // pop sending dialog - Navigator.of(context).pop(); + if (context.mounted) { + Navigator.of(context).pop(); - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - if (isDesktop) { - return DesktopDialog( - maxWidth: 450, - child: Padding( - padding: const EdgeInsets.all(32), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Broadcast transaction failed", - style: STextStyles.desktopH3(context), - ), - const SizedBox( - height: 24, - ), - Flexible( - child: SingleChildScrollView( - child: SelectableText( - e.toString(), - style: STextStyles.smallMed14(context), - ), + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + if (isDesktop) { + return DesktopDialog( + maxWidth: 450, + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Broadcast transaction failed", + style: STextStyles.desktopH3(context), ), - ), - const SizedBox( - height: 56, - ), - Row( - children: [ - const Spacer(), - Expanded( - child: PrimaryButton( - buttonHeight: ButtonHeight.l, - label: "Ok", - onPressed: Navigator.of(context).pop, + const SizedBox(height: 24), + Flexible( + child: SingleChildScrollView( + child: SelectableText( + e.toString(), + style: STextStyles.smallMed14(context), ), ), - ], - ), - ], + ), + const SizedBox(height: 56), + Row( + children: [ + const Spacer(), + Expanded( + child: PrimaryButton( + buttonHeight: ButtonHeight.l, + label: "Ok", + onPressed: Navigator.of(context).pop, + ), + ), + ], + ), + ], + ), ), - ), - ); - } else { - return StackDialog( - title: "Broadcast transaction failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + ); + } else { + return StackDialog( + title: "Broadcast transaction failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), ), + onPressed: () { + Navigator.of(context).pop(); + }, ), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ); - } - }, - ); + ); + } + }, + ); + } } } @@ -377,7 +371,8 @@ class _ConfirmTransactionViewState case FiroType.spark: fee = widget.txData.fee; - amountWithoutChange = (widget.txData.amountWithoutChange ?? + amountWithoutChange = + (widget.txData.amountWithoutChange ?? Amount.zeroWith( fractionDigits: wallet.cryptoCurrency.fractionDigits, )) + @@ -394,82 +389,79 @@ class _ConfirmTransactionViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - // if (FocusScope.of(context).hasFocus) { - // FocusScope.of(context).unfocus(); - // await Future.delayed(Duration(milliseconds: 50)); - // } - Navigator.of(context).pop(); - }, - ), - title: Text( - "Confirm transaction", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Confirm transaction", + style: STextStyles.navBarTitle(context), ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, + ), + body: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.min, - children: [ - Row( + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, children: [ - AppBarBackButton( - size: 40, - iconSize: 24, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(), - ), - Text( - "Confirm $unit transaction", - style: STextStyles.desktopH3(context), + Row( + children: [ + AppBarBackButton( + size: 40, + iconSize: 24, + onPressed: + () => + Navigator.of(context, rootNavigator: true).pop(), + ), + Text( + "Confirm $unit transaction", + style: STextStyles.desktopH3(context), + ), + ], ), + Flexible(child: SingleChildScrollView(child: child)), ], ), - Flexible( - child: SingleChildScrollView( - child: child, - ), - ), - ], - ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, @@ -478,13 +470,8 @@ class _ConfirmTransactionViewState Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Send $unit", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 12, - ), + Text("Send $unit", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -495,9 +482,7 @@ class _ConfirmTransactionViewState : "Recipient", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( widget.isPaynymTransaction ? widget.txData.paynymAccountLite!.nymName @@ -508,25 +493,23 @@ class _ConfirmTransactionViewState ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - ), + Text("Amount", style: STextStyles.smallMed12(context)), SelectableText( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( amountWithoutChange, - ethContract: widget.isTokenTx - ? ref - .watch(pCurrentTokenWallet)! - .tokenContract - : null, + ethContract: + widget.isTokenTx + ? ref + .watch(pCurrentTokenWallet)! + .tokenContract + : null, ), style: STextStyles.itemSubtitle12(context), textAlign: TextAlign.right, @@ -534,10 +517,7 @@ class _ConfirmTransactionViewState ], ), ), - if (coin is! NanoCurrency) - const SizedBox( - height: 12, - ), + if (coin is! NanoCurrency) const SizedBox(height: 12), if (coin is! NanoCurrency) RoundedWhiteContainer( child: Row( @@ -556,9 +536,7 @@ class _ConfirmTransactionViewState ), ), if (widget.txData.fee != null && widget.txData.vSize != null) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.fee != null && widget.txData.vSize != null) RoundedWhiteContainer( child: Row( @@ -568,9 +546,7 @@ class _ConfirmTransactionViewState "sats/vByte", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle12(context), @@ -579,9 +555,7 @@ class _ConfirmTransactionViewState ), ), if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty) RoundedWhiteContainer( child: Column( @@ -591,9 +565,7 @@ class _ConfirmTransactionViewState "On chain note", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( widget.txData.noteOnChain!, style: STextStyles.itemSubtitle12(context), @@ -602,9 +574,7 @@ class _ConfirmTransactionViewState ), ), if (widget.txData.note!.isNotEmpty) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.note!.isNotEmpty) RoundedWhiteContainer( child: Column( @@ -614,9 +584,7 @@ class _ConfirmTransactionViewState (coin is Epiccash) ? "Local Note" : "Note", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( widget.txData.note!, style: STextStyles.itemSubtitle12(context), @@ -644,9 +612,10 @@ class _ConfirmTransactionViewState children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, borderRadius: BorderRadius.only( topLeft: Radius.circular( Constants.size.circularBorderRadius, @@ -674,9 +643,7 @@ class _ConfirmTransactionViewState width: 32, height: 32, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Text( "Send $unit", style: STextStyles.desktopTextMedium(context), @@ -697,9 +664,7 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Builder( builder: (context) { final externalCalls = ref.watch( @@ -710,77 +675,81 @@ class _ConfirmTransactionViewState String fiatAmount = "N/A"; if (externalCalls) { - final price = widget.isTokenTx - ? ref - .read( - priceAnd24hChangeNotifierProvider, - ) - .getTokenPrice( - ref - .read(pCurrentTokenWallet)! - .tokenContract - .address, - ) - .item1 - : ref - .read( - priceAnd24hChangeNotifierProvider, - ) - .getPrice(coin) - .item1; - if (price > Decimal.zero) { - fiatAmount = - (amountWithoutChange.decimal * price) - .toAmount(fractionDigits: 2) - .fiatString( - locale: ref + final price = + widget.isTokenTx + ? ref + .read( + priceAnd24hChangeNotifierProvider, + ) + .getTokenPrice( + ref + .read(pCurrentTokenWallet)! + .tokenContract + .address, + ) + ?.value + : ref + .read( + priceAnd24hChangeNotifierProvider, + ) + .getPrice(coin) + ?.value; + if (price != null && price > Decimal.zero) { + fiatAmount = (amountWithoutChange.decimal * + price) + .toAmount(fractionDigits: 2) + .fiatString( + locale: + ref .read( localeServiceChangeNotifierProvider, ) .locale, - ); + ); } } return Row( children: [ SelectableText( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( amountWithoutChange, - ethContract: widget.isTokenTx - ? ref - .watch(pCurrentTokenWallet)! - .tokenContract - : null, + ethContract: + widget.isTokenTx + ? ref + .watch( + pCurrentTokenWallet, + )! + .tokenContract + : null, + ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, ), - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), ), if (externalCalls) Text( " | ", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (externalCalls) SelectableText( - "~$fiatAmount ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - )}", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + "~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ); @@ -791,9 +760,10 @@ class _ConfirmTransactionViewState ), Container( height: 1, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ), Padding( padding: const EdgeInsets.all(12), @@ -809,22 +779,24 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( // TODO: [prio=med] spark transaction specifics - better handling widget.isPaynymTransaction ? widget.txData.paynymAccountLite!.nymName : widget.txData.recipients?.first.address ?? - widget.txData.sparkRecipients!.first + widget + .txData + .sparkRecipients! + .first .address, style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -833,9 +805,10 @@ class _ConfirmTransactionViewState if (widget.isPaynymTransaction) Container( height: 1, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ), if (widget.isPaynymTransaction) Padding( @@ -850,17 +823,16 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( ref.watch(pAmountFormatter(coin)).format(fee!), style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -905,10 +877,7 @@ class _ConfirmTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(left: 32, right: 32), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -919,10 +888,7 @@ class _ConfirmTransactionViewState style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) - const SizedBox( - height: 8, - ), + if (coin is Epiccash) const SizedBox(height: 8), if (coin is Epiccash) ClipRRect( borderRadius: BorderRadius.circular( @@ -941,47 +907,46 @@ class _ConfirmTransactionViewState _onChainNoteFocusNode, context, ).copyWith( - suffixIcon: onChainNoteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - onChainNoteController.text = ""; - }); - }, - ), - ], + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController.text = + ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - if (coin is Epiccash) - const SizedBox( - height: 12, - ), + if (coin is Epiccash) const SizedBox(height: 12), SelectableText( (coin is Epiccash) ? "Local Note (optional)" : "Note (optional)", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -993,11 +958,13 @@ class _ConfirmTransactionViewState enableSuggestions: isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), onChanged: (_) => setState(() {}), @@ -1013,39 +980,36 @@ class _ConfirmTransactionViewState bottom: 12, right: 5, ), - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState( - () => noteController.text = "", - ); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState( + () => noteController.text = "", + ); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ], ), ), if (isDesktop && !widget.isPaynymTransaction) Padding( - padding: const EdgeInsets.only( - left: 32, - ), + padding: const EdgeInsets.only(left: 32), child: Text( "Transaction fee", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -1053,19 +1017,16 @@ class _ConfirmTransactionViewState ), if (isDesktop && !widget.isPaynymTransaction) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( ref.watch(pAmountFormatter(coin)).format(fee!), style: STextStyles.itemSubtitle(context), @@ -1077,9 +1038,7 @@ class _ConfirmTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - left: 32, - ), + padding: const EdgeInsets.only(left: 32), child: Text( "sats/vByte", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -1090,19 +1049,16 @@ class _ConfirmTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle(context), @@ -1110,75 +1066,79 @@ class _ConfirmTransactionViewState ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 23 : 12, - ), + SizedBox(height: isDesktop ? 23 : 12), if (!widget.isTokenTx) Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: RoundedContainer( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 16, - vertical: 18, - ) - : const EdgeInsets.all(12), - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, + padding: + isDesktop + ? const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ) + : const EdgeInsets.all(12), + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( isDesktop ? "Total amount to send" : "Total amount", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.titleBold12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), ), SelectableText( ref .watch(pAmountFormatter(coin)) .format(amountWithoutChange + fee!), - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), textAlign: TextAlign.right, ), ], ), ), ), - SizedBox( - height: isDesktop ? 28 : 16, - ), + SizedBox(height: isDesktop ? 28 : 16), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: PrimaryButton( label: "Send", buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -1188,31 +1148,28 @@ class _ConfirmTransactionViewState if (isDesktop) { unlocked = await showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - DesktopDialogCloseButton(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: DesktopAuthSend( - coin: coin, - ), - ), - ], - ), - ), + ), ); } else { unlocked = await Navigator.push( @@ -1220,18 +1177,21 @@ class _ConfirmTransactionViewState RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - popOnSuccess: true, - routeOnSuccessArguments: true, - routeOnSuccess: "", - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to send transaction", - biometricsAuthenticationTitle: "Confirm Transaction", + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: + "Confirm Transaction", + ), + settings: const RouteSettings( + name: "/confirmsendlockscreen", ), - settings: - const RouteSettings(name: "/confirmsendlockscreen"), ), ); } @@ -1243,9 +1203,10 @@ class _ConfirmTransactionViewState unawaited( showFloatingFlushBar( type: FlushBarType.warning, - message: Util.isDesktop - ? "Invalid passphrase" - : "Invalid PIN", + message: + Util.isDesktop + ? "Invalid passphrase" + : "Invalid PIN", context: context, ), ); @@ -1254,10 +1215,7 @@ class _ConfirmTransactionViewState }, ), ), - if (isDesktop) - const SizedBox( - height: 32, - ), + if (isDesktop) const SizedBox(height: 32), ], ), ), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 4bdcef6e2..5a624a916 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -150,13 +150,12 @@ class _SendViewState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final Amount amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: coin.fractionDigits); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); ref.read(pSendAmount.notifier).state = amount; } @@ -238,29 +237,27 @@ class _SendViewState extends ConsumerState { ); final Amount? amount; if (baseAmount != null) { - final Decimal _price = - ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1; + final _price = + ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin)?.value; - if (_price == Decimal.zero) { + if (_price == null || _price == Decimal.zero) { amount = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); } else { - amount = baseAmount <= Amount.zero - ? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits) - : (baseAmount.decimal / _price) - .toDecimal( - scaleOnInfinitePrecision: coin.fractionDigits, - ) - .toAmount(fractionDigits: coin.fractionDigits); + amount = + baseAmount <= Amount.zero + ? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits) + : (baseAmount.decimal / _price) + .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) + .toAmount(fractionDigits: coin.fractionDigits); } if (_cachedAmountToSend != null && _cachedAmountToSend == amount) { return; } _cachedAmountToSend = amount; - final amountString = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final amountString = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChangeLock = true; cryptoAmountController.text = amountString; @@ -281,9 +278,9 @@ class _SendViewState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( - cryptoAmountController.text, - ); + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse(cryptoAmountController.text); final Amount? amount; if (cryptoAmount != null) { amount = cryptoAmount; @@ -293,13 +290,11 @@ class _SendViewState extends ConsumerState { _cachedAmountToSend = amount; final price = - ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1; + ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin)?.value; - if (price > Decimal.zero) { + if (price != null && price > Decimal.zero) { baseAmountController.text = (amount.decimal * price) - .toAmount( - fractionDigits: 2, - ) + .toAmount(fractionDigits: 2) .fiatString( locale: ref.read(localeServiceChangeNotifierProvider).locale, ); @@ -356,10 +351,12 @@ class _SendViewState extends ConsumerState { fee = fee.split(" ").first; } - final value = fee.contains(",") - ? Decimal.parse(fee.replaceFirst(",", ".")) - .toAmount(fractionDigits: coin.fractionDigits) - : Decimal.parse(fee).toAmount(fractionDigits: coin.fractionDigits); + final value = + fee.contains(",") + ? Decimal.parse( + fee.replaceFirst(",", "."), + ).toAmount(fractionDigits: coin.fractionDigits) + : Decimal.parse(fee).toAmount(fractionDigits: coin.fractionDigits); if (shouldSetState) { setState(() => _currentFee = value); @@ -390,14 +387,15 @@ class _SendViewState extends ConsumerState { } else { final wallet = ref.read(pWallets).getWallet(walletId); if (wallet is SparkInterface) { - ref.read(pValidSparkSendToAddress.notifier).state = - SparkInterface.validateSparkAddress( + ref + .read(pValidSparkSendToAddress.notifier) + .state = SparkInterface.validateSparkAddress( address: address ?? "", isTestNet: wallet.cryptoCurrency.network.isTestNet, ); - ref.read(pIsExchangeAddress.state).state = - (coin as Firo).isExchangeAddress(address ?? ""); + ref.read(pIsExchangeAddress.state).state = (coin as Firo) + .isExchangeAddress(address ?? ""); if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && ref.read(pIsExchangeAddress) && @@ -410,8 +408,8 @@ class _SendViewState extends ConsumerState { } } - ref.read(pValidSendToAddress.notifier).state = - wallet.cryptoCurrency.validateAddress(address ?? ""); + ref.read(pValidSendToAddress.notifier).state = wallet.cryptoCurrency + .validateAddress(address ?? ""); } } @@ -486,11 +484,9 @@ class _SendViewState extends ConsumerState { } fee = await wallet.estimateFeeFor(amount, specialMoneroId.value); - cachedFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFees[amount]!; } else if (isFiro) { @@ -499,39 +495,29 @@ class _SendViewState extends ConsumerState { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.public: fee = await firoWallet.estimateFeeFor(amount, feeRate); - cachedFiroPublicFees[amount] = - ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroPublicFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroPublicFees[amount]!; case FiroType.lelantus: fee = await firoWallet.estimateFeeForLelantus(amount); - cachedFiroLelantusFees[amount] = - ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroLelantusFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroLelantusFees[amount]!; case FiroType.spark: fee = await firoWallet.estimateFeeForSpark(amount); - cachedFiroSparkFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroSparkFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroSparkFees[amount]!; } } else { fee = await wallet.estimateFeeFor(amount, feeRate); - cachedFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFees[amount]!; } @@ -540,9 +526,7 @@ class _SendViewState extends ConsumerState { Future _previewTransaction() async { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); final wallet = ref.read(pWallets).getWallet(walletId); final Amount amount = ref.read(pSendAmount)!; @@ -591,9 +575,10 @@ class _SendViewState extends ConsumerState { child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -604,10 +589,7 @@ class _SendViewState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Yes", - style: STextStyles.button(context), - ), + child: Text("Yes", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -636,7 +618,8 @@ class _SendViewState extends ConsumerState { builder: (context) { return BuildingTransactionDialog( coin: wallet.info.coin, - isSpark: wallet is FiroWallet && + isSpark: + wallet is FiroWallet && ref.read(publicPrivateBalanceStateProvider.state).state == FiroType.spark, onCancel: () { @@ -650,11 +633,7 @@ class _SendViewState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); Future txDataFuture; @@ -672,11 +651,12 @@ class _SendViewState extends ConsumerState { ], satsPerVByte: isCustomFee ? customFeeRate : null, feeRateType: feeRate, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } else if (wallet is FiroWallet) { @@ -695,26 +675,24 @@ class _SendViewState extends ConsumerState { ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (coinControlEnabled && selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } else { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (coinControlEnabled && selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } @@ -724,11 +702,7 @@ class _SendViewState extends ConsumerState { txDataFuture = wallet.prepareSendLelantus( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], ), ); @@ -737,25 +711,23 @@ class _SendViewState extends ConsumerState { case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: ref.read(pValidSparkSendToAddress) - ? null - : [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], - sparkRecipients: ref.read(pValidSparkSendToAddress) - ? [ - ( - address: _address!, - amount: amount, - memo: memoController.text, - isChange: false, - ), - ] - : null, + recipients: + ref.read(pValidSparkSendToAddress) + ? null + : [ + (address: _address!, amount: amount, isChange: false), + ], + sparkRecipients: + ref.read(pValidSparkSendToAddress) + ? [ + ( + address: _address!, + amount: amount, + memo: memoController.text, + isChange: false, + ), + ] + : null, ), ); break; @@ -764,29 +736,21 @@ class _SendViewState extends ConsumerState { final memo = coin is Stellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); TxData txData = results.first as TxData; @@ -794,9 +758,10 @@ class _SendViewState extends ConsumerState { if (isPaynymSend) { txData = txData.copyWith( paynymAccountLite: widget.accountLite!, - note: noteController.text.isNotEmpty - ? noteController.text - : "PayNym send", + note: + noteController.text.isNotEmpty + ? noteController.text + : "PayNym send", ); } else { txData = txData.copyWith(note: noteController.text); @@ -810,12 +775,13 @@ class _SendViewState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: txData, - walletId: walletId, - isPaynymTransaction: isPaynymSend, - onSuccess: clearSendForm, - ), + builder: + (_) => ConfirmTransactionView( + txData: txData, + walletId: walletId, + isPaynymTransaction: isPaynymSend, + onSuccess: clearSendForm, + ), settings: const RouteSettings( name: ConfirmTransactionView.routeName, ), @@ -845,9 +811,10 @@ class _SendViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -886,10 +853,9 @@ class _SendViewState extends ConsumerState { } Amount _selectedUtxosAmount(Set utxos) => Amount( - rawValue: - utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), - fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, - ); + rawValue: utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), + fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, + ); Future _sendAllTapped(bool showCoinControl) async { final Amount amount; @@ -912,10 +878,9 @@ class _SendViewState extends ConsumerState { amount = ref.read(pWalletBalance(walletId)).spendable; } - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChanged(); } @@ -934,8 +899,9 @@ class _SendViewState extends ConsumerState { }); _currentFee = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); - _calculateFeesFuture = - calculateFees(0.toAmountAsRaw(fractionDigits: coin.fractionDigits)); + _calculateFeesFuture = calculateFees( + 0.toAmountAsRaw(fractionDigits: coin.fractionDigits), + ); _data = widget.autoFillData; walletId = widget.walletId; clipboard = widget.clipboard; @@ -962,10 +928,9 @@ class _SendViewState extends ConsumerState { fractionDigits: coin.fractionDigits, ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); } sendToController.text = _data.contactLabel; _address = _data.address.trim(); @@ -1051,7 +1016,8 @@ class _SendViewState extends ConsumerState { localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final showCoinControl = wallet is CoinControlInterface && + final showCoinControl = + wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, @@ -1075,9 +1041,7 @@ class _SendViewState extends ConsumerState { }); } else { setState(() { - _calculateFeesFuture = calculateFees( - ref.read(pSendAmount)!, - ); + _calculateFeesFuture = calculateFees(ref.read(pSendAmount)!); }); } @@ -1112,6 +1076,15 @@ class _SendViewState extends ConsumerState { }); } + Decimal? price; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin)?.value, + ), + ); + } + return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, @@ -1135,11 +1108,7 @@ class _SendViewState extends ConsumerState { body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -1154,9 +1123,10 @@ class _SendViewState extends ConsumerState { children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -1166,25 +1136,20 @@ class _SendViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 22, height: 22, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context) - .copyWith(fontSize: 14), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -1194,14 +1159,16 @@ class _SendViewState extends ConsumerState { if (isFiro) Text( "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), if (coin is! Firo) Text( "Available balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), ], ), @@ -1217,33 +1184,39 @@ class _SendViewState extends ConsumerState { ) .state) { case FiroType.public: - amount = ref - .read(pWalletBalance(walletId)) - .spendable; + amount = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; break; case FiroType.lelantus: - amount = ref - .read( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; + amount = + ref + .read( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; break; case FiroType.spark: - amount = ref - .read( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; + amount = + ref + .read( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; break; } } else { - amount = ref - .read(pWalletBalance(walletId)) - .spendable; + amount = + ref + .read(pWalletBalance(walletId)) + .spendable; } return GestureDetector( @@ -1269,24 +1242,17 @@ class _SendViewState extends ConsumerState { .format(amount), style: STextStyles.titleBold12( context, - ).copyWith( - fontSize: 10, - ), + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), - Text( - "${(amount.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1))).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle( - context, - ).copyWith( - fontSize: 8, + if (price != null) + Text( + "${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, ), - textAlign: TextAlign.right, - ), ], ), ), @@ -1297,9 +1263,7 @@ class _SendViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -1327,9 +1291,7 @@ class _SendViewState extends ConsumerState { // ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (isPaynymSend) TextField( key: const Key("sendViewPaynymAddressFieldKey"), @@ -1362,7 +1324,9 @@ class _SendViewState extends ConsumerState { onChanged: (newValue) { final trimmed = newValue.trim(); - if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { + if ((trimmed.length - (_address?.length ?? 0)) + .abs() > + 1) { final parsed = AddressUtils.parsePaymentUri( trimmed, logging: Logging.instance, @@ -1397,9 +1361,10 @@ class _SendViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: @@ -1407,87 +1372,93 @@ class _SendViewState extends ConsumerState { children: [ _addressToggleFlag ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Address Field Input.", - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders( - _address, - ); - setState(() { - _addressToggleFlag = - false; - }); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders( + _address, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data! - .text!.isNotEmpty) { - String content = - data.text!.trim(); - if (content - .contains("\n")) { - content = - content.substring( - 0, - content.indexOf( - "\n", - ), - ); - } + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + String content = + data.text!.trim(); + if (content.contains( + "\n", + )) { + content = content + .substring( + 0, + content.indexOf( + "\n", + ), + ); + } - if (coin is Epiccash) { - // strip http:// and https:// if content contains @ - content = AddressUtils() - .formatAddress( - content, - ); - } + if (coin is Epiccash) { + // strip http:// and https:// if content contains @ + content = AddressUtils() + .formatAddress( + content, + ); + } - final trimmed = content.trim(); - final parsed = AddressUtils.parsePaymentUri( - trimmed, - logging: Logging.instance, + final trimmed = + content.trim(); + final parsed = + AddressUtils.parsePaymentUri( + trimmed, + logging: + Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + sendToController.text = + content; + _address = content; + + _setValidAddressProviders( + _address, ); - if (parsed != null) { - _applyUri(parsed); - } else { - sendToController.text = - content; - _address = content; - _setValidAddressProviders(_address,); - - setState(() { - _addressToggleFlag = - sendToController - .text - .isNotEmpty; - }); - } + setState(() { + _addressToggleFlag = + sendToController + .text + .isNotEmpty; + }); } - }, - child: sendToController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + } + }, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( semanticsLabel: @@ -1520,9 +1491,7 @@ class _SendViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (isStellar || (ref.watch(pValidSparkSendToAddress) && ref.watch( @@ -1558,9 +1527,10 @@ class _SendViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: @@ -1568,42 +1538,41 @@ class _SendViewState extends ConsumerState { children: [ memoController.text.isNotEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Memo Field Input.", - key: const Key( - "sendViewClearMemoFieldButtonKey", - ), - onTap: () { - memoController.text = ""; - setState(() {}); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Memo Field Input.", + key: const Key( + "sendViewClearMemoFieldButtonKey", + ), + onTap: () { + memoController.text = ""; + setState(() {}); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Memo Field Input.", - key: const Key( - "sendViewPasteMemoFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data! - .text!.isNotEmpty) { - final String content = - data.text!.trim(); - - memoController.text = - content.trim(); - - setState(() {}); - } - }, - child: const ClipboardIcon(), + semanticsLabel: + "Paste Button. Pastes From Clipboard To Memo Field Input.", + key: const Key( + "sendViewPasteMemoFieldButtonKey", ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + final String content = + data.text!.trim(); + + memoController.text = + content.trim(); + + setState(() {}); + } + }, + child: const ClipboardIcon(), + ), ], ), ), @@ -1624,20 +1593,24 @@ class _SendViewState extends ConsumerState { FiroType.lelantus) { if (_data != null && _data.contactLabel == _address) { - error = SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: coin.network == - CryptoCurrencyNetwork.test, - ) - ? "Unsupported" - : null; - } else if (ref - .watch(pValidSparkSendToAddress)) { + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: + coin.network == + CryptoCurrencyNetwork.test, + ) + ? "Unsupported" + : null; + } else if (ref.watch( + pValidSparkSendToAddress, + )) { error = "Unsupported"; } else { - error = ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; } } else { if (_data != null && @@ -1674,11 +1647,13 @@ class _SendViewState extends ConsumerState { child: Text( error, textAlign: TextAlign.left, - style: - STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, ), ), ), @@ -1686,20 +1661,14 @@ class _SendViewState extends ConsumerState { } }, ), - if (isFiro) - const SizedBox( - height: 12, - ), + if (isFiro) const SizedBox(height: 12), if (isFiro) Text( "Send from", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (isFiro) - const SizedBox( - height: 8, - ), + if (isFiro) const SizedBox(height: 8), if (isFiro) Stack( children: [ @@ -1715,9 +1684,10 @@ class _SendViewState extends ConsumerState { horizontal: 12, ), child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, + splashColor: + Theme.of( + context, + ).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1732,10 +1702,10 @@ class _SendViewState extends ConsumerState { top: Radius.circular(20), ), ), - builder: (_) => - FiroBalanceSelectionSheet( - walletId: walletId, - ), + builder: + (_) => FiroBalanceSelectionSheet( + walletId: walletId, + ), ); }, child: Row( @@ -1750,9 +1720,7 @@ class _SendViewState extends ConsumerState { context, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Builder( builder: (_) { final Amount amount; @@ -1763,31 +1731,34 @@ class _SendViewState extends ConsumerState { ) .state) { case FiroType.public: - amount = ref - .watch( - pWalletBalance( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalance( + walletId, + ), + ) + .spendable; break; case FiroType.lelantus: - amount = ref - .watch( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; break; case FiroType.spark: - amount = ref - .watch( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; break; } @@ -1796,13 +1767,11 @@ class _SendViewState extends ConsumerState { .watch( pAmountFormatter(coin), ) - .format( - amount, - ), + .format(amount), style: STextStyles.itemSubtitle( - context, - ), + context, + ), ); }, ), @@ -1812,9 +1781,10 @@ class _SendViewState extends ConsumerState { Assets.svg.chevronDown, width: 8, height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of(context) + .extension()! + .textSubtitle2, ), ], ), @@ -1822,9 +1792,7 @@ class _SendViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -1843,27 +1811,28 @@ class _SendViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldCryptoTextFieldKey", ), - key: - const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1888,10 +1857,9 @@ class _SendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( @@ -1900,11 +1868,13 @@ class _SendViewState extends ConsumerState { ref .watch(pAmountUnit(coin)) .unitForCoin(coin), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -1912,28 +1882,29 @@ class _SendViewState extends ConsumerState { ), ), if (Prefs.instance.externalCalls) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", ), - key: - const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1956,34 +1927,33 @@ class _SendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), ), ), ), - if (showCoinControl) - const SizedBox( - height: 8, - ), + if (showCoinControl) const SizedBox(height: 8), if (showCoinControl) RoundedWhiteContainer( child: Row( @@ -1992,17 +1962,20 @@ class _SendViewState extends ConsumerState { children: [ Text( "Coin control", - style: - STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + style: STextStyles.w500_14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ), CustomTextButton( - text: selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", onTap: () async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); @@ -2012,9 +1985,10 @@ class _SendViewState extends ConsumerState { } if (context.mounted) { - final spendable = ref - .read(pWalletBalance(walletId)) - .spendable; + final spendable = + ref + .read(pWalletBalance(walletId)) + .spendable; Amount? amount; if (ref.read(pSendAmount) != null) { @@ -2027,9 +2001,9 @@ class _SendViewState extends ConsumerState { } } - final result = - await Navigator.of(context) - .pushNamed( + final result = await Navigator.of( + context, + ).pushNamed( CoinControlView.routeName, arguments: Tuple4( walletId, @@ -2050,19 +2024,14 @@ class _SendViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is Epiccash) Text( "On chain Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) - const SizedBox( - height: 8, - ), + if (coin is Epiccash) const SizedBox(height: 8), if (coin is Epiccash) ClipRRect( borderRadius: BorderRadius.circular( @@ -2082,35 +2051,33 @@ class _SendViewState extends ConsumerState { _onChainNoteFocusNode, context, ).copyWith( - suffixIcon: onChainNoteController - .text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - onChainNoteController - .text = ""; - }); - }, - ), - ], + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController + .text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), - if (coin is Epiccash) - const SizedBox( - height: 12, - ), + if (coin is Epiccash) const SizedBox(height: 12), Text( (coin is Epiccash) ? "Local Note (optional)" @@ -2118,9 +2085,7 @@ class _SendViewState extends ConsumerState { style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -2137,32 +2102,32 @@ class _SendViewState extends ConsumerState { _noteFocusNode, context, ).copyWith( - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) @@ -2174,9 +2139,7 @@ class _SendViewState extends ConsumerState { if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) @@ -2195,193 +2158,212 @@ class _SendViewState extends ConsumerState { horizontal: 12, ), child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, + splashColor: + Theme.of( + context, + ).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), - onPressed: isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public - ? null - : () { - showModalBottomSheet( - backgroundColor: - Colors.transparent, - context: context, - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - TransactionFeeSelectionSheet( - walletId: walletId, - amount: (Decimal.tryParse( - cryptoAmountController - .text, - ) ?? - ref - .watch(pSendAmount) - ?.decimal ?? - Decimal.zero) - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - updateChosen: (String fee) { - if (fee == "custom") { - if (!isCustomFee) { - setState(() { - isCustomFee = true; - }); - } - return; - } - - _setCurrentFee( - fee, - true, - ); - setState(() { - _calculateFeesFuture = - Future(() => fee); - if (isCustomFee) { - isCustomFee = false; - } - }); - }, - ), - ); - }, - child: (isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public) - ? Row( - children: [ - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - "~${snapshot.data!}", - style: STextStyles - .itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: STextStyles - .itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ) - : Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - ref + onPressed: + isFiro && + ref .watch( - feeRateTypeStateProvider + publicPrivateBalanceStateProvider .state, ) - .state - .prettyName, - style: STextStyles - .itemSubtitle12( - context, + .state != + FiroType.public + ? null + : () { + showModalBottomSheet( + backgroundColor: + Colors.transparent, + context: context, + shape: + const RoundedRectangleBorder( + borderRadius: + BorderRadius.vertical( + top: + Radius.circular( + 20, + ), + ), ), - ), - const SizedBox( - width: 10, - ), - FutureBuilder( - future: - _calculateFeesFuture, - builder: - (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - isCustomFee - ? "" - : "~${snapshot.data!}", - style: STextStyles - .itemSubtitle( - context, + builder: + ( + _, + ) => TransactionFeeSelectionSheet( + walletId: walletId, + amount: (Decimal.tryParse( + cryptoAmountController + .text, + ) ?? + ref + .watch( + pSendAmount, + ) + ?.decimal ?? + Decimal.zero) + .toAmount( + fractionDigits: + coin.fractionDigits, ), + updateChosen: ( + String fee, + ) { + if (fee == "custom") { + if (!isCustomFee) { + setState(() { + isCustomFee = + true; + }); + } + return; + } + + _setCurrentFee( + fee, + true, ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: STextStyles - .itemSubtitle( + setState(() { + _calculateFeesFuture = + Future(() => fee); + if (isCustomFee) { + isCustomFee = false; + } + }); + }, + ), + ); + }, + child: + (isFiro && + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) + ? Row( + children: [ + FutureBuilder( + future: _calculateFeesFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ) + : Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeStateProvider + .state, + ) + .state + .prettyName, + style: + STextStyles.itemSubtitle12( context, ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - ], - ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + isCustomFee + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textSubtitle2, + ), + ], + ), ), ), ], @@ -2400,28 +2382,26 @@ class _SendViewState extends ConsumerState { ), ), const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), TextButton( - onPressed: ref.watch(pPreviewTxButtonEnabled(coin)) - ? _previewTransaction - : null, - style: ref.watch(pPreviewTxButtonEnabled(coin)) - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + onPressed: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? _previewTransaction + : null, + style: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), child: Text( "Preview", style: STextStyles.button(context), ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ], ), ), diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 01ae07406..281045361 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -183,10 +183,12 @@ class _TokenSendViewState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: tokenContract.decimals, - ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( + final Amount amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: tokenContract.decimals); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format( amount, withUnitName: false, indicatePrecisionLoss: false, @@ -231,22 +233,24 @@ class _TokenSendViewState extends ConsumerState { locale: ref.read(localeServiceChangeNotifierProvider).locale, ); if (baseAmount != null) { - final _price = ref - .read(priceAnd24hChangeNotifierProvider) - .getTokenPrice(tokenContract.address) - .item1; + final _price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getTokenPrice(tokenContract.address) + ?.value; - if (_price == Decimal.zero) { + if (_price == null || _price == Decimal.zero) { _amountToSend = Amount.zero; } else { - _amountToSend = baseAmount <= Amount.zero - ? Amount.zero - : Amount.fromDecimal( - (baseAmount.decimal / _price).toDecimal( - scaleOnInfinitePrecision: tokenContract.decimals, - ), - fractionDigits: tokenContract.decimals, - ); + _amountToSend = + baseAmount <= Amount.zero + ? Amount.zero + : Amount.fromDecimal( + (baseAmount.decimal / _price).toDecimal( + scaleOnInfinitePrecision: tokenContract.decimals, + ), + fractionDigits: tokenContract.decimals, + ); } if (_cachedAmountToSend != null && _cachedAmountToSend == _amountToSend) { return; @@ -254,10 +258,9 @@ class _TokenSendViewState extends ConsumerState { _cachedAmountToSend = _amountToSend; _cryptoAmountChangeLock = true; - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - _amountToSend!, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(_amountToSend!, withUnitName: false); _cryptoAmountChangeLock = false; } else { _amountToSend = Amount.zero; @@ -275,10 +278,9 @@ class _TokenSendViewState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( - cryptoAmountController.text, - ethContract: tokenContract, - ); + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse(cryptoAmountController.text, ethContract: tokenContract); if (cryptoAmount != null) { _amountToSend = cryptoAmount; if (_cachedAmountToSend != null && @@ -287,16 +289,15 @@ class _TokenSendViewState extends ConsumerState { } _cachedAmountToSend = _amountToSend; - final price = ref - .read(priceAnd24hChangeNotifierProvider) - .getTokenPrice(tokenContract.address) - .item1; + final price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getTokenPrice(tokenContract.address) + ?.value; - if (price > Decimal.zero) { + if (price != null && price > Decimal.zero) { baseAmountController.text = (_amountToSend!.decimal * price) - .toAmount( - fractionDigits: 2, - ) + .toAmount(fractionDigits: 2) .fiatString( locale: ref.read(localeServiceChangeNotifierProvider).locale, ); @@ -376,11 +377,9 @@ class _TokenSendViewState extends ConsumerState { } final Amount fee = await wallet.estimateFeeFor(Amount.zero, feeRate); - cachedFees = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFees = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFees; } @@ -388,9 +387,7 @@ class _TokenSendViewState extends ConsumerState { Future _previewTransaction() async { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); final wallet = ref.read(pWallets).getWallet(walletId); final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -471,33 +468,20 @@ class _TokenSendViewState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); TxData txData; Future txDataFuture; txDataFuture = tokenWallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], feeRateType: ref.read(feeRateTypeStateProvider), note: noteController.text, ), ); - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); txData = results.first as TxData; @@ -509,13 +493,14 @@ class _TokenSendViewState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: txData, - walletId: walletId, - isTokenTx: true, - onSuccess: clearSendForm, - routeOnSuccessName: TokenView.routeName, - ), + builder: + (_) => ConfirmTransactionView( + txData: txData, + walletId: walletId, + isTokenTx: true, + onSuccess: clearSendForm, + routeOnSuccessName: TokenView.routeName, + ), settings: const RouteSettings( name: ConfirmTransactionView.routeName, ), @@ -545,9 +530,10 @@ class _TokenSendViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -637,6 +623,15 @@ class _TokenSendViewState extends ConsumerState { localeServiceChangeNotifierProvider.select((value) => value.locale), ); + Decimal? price; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getTokenPrice(tokenContract.address)?.value, + ), + ); + } + return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, @@ -660,11 +655,7 @@ class _TokenSendViewState extends ConsumerState { body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -679,9 +670,10 @@ class _TokenSendViewState extends ConsumerState { children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -693,24 +685,24 @@ class _TokenSendViewState extends ConsumerState { EthTokenIcon( contractAddress: tokenContract.address, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context) - .copyWith(fontSize: 14), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), Text( "Available balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), ], ), @@ -722,13 +714,11 @@ class _TokenSendViewState extends ConsumerState { .format( ref .read( - pTokenBalance( - ( - walletId: widget.walletId, - contractAddress: - tokenContract.address, - ), - ), + pTokenBalance(( + walletId: widget.walletId, + contractAddress: + tokenContract.address, + )), ) .spendable, ethContract: tokenContract, @@ -748,48 +738,30 @@ class _TokenSendViewState extends ConsumerState { .format( ref .watch( - pTokenBalance( - ( - walletId: - widget.walletId, - contractAddress: - tokenContract - .address, - ), - ), - ) - .spendable, - ethContract: tokenContract, - ), - style: - STextStyles.titleBold12(context) - .copyWith( - fontSize: 10, - ), - textAlign: TextAlign.right, - ), - Text( - "${(ref.watch( - pTokenBalance( - ( + pTokenBalance(( walletId: widget.walletId, contractAddress: tokenContract .address, - ), - ), - ).spendable.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getTokenPrice(tokenContract.address).item1))).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle(context) - .copyWith( - fontSize: 8, - ), + )), + ) + .spendable, + ethContract: tokenContract, + ), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), + if (price != null) + Text( + "${(ref.watch(pTokenBalance((walletId: widget.walletId, contractAddress: tokenContract.address))).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, + ), ], ), ), @@ -798,17 +770,13 @@ class _TokenSendViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Text( "Send to", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -850,9 +818,10 @@ class _TokenSendViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: @@ -860,33 +829,33 @@ class _TokenSendViewState extends ConsumerState { children: [ _addressToggleFlag ? TextFieldIconButton( - key: const Key( - "tokenSendViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _updatePreviewButtonState( - _address, - _amountToSend, - ); - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) + key: const Key( + "tokenSendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, + _amountToSend, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "tokenSendViewPasteAddressFieldButtonKey", - ), - onTap: - _onTokenSendViewPasteAddressFieldButtonPressed, - child: sendToController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + key: const Key( + "tokenSendViewPasteAddressFieldButtonKey", ), + onTap: + _onTokenSendViewPasteAddressFieldButtonPressed, + child: + sendToController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( key: const Key( @@ -935,11 +904,13 @@ class _TokenSendViewState extends ConsumerState { child: Text( error, textAlign: TextAlign.left, - style: - STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, ), ), ), @@ -947,9 +918,7 @@ class _TokenSendViewState extends ConsumerState { } }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -972,27 +941,28 @@ class _TokenSendViewState extends ConsumerState { // ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldCryptoTextFieldKey", ), - key: - const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1014,10 +984,9 @@ class _TokenSendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( @@ -1026,11 +995,13 @@ class _TokenSendViewState extends ConsumerState { ref .watch(pAmountUnit(coin)) .unitForContract(tokenContract), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -1038,28 +1009,29 @@ class _TokenSendViewState extends ConsumerState { ), ), if (Prefs.instance.externalCalls) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", ), - key: - const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1081,41 +1053,39 @@ class _TokenSendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Text( "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1132,41 +1102,39 @@ class _TokenSendViewState extends ConsumerState { _noteFocusNode, context, ).copyWith( - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is! Epiccash) Text( "Transaction fee (estimated)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Stack( children: [ TextField( @@ -1182,9 +1150,10 @@ class _TokenSendViewState extends ConsumerState { horizontal: 12, ), child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, + splashColor: + Theme.of( + context, + ).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1199,25 +1168,27 @@ class _TokenSendViewState extends ConsumerState { top: Radius.circular(20), ), ), - builder: (_) => - TransactionFeeSelectionSheet( - walletId: walletId, - isToken: true, - amount: (Decimal.tryParse( - cryptoAmountController.text, - ) ?? - Decimal.zero) - .toAmount( - fractionDigits: - tokenContract.decimals, - ), - updateChosen: (String fee) { - setState(() { - _calculateFeesFuture = - Future(() => fee); - }); - }, - ), + builder: + (_) => TransactionFeeSelectionSheet( + walletId: walletId, + isToken: true, + amount: (Decimal.tryParse( + cryptoAmountController + .text, + ) ?? + Decimal.zero) + .toAmount( + fractionDigits: + tokenContract.decimals, + ), + updateChosen: (String fee) { + setState(() { + _calculateFeesFuture = Future( + () => fee, + ); + }); + }, + ), ); }, child: Row( @@ -1238,9 +1209,7 @@ class _TokenSendViewState extends ConsumerState { context, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), FutureBuilder( future: _calculateFeesFuture, builder: (context, snapshot) { @@ -1251,8 +1220,8 @@ class _TokenSendViewState extends ConsumerState { "~${snapshot.data!}", style: STextStyles.itemSubtitle( - context, - ), + context, + ), ); } else { return AnimatedText( @@ -1264,8 +1233,8 @@ class _TokenSendViewState extends ConsumerState { ], style: STextStyles.itemSubtitle( - context, - ), + context, + ), ); } }, @@ -1276,9 +1245,10 @@ class _TokenSendViewState extends ConsumerState { Assets.svg.chevronDown, width: 8, height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of(context) + .extension()! + .textSubtitle2, ), ], ), @@ -1287,36 +1257,36 @@ class _TokenSendViewState extends ConsumerState { ], ), const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), TextButton( - onPressed: ref - .watch( - previewTokenTxButtonStateProvider.state, - ) - .state - ? _previewTransaction - : null, - style: ref - .watch( - previewTokenTxButtonStateProvider.state, - ) - .state - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + onPressed: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? _previewTransaction + : null, + style: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), child: Text( "Preview", style: STextStyles.button(context), ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ], ), ), diff --git a/lib/pages/token_view/sub_widgets/my_token_select_item.dart b/lib/pages/token_view/sub_widgets/my_token_select_item.dart index 4f1eec6d1..745f2a0fd 100644 --- a/lib/pages/token_view/sub_widgets/my_token_select_item.dart +++ b/lib/pages/token_view/sub_widgets/my_token_select_item.dart @@ -56,10 +56,7 @@ class _MyTokenSelectItemState extends ConsumerState { late final CachedEthTokenBalance cachedBalance; - Future _loadTokenWallet( - BuildContext context, - WidgetRef ref, - ) async { + Future _loadTokenWallet(BuildContext context, WidgetRef ref) async { try { await ref.read(pCurrentTokenWallet)!.init(); return true; @@ -67,20 +64,21 @@ class _MyTokenSelectItemState extends ConsumerState { await showDialog( barrierDismissible: false, context: context, - builder: (context) => BasicDialog( - title: "Failed to load token data", - desktopHeight: double.infinity, - desktopWidth: 450, - rightButton: PrimaryButton( - label: "OK", - onPressed: () { - Navigator.of(context).pop(); - if (!isDesktop) { - Navigator.of(context).pop(); - } - }, - ), - ), + builder: + (context) => BasicDialog( + title: "Failed to load token data", + desktopHeight: double.infinity, + desktopWidth: 450, + rightButton: PrimaryButton( + label: "OK", + onPressed: () { + Navigator.of(context).pop(); + if (!isDesktop) { + Navigator.of(context).pop(); + } + }, + ), + ), ); return false; } @@ -90,11 +88,14 @@ class _MyTokenSelectItemState extends ConsumerState { final old = ref.read(tokenServiceStateProvider); // exit previous if there is one unawaited(old?.exit()); - ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet( - ethWallet: - ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet, - contract: widget.token, - ) as EthTokenWallet; + ref.read(tokenServiceStateProvider.state).state = + Wallet.loadTokenWallet( + ethWallet: + ref.read(pWallets).getWallet(widget.walletId) + as EthereumWallet, + contract: widget.token, + ) + as EthTokenWallet; final success = await showLoading( whileFuture: _loadTokenWallet(context, ref), @@ -138,17 +139,29 @@ class _MyTokenSelectItemState extends ConsumerState { @override Widget build(BuildContext context) { + String? priceString; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + priceString = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (s) => + s.getTokenPrice(widget.token.address)?.value.toStringAsFixed(2), + ), + ); + } + return RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: MaterialButton( key: Key("walletListItemButtonKey_${widget.token.symbol}"), - padding: isDesktop - ? const EdgeInsets.symmetric(horizontal: 28, vertical: 24) - : const EdgeInsets.symmetric(horizontal: 12, vertical: 13), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 28, vertical: 24) + : const EdgeInsets.symmetric(horizontal: 12, vertical: 13), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), onPressed: _onPressed, child: Row( @@ -157,9 +170,7 @@ class _MyTokenSelectItemState extends ConsumerState { contractAddress: widget.token.address, size: isDesktop ? 32 : 28, ), - SizedBox( - width: isDesktop ? 12 : 10, - ), + SizedBox(width: isDesktop ? 12 : 10), Expanded( child: Consumer( builder: (_, ref, __) { @@ -170,14 +181,17 @@ class _MyTokenSelectItemState extends ConsumerState { children: [ Text( widget.token.name, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.titleBold12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ) + : STextStyles.titleBold12(context), ), const Spacer(), Text( @@ -190,62 +204,52 @@ class _MyTokenSelectItemState extends ConsumerState { .format( ref .watch( - pTokenBalance( - ( - walletId: widget.walletId, - contractAddress: - widget.token.address - ), - ), + pTokenBalance(( + walletId: widget.walletId, + contractAddress: widget.token.address, + )), ) .total, ethContract: widget.token, ), - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ) + : STextStyles.itemSubtitle(context), ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Row( children: [ Text( widget.token.symbol, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle(context), ), const Spacer(), - Text( - "${ref.watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value - .getTokenPrice(widget.token.address) - .item1 - .toStringAsFixed(2), - ), - )} " - "${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - )}", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), - ), + if (priceString != null) + Text( + "$priceString " + "${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle(context), + ), ], ), ], diff --git a/lib/pages/token_view/sub_widgets/token_summary.dart b/lib/pages/token_view/sub_widgets/token_summary.dart index f5b051ef7..9bebfda49 100644 --- a/lib/pages/token_view/sub_widgets/token_summary.dart +++ b/lib/pages/token_view/sub_widgets/token_summary.dart @@ -11,6 +11,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; @@ -53,12 +54,22 @@ class TokenSummary extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final token = - ref.watch(pCurrentTokenWallet.select((value) => value!.tokenContract)); + final token = ref.watch( + pCurrentTokenWallet.select((value) => value!.tokenContract), + ); final balance = ref.watch( pTokenBalance((walletId: walletId, contractAddress: token.address)), ); + Decimal? price; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getTokenPrice(token.address)?.value, + ), + ); + } + return Stack( children: [ RoundedContainer( @@ -71,30 +82,26 @@ class TokenSummary extends ConsumerWidget { children: [ SvgPicture.asset( Assets.svg.walletDesktop, - color: Theme.of(context) - .extension()! - .tokenSummaryTextSecondary, + color: + Theme.of( + context, + ).extension()!.tokenSummaryTextSecondary, width: 12, height: 12, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Text( - ref.watch( - pWalletName(walletId), - ), + ref.watch(pWalletName(walletId)), style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .tokenSummaryTextSecondary, + color: + Theme.of( + context, + ).extension()!.tokenSummaryTextSecondary, ), ), ], ), - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -105,58 +112,31 @@ class TokenSummary extends ConsumerWidget { Ethereum(CryptoCurrencyNetwork.main), ), ) - .format( - balance.total, - ethContract: token, - ), + .format(balance.total, ethContract: token), style: STextStyles.pageTitleH1(context).copyWith( - color: Theme.of(context) - .extension()! - .tokenSummaryTextPrimary, + color: + Theme.of( + context, + ).extension()!.tokenSummaryTextPrimary, ), ), - const SizedBox( - width: 10, - ), - CoinTickerTag( - walletId: walletId, - ), + const SizedBox(width: 10), + CoinTickerTag(walletId: walletId), ], ), - const SizedBox( - height: 6, - ), - Text( - "${(balance.total.decimal * ref.watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value.getTokenPrice(token.address).item1, - ), - )).toAmount( - fractionDigits: 2, - ).fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider.select( - (value) => value.locale, - ), - ), - )} ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, + if (price != null) const SizedBox(height: 6), + if (price != null) + Text( + "${(balance.total.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle500(context).copyWith( + color: + Theme.of( + context, + ).extension()!.tokenSummaryTextPrimary, ), - )}", - style: STextStyles.subtitle500(context).copyWith( - color: Theme.of(context) - .extension()! - .tokenSummaryTextPrimary, ), - ), - const SizedBox( - height: 20, - ), - TokenWalletOptions( - walletId: walletId, - tokenContract: token, - ), + const SizedBox(height: 20), + TokenWalletOptions(walletId: walletId, tokenContract: token), ], ), ), @@ -195,11 +175,7 @@ class TokenWalletOptions extends ConsumerWidget { unawaited( Navigator.of(context).pushNamed( WalletInitiatedExchangeView.routeName, - arguments: Tuple3( - walletId, - ethereum, - tokenContract, - ), + arguments: Tuple3(walletId, ethereum, tokenContract), ), ); } @@ -208,10 +184,7 @@ class TokenWalletOptions extends ConsumerWidget { unawaited( Navigator.of(context).pushNamed( BuyInWalletView.routeName, - arguments: Tuple2( - ethereum, - tokenContract, - ), + arguments: Tuple2(ethereum, tokenContract), ), ); } @@ -228,50 +201,35 @@ class TokenWalletOptions extends ConsumerWidget { onPressed: () { Navigator.of(context).pushNamed( ReceiveView.routeName, - arguments: Tuple2( - walletId, - tokenContract, - ), + arguments: Tuple2(walletId, tokenContract), ); }, subLabel: "Receive", iconAssetPathSVG: Assets.svg.arrowDownLeft, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), TokenOptionsButton( onPressed: () { Navigator.of(context).pushNamed( TokenSendView.routeName, - arguments: Tuple3( - walletId, - ethereum, - tokenContract, - ), + arguments: Tuple3(walletId, ethereum, tokenContract), ); }, subLabel: "Send", iconAssetPathSVG: Assets.svg.arrowUpRight, ), if (AppConfig.hasFeature(AppFeature.swap) && showExchange) - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (AppConfig.hasFeature(AppFeature.swap) && showExchange) TokenOptionsButton( onPressed: () => _onExchangePressed(context), subLabel: "Swap", iconAssetPathSVG: ref.watch( - themeProvider.select( - (value) => value.assets.exchange, - ), + themeProvider.select((value) => value.assets.exchange), ), ), if (AppConfig.hasFeature(AppFeature.buy) && showExchange) - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (AppConfig.hasFeature(AppFeature.buy) && showExchange) TokenOptionsButton( onPressed: () => _onBuyPressed(context), @@ -320,46 +278,47 @@ class TokenOptionsButton extends StatelessWidget { padding: const EdgeInsets.all(10), child: ConditionalParent( condition: iconSize < 24, - builder: (child) => RoundedContainer( - padding: const EdgeInsets.all(6), - color: Theme.of(context) - .extension()! - .tokenSummaryIcon - .withOpacity(0.4), - radiusMultiplier: 10, - child: Center( - child: child, - ), - ), - child: iconAssetPathSVG.startsWith("assets/") - ? SvgPicture.asset( - iconAssetPathSVG, - color: Theme.of(context) - .extension()! - .tokenSummaryIcon, - width: iconSize, - height: iconSize, - ) - : SvgPicture.file( - File(iconAssetPathSVG), - color: Theme.of(context) - .extension()! - .tokenSummaryIcon, - width: iconSize, - height: iconSize, - ), + builder: + (child) => RoundedContainer( + padding: const EdgeInsets.all(6), + color: Theme.of(context) + .extension()! + .tokenSummaryIcon + .withOpacity(0.4), + radiusMultiplier: 10, + child: Center(child: child), + ), + child: + iconAssetPathSVG.startsWith("assets/") + ? SvgPicture.asset( + iconAssetPathSVG, + color: + Theme.of( + context, + ).extension()!.tokenSummaryIcon, + width: iconSize, + height: iconSize, + ) + : SvgPicture.file( + File(iconAssetPathSVG), + color: + Theme.of( + context, + ).extension()!.tokenSummaryIcon, + width: iconSize, + height: iconSize, + ), ), ), ), - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), Text( subLabel, style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .tokenSummaryTextPrimary, + color: + Theme.of( + context, + ).extension()!.tokenSummaryTextPrimary, ), ), ], @@ -368,10 +327,7 @@ class TokenOptionsButton extends StatelessWidget { } class CoinTickerTag extends ConsumerWidget { - const CoinTickerTag({ - super.key, - required this.walletId, - }); + const CoinTickerTag({super.key, required this.walletId}); final String walletId; @@ -382,11 +338,7 @@ class CoinTickerTag extends ConsumerWidget { radiusMultiplier: 0.25, color: Theme.of(context).extension()!.ethTagBG, child: Text( - ref - .watch( - pWalletCoin(walletId), - ) - .ticker, + ref.watch(pWalletCoin(walletId)).ticker, style: STextStyles.w600_12(context).copyWith( color: Theme.of(context).extension()!.ethTagText, ), diff --git a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart index 08d9152b8..1929a1ca4 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart @@ -11,6 +11,7 @@ import 'dart:io'; import 'dart:typed_data'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -52,9 +53,7 @@ class WalletSummaryInfo extends ConsumerWidget { useSafeArea: true, isScrollControlled: true, shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (_) => WalletBalanceToggleSheet(walletId: walletId), ); @@ -64,9 +63,6 @@ class WalletSummaryInfo extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { debugPrint("BUILD: $runtimeType"); - final externalCalls = ref.watch( - prefsChangeNotifierProvider.select((value) => value.externalCalls), - ); final coin = ref.watch(pWalletCoin(walletId)); final balance = ref.watch(pWalletBalance(walletId)); @@ -74,14 +70,27 @@ class WalletSummaryInfo extends ConsumerWidget { localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final baseCurrency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final baseCurrency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); + + ({double change24h, Decimal value})? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ); + } final priceTuple = ref.watch( priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin)), ); - final _showAvailable = ref.watch(walletBalanceToggleStateProvider) == + final _showAvailable = + ref.watch(walletBalanceToggleStateProvider) == WalletBalanceToggleState.available; final Amount balanceToShow; @@ -119,23 +128,23 @@ class WalletSummaryInfo extends ConsumerWidget { List? imageBytes; if (coin is Banano) { - imageBytes = (ref.watch(pWallets).getWallet(walletId) as BananoWallet) - .getMonkeyImageBytes(); + imageBytes = + (ref.watch(pWallets).getWallet(walletId) as BananoWallet) + .getMonkeyImageBytes(); } return ConditionalParent( condition: imageBytes != null, - builder: (child) => Stack( - children: [ - Positioned.fill( - left: 150.0, - child: SvgPicture.memory( - Uint8List.fromList(imageBytes!), - ), + builder: + (child) => Stack( + children: [ + Positioned.fill( + left: 150.0, + child: SvgPicture.memory(Uint8List.fromList(imageBytes!)), + ), + child, + ], ), - child, - ], - ), child: Row( children: [ Expanded( @@ -164,20 +173,20 @@ class WalletSummaryInfo extends ConsumerWidget { Text( title, style: STextStyles.subtitle500(context).copyWith( - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of( + context, + ).extension()!.textFavoriteCard, ), ), if (!toggleBalance) ...[ - const SizedBox( - width: 4, - ), + const SizedBox(width: 4), SvgPicture.asset( Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of( + context, + ).extension()!.textFavoriteCard, width: 8, height: 4, ), @@ -207,23 +216,21 @@ class WalletSummaryInfo extends ConsumerWidget { ref.watch(pAmountFormatter(coin)).format(balanceToShow), style: STextStyles.pageTitleH1(context).copyWith( fontSize: 24, - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of( + context, + ).extension()!.textFavoriteCard, ), ), ), - if (externalCalls) + if (price != null) Text( - "${(priceTuple.item1 * balanceToShow.decimal).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} $baseCurrency", + "${(price.value * balanceToShow.decimal).toAmount(fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.subtitle500(context).copyWith( - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of( + context, + ).extension()!.textFavoriteCard, ), ), ], @@ -232,9 +239,7 @@ class WalletSummaryInfo extends ConsumerWidget { Column( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), diff --git a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart index 5afd82597..9fcbfc3f4 100644 --- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart +++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart @@ -10,6 +10,7 @@ import 'dart:async'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; @@ -51,17 +52,11 @@ import '../sub_widgets/tx_icon.dart'; import 'transaction_details_view.dart'; import 'transaction_search_filter_view.dart'; -typedef _GroupedTransactions = ({ - String label, - DateTime startDate, - List transactions -}); +typedef _GroupedTransactions = + ({String label, DateTime startDate, List transactions}); class AllTransactionsView extends ConsumerStatefulWidget { - const AllTransactionsView({ - super.key, - required this.walletId, - }); + const AllTransactionsView({super.key, required this.walletId}); static const String routeName = "/allTransactions"; @@ -106,13 +101,14 @@ class _TransactionDetailsViewState extends ConsumerState { // debugPrint("FILTER: $filter"); final contacts = ref.read(addressBookServiceProvider).contacts; - final notes = ref - .read(mainDBProvider) - .isar - .transactionNotes - .where() - .walletIdEqualTo(walletId) - .findAllSync(); + final notes = + ref + .read(mainDBProvider) + .isar + .transactionNotes + .where() + .walletIdEqualTo(walletId) + .findAllSync(); return transactions.where((tx) { if (!filter.sent && !filter.received) { @@ -162,15 +158,16 @@ class _TransactionDetailsViewState extends ConsumerState { bool contains = false; // check if address book name contains - contains |= contacts - .where( - (e) => - e.addresses - .where((a) => a.address == tx.address.value?.value) - .isNotEmpty && - e.name.toLowerCase().contains(keyword), - ) - .isNotEmpty; + contains |= + contacts + .where( + (e) => + e.addresses + .where((a) => a.address == tx.address.value?.value) + .isNotEmpty && + e.name.toLowerCase().contains(keyword), + ) + .isNotEmpty; // check if address contains contains |= @@ -195,8 +192,9 @@ class _TransactionDetailsViewState extends ConsumerState { contains |= tx.type.name.toLowerCase().contains(keyword); // check if date contains - contains |= - Format.extractDateFrom(tx.timestamp).toLowerCase().contains(keyword); + contains |= Format.extractDateFrom( + tx.timestamp, + ).toLowerCase().contains(keyword); return contains; } @@ -210,13 +208,14 @@ class _TransactionDetailsViewState extends ConsumerState { } text = text.toLowerCase(); final contacts = ref.read(addressBookServiceProvider).contacts; - final notes = ref - .read(mainDBProvider) - .isar - .transactionNotes - .where() - .walletIdEqualTo(walletId) - .findAllSync(); + final notes = + ref + .read(mainDBProvider) + .isar + .transactionNotes + .where() + .walletIdEqualTo(walletId) + .findAllSync(); return transactions .where((tx) => _isKeywordMatch(tx, text, contacts, notes)) @@ -232,8 +231,11 @@ class _TransactionDetailsViewState extends ConsumerState { final date = DateTime.fromMillisecondsSinceEpoch(tx.timestamp * 1000); final monthYear = "${Constants.monthMap[date.month]} ${date.year}"; if (map[monthYear] == null) { - map[monthYear] = - (label: monthYear, startDate: date, transactions: [tx]); + map[monthYear] = ( + label: monthYear, + startDate: date, + transactions: [tx], + ); } else { map[monthYear]!.transactions.add(tx); } @@ -250,97 +252,99 @@ class _TransactionDetailsViewState extends ConsumerState { return MasterScaffold( background: Theme.of(context).extension()!.background, isDesktop: isDesktop, - appBar: isDesktop - ? DesktopAppBar( - isCompactHeight: true, - background: Theme.of(context).extension()!.popupBG, - leading: Row( - children: [ - const SizedBox( - width: 32, - ), - AppBarIconButton( - size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.arrowLeft, - width: 18, - height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: Navigator.of(context).pop, - ), - const SizedBox( - width: 12, - ), - Text( - "Transactions", - style: STextStyles.desktopH3(context), - ), - ], - ), - ) - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Transactions", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("transactionSearchFilterViewButton"), - size: 36, + appBar: + isDesktop + ? DesktopAppBar( + isCompactHeight: true, + background: Theme.of(context).extension()!.popupBG, + leading: Row( + children: [ + const SizedBox(width: 32), + AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], - color: Theme.of(context) - .extension()! - .background, icon: SvgPicture.asset( - Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), - onPressed: () { - Navigator.of(context).pushNamed( - TransactionSearchFilterView.routeName, - arguments: - ref.read(pWallets).getWallet(walletId).info.coin, - ); - }, + onPressed: Navigator.of(context).pop, ), - ), + const SizedBox(width: 12), + Text("Transactions", style: STextStyles.desktopH3(context)), + ], ), - ], - ), + ) + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Transactions", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 20, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("transactionSearchFilterViewButton"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.filter, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + TransactionSearchFilterView.routeName, + arguments: + ref + .read(pWallets) + .getWallet(walletId) + .info + .coin, + ); + }, + ), + ), + ), + ], + ), body: Padding( padding: EdgeInsets.only( left: isDesktop ? 20 : 12, @@ -355,15 +359,10 @@ class _TransactionDetailsViewState extends ConsumerState { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => SizedBox( - width: 570, - child: child, - ), + builder: (child) => SizedBox(width: 570, child: child), child: ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -378,15 +377,18 @@ class _TransactionDetailsViewState extends ConsumerState { _searchString = value; }); }, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Search...", searchFieldFocusNode, @@ -404,35 +406,33 @@ class _TransactionDetailsViewState extends ConsumerState { height: isDesktop ? 20 : 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), ), - if (isDesktop) - const SizedBox( - width: 20, - ), + if (isDesktop) const SizedBox(width: 20), if (isDesktop) SecondaryButton( buttonHeight: ButtonHeight.l, @@ -440,9 +440,10 @@ class _TransactionDetailsViewState extends ConsumerState { label: "Filter", icon: SvgPicture.asset( Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -453,9 +454,7 @@ class _TransactionDetailsViewState extends ConsumerState { showDialog( context: context, builder: (context) { - return TransactionSearchFilterView( - coin: coin, - ); + return TransactionSearchFilterView(coin: coin); }, ); } else { @@ -469,25 +468,14 @@ class _TransactionDetailsViewState extends ConsumerState { ], ), ), - if (isDesktop) - const SizedBox( - height: 8, - ), + if (isDesktop) const SizedBox(height: 8), if (isDesktop && ref.watch(transactionFilterProvider.state).state != null) const Padding( - padding: EdgeInsets.symmetric( - vertical: 8, - ), - child: Row( - children: [ - TransactionFilterOptionBar(), - ], - ), + padding: EdgeInsets.symmetric(vertical: 8), + child: Row(children: [TransactionFilterOptionBar()]), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: Consumer( builder: (_, ref, __) { @@ -495,38 +483,40 @@ class _TransactionDetailsViewState extends ConsumerState { ref.watch(transactionFilterProvider.state).state; return FutureBuilder( - future: ref - .watch(mainDBProvider) - .isar - .transactions - .buildQuery( - whereClauses: [ - IndexWhereClause.equalTo( - indexName: 'walletId', - value: [widget.walletId], - ), - ], - // TODO: [prio=med] add filters to wallet or cryptocurrency class - // eth tokens should all be on v2 txn now so this should not be needed here - // filter: widget.contractAddress != null - // ? FilterGroup.and([ - // FilterCondition.equalTo( - // property: r"contractAddress", - // value: widget.contractAddress!, - // ), - // const FilterCondition.equalTo( - // property: r"subType", - // value: TransactionSubType.ethToken, - // ), - // ]) - // : null, - sortBy: [ - const SortProperty( - property: "timestamp", - sort: Sort.desc, - ), - ], - ).findAll(), + future: + ref + .watch(mainDBProvider) + .isar + .transactions + .buildQuery( + whereClauses: [ + IndexWhereClause.equalTo( + indexName: 'walletId', + value: [widget.walletId], + ), + ], + // TODO: [prio=med] add filters to wallet or cryptocurrency class + // eth tokens should all be on v2 txn now so this should not be needed here + // filter: widget.contractAddress != null + // ? FilterGroup.and([ + // FilterCondition.equalTo( + // property: r"contractAddress", + // value: widget.contractAddress!, + // ), + // const FilterCondition.equalTo( + // property: r"subType", + // value: TransactionSubType.ethToken, + // ), + // ]) + // : null, + sortBy: [ + const SortProperty( + property: "timestamp", + sort: Sort.desc, + ), + ], + ) + .findAll(), builder: (_, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { @@ -555,43 +545,39 @@ class _TransactionDetailsViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (index != 0) - const SizedBox( - height: 12, - ), + if (index != 0) const SizedBox(height: 12), Text( month.label, style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (isDesktop) RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: ListView.separated( shrinkWrap: true, primary: false, - separatorBuilder: (context, _) => - Container( - height: 1, - color: Theme.of(context) - .extension()! - .background, - ), + separatorBuilder: + (context, _) => Container( + height: 1, + color: + Theme.of(context) + .extension()! + .background, + ), itemCount: month.transactions.length, - itemBuilder: (context, index) => - Padding( - padding: const EdgeInsets.all(4), - child: DesktopTransactionCardRow( - key: Key( - "transactionCard_key_${month.transactions[index].txid}", + itemBuilder: + (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: DesktopTransactionCardRow( + key: Key( + "transactionCard_key_${month.transactions[index].txid}", + ), + transaction: + month.transactions[index], + walletId: walletId, + ), ), - transaction: - month.transactions[index], - walletId: walletId, - ), - ), ), ), if (!isDesktop) @@ -659,10 +645,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - sent: false, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(sent: false); setState(() {}); } }, @@ -678,10 +664,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - received: false, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(received: false); setState(() {}); } }, @@ -698,10 +684,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - to: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(to: null); setState(() {}); } }, @@ -717,10 +703,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - from: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(from: null); setState(() {}); } }, @@ -737,10 +723,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - amount: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(amount: null); setState(() {}); } }, @@ -756,10 +742,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - keyword: "", - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(keyword: ""); setState(() {}); } }, @@ -780,9 +766,7 @@ class _TransactionFilterOptionBarState scrollDirection: Axis.horizontal, shrinkWrap: true, itemCount: items.length, - separatorBuilder: (_, __) => const SizedBox( - width: 16, - ), + separatorBuilder: (_, __) => const SizedBox(width: 16), itemBuilder: (context, index) => items[index], ), ); @@ -811,9 +795,7 @@ class TransactionFilterOptionBarItem extends StatelessWidget { borderRadius: BorderRadius.circular(1000), ), child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 14, - ), + padding: const EdgeInsets.symmetric(horizontal: 14), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -831,9 +813,7 @@ class TransactionFilterOptionBarItem extends StatelessWidget { ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), XIcon( width: 16, height: 16, @@ -915,17 +895,23 @@ class _DesktopTransactionCardRowState localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final baseCurrency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final baseCurrency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); final coin = ref.watch(pWalletCoin(walletId)); - final price = ref - .watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin)), - ) - .item1; + Decimal? price; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + price = + ref + .watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ) + ?.value; + } late final String prefix; if (Util.isDesktop) { @@ -946,8 +932,9 @@ class _DesktopTransactionCardRowState color: Theme.of(context).extension()!.popupBG, elevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: RawMaterialButton( shape: RoundedRectangleBorder( @@ -970,34 +957,28 @@ class _DesktopTransactionCardRowState if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: TransactionDetailsView( - transaction: _transaction, - coin: coin, - walletId: walletId, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TransactionDetailsView( + transaction: _transaction, + coin: coin, + walletId: walletId, + ), + ), ); } else { unawaited( Navigator.of(context).pushNamed( TransactionDetailsView.routeName, - arguments: Tuple3( - _transaction, - coin, - walletId, - ), + arguments: Tuple3(_transaction, coin, walletId), ), ); } }, child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row( children: [ TxIcon( @@ -1005,21 +986,16 @@ class _DesktopTransactionCardRowState currentHeight: currentHeight, coin: coin, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( flex: 3, child: Text( _transaction.isCancelled ? "Cancelled" - : whatIsIt( - _transaction.type, - coin, - currentHeight, - ), - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + : whatIsIt(_transaction.type, coin, currentHeight), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark, ), ), @@ -1038,20 +1014,19 @@ class _DesktopTransactionCardRowState final amount = _transaction.realAmount; return Text( "$prefix${ref.watch(pAmountFormatter(coin)).format(amount)}", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ); }, ), ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) + if (price != null) Expanded( flex: 4, child: Builder( @@ -1059,11 +1034,7 @@ class _DesktopTransactionCardRowState final amount = _transaction.realAmount; return Text( - "$prefix${(amount.decimal * price).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} $baseCurrency", + "$prefix${(amount.decimal * price!).toAmount(fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.desktopTextExtraExtraSmall(context), ); }, diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index 11ebd1b82..edd0bff14 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -10,6 +10,7 @@ import 'dart:async'; +import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -99,11 +100,12 @@ class _TransactionDetailsViewState isTokenTx = _transaction.subType == TransactionSubType.ethToken; walletId = widget.walletId; - minConfirms = ref - .read(pWallets) - .getWallet(widget.walletId) - .cryptoCurrency - .minConfirms; + minConfirms = + ref + .read(pWallets) + .getWallet(widget.walletId) + .cryptoCurrency + .minConfirms; coin = widget.coin; amount = _transaction.realAmount; fee = _transaction.fee.toAmountAsRaw(fractionDigits: coin.fractionDigits); @@ -114,9 +116,12 @@ class _TransactionDetailsViewState amountPrefix = _transaction.type == TransactionType.outgoing ? "-" : "+"; } - ethContract = isTokenTx - ? ref.read(mainDBProvider).getEthContractSync(_transaction.otherData!) - : null; + ethContract = + isTokenTx + ? ref + .read(mainDBProvider) + .getEthContractSync(_transaction.otherData!) + : null; unit = isTokenTx ? ethContract!.symbol : coin.ticker; @@ -208,10 +213,14 @@ class _TransactionDetailsViewState return address; } try { - final contacts = ref.read(addressBookServiceProvider).contacts.where( - (element) => element.addresses - .where((element) => element.address == address) - .isNotEmpty, + final contacts = ref + .read(addressBookServiceProvider) + .contacts + .where( + (element) => + element.addresses + .where((element) => element.address == address) + .isNotEmpty, ); if (contacts.isNotEmpty) { return contacts.first.name; @@ -219,7 +228,7 @@ class _TransactionDetailsViewState return address; } } catch (e, s) { - Logging.instance.w("$e\n$s", error: e, stackTrace: s,); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); return address; } } @@ -240,8 +249,9 @@ class _TransactionDetailsViewState builder: (_, ref, __) { return Checkbox( value: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.hideBlockExplorerWarning), + prefsChangeNotifierProvider.select( + (value) => value.hideBlockExplorerWarning, + ), ), onChanged: (value) { if (value is bool) { @@ -267,23 +277,21 @@ class _TransactionDetailsViewState child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), onPressed: () { Navigator.of(context).pop(true); }, - child: Text( - "Continue", - style: STextStyles.button(context), - ), + child: Text("Continue", style: STextStyles.button(context)), ), ); } else { @@ -297,10 +305,7 @@ class _TransactionDetailsViewState Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Attention", - style: STextStyles.desktopH2(context), - ), + Text("Attention", style: STextStyles.desktopH2(context)), Row( children: [ Consumer( @@ -344,10 +349,7 @@ class _TransactionDetailsViewState buttonHeight: ButtonHeight.l, label: "Cancel", onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(false); + Navigator.of(context, rootNavigator: true).pop(false); }, ), const SizedBox(width: 20), @@ -356,10 +358,7 @@ class _TransactionDetailsViewState buttonHeight: ButtonHeight.l, label: "Continue", onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(true); + Navigator.of(context, rootNavigator: true).pop(true); }, ), ], @@ -378,38 +377,53 @@ class _TransactionDetailsViewState Widget build(BuildContext context) { final currentHeight = ref.watch(pWalletChainHeight(walletId)); + Decimal? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => + isTokenTx + ? value.getTokenPrice(_transaction.otherData!)?.value + : value.getPrice(coin)?.value, + ), + ); + } + return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - // if (FocusScope.of(context).hasFocus) { - // FocusScope.of(context).unfocus(); - // await Future.delayed(Duration(milliseconds: 50)); - // } - Navigator.of(context).pop(); - }, - ), - title: Text( - "Transaction details", - style: STextStyles.navBarTitle(context), + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Transaction details", + style: STextStyles.navBarTitle(context), + ), ), - ), body: Padding( - padding: isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), child: Column( children: [ if (isDesktop) @@ -425,21 +439,20 @@ class _TransactionDetailsViewState ), Expanded( child: Padding( - padding: isDesktop - ? const EdgeInsets.only( - right: 32, - bottom: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), child: ConditionalParent( condition: isDesktop, builder: (child) { return RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, padding: const EdgeInsets.all(0), child: child, ); @@ -447,33 +460,40 @@ class _TransactionDetailsViewState child: SingleChildScrollView( primary: isDesktop ? false : null, child: Padding( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), child: Container( - decoration: isDesktop - ? BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, + decoration: + isDesktop + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ), - ) - : null, + ) + : null, child: Padding( - padding: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -486,92 +506,59 @@ class _TransactionDetailsViewState currentHeight: currentHeight, coin: coin, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SelectableText( _transaction.isCancelled ? coin is Ethereum ? "Failed" : "Cancelled" : whatIsIt( - _transaction, - currentHeight, - ), + _transaction, + currentHeight, + ), style: STextStyles.desktopTextMedium( - context, - ), + context, + ), ), ], ), Column( - crossAxisAlignment: isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, children: [ SelectableText( "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.titleBold12( - context, - ), - ), - const SizedBox( - height: 2, - ), - if (ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.externalCalls, - ), - )) - SelectableText( - "$amountPrefix${(amount.decimal * ref.watch( - priceAnd24hChangeNotifierProvider - .select( - (value) => isTokenTx - ? value - .getTokenPrice( - _transaction - .otherData!, - ) - .item1 - : value - .getPrice( - coin, - ) - .item1, - ), - )).toAmount(fractionDigits: 2).fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider - .select( - (value) => value.locale, - ), - ), - )} ${ref.watch( - prefsChangeNotifierProvider - .select( - (value) => value.currency, - ), - )}", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.titleBold12( context, ), + ), + const SizedBox(height: 2), + if (price != null) + SelectableText( + "$amountPrefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), ], ), @@ -589,23 +576,24 @@ class _TransactionDetailsViewState isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Status", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall(context) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle(context), ), // Flexible( // child: FittedBox( @@ -616,25 +604,30 @@ class _TransactionDetailsViewState ? coin is Ethereum ? "Failed" : "Cancelled" - : whatIsIt( - _transaction, - currentHeight, - ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: _transaction.type == - TransactionType.outgoing - ? Theme.of(context) - .extension()! - .accentColorOrange - : Theme.of(context) - .extension()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12(context), + : whatIsIt(_transaction, currentHeight), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), ), // ), // ), @@ -649,9 +642,7 @@ class _TransactionDetailsViewState TransactionSubType.mint)) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (!((coin is Monero || coin is Wownero) && _transaction.type == TransactionType.outgoing) && @@ -659,9 +650,10 @@ class _TransactionDetailsViewState _transaction.subType == TransactionSubType.mint)) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -687,30 +679,36 @@ class _TransactionDetailsViewState if (isDesktop) { showDialog( context: context, - builder: (_) => - DesktopDialog( - maxHeight: - double.infinity, - child: - AddressDetailsView( - addressId: - _transaction - .address - .value! - .id, - walletId: widget - .walletId, - ), - ), + builder: + ( + _, + ) => DesktopDialog( + maxHeight: + double + .infinity, + child: AddressDetailsView( + addressId: + _transaction + .address + .value! + .id, + walletId: + widget + .walletId, + ), + ), ); } else { - Navigator.of(context) - .pushNamed( + Navigator.of( + context, + ).pushNamed( AddressDetailsView .routeName, arguments: Tuple2( - _transaction.address - .value!.id, + _transaction + .address + .value! + .id, widget.walletId, ), ); @@ -725,83 +723,86 @@ class _TransactionDetailsViewState TransactionType.outgoing ? "Sent to" : "Receiving address", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), _transaction.type == TransactionType.incoming ? FutureBuilder( - future: fetchContactNameFor( - _transaction - .address.value!.value, - ), - builder: ( - builderContext, - AsyncSnapshot - snapshot, - ) { - String - addressOrContactName = - _transaction.address - .value!.value; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - addressOrContactName = - snapshot.data!; - } - return SelectableText( - addressOrContactName, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( + future: fetchContactNameFor( + _transaction + .address + .value! + .value, + ), + builder: ( + builderContext, + AsyncSnapshot + snapshot, + ) { + String addressOrContactName = + _transaction + .address + .value! + .value; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + addressOrContactName = + snapshot.data!; + } + return SelectableText( + addressOrContactName, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles - .itemSubtitle12( + : STextStyles.itemSubtitle12( context, ), - ); - }, - ) + ); + }, + ) : SelectableText( - _transaction - .address.value!.value, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( + _transaction + .address + .value! + .value, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles - .itemSubtitle12( + : STextStyles.itemSubtitle12( context, ), - ), + ), ], ), ), @@ -815,14 +816,13 @@ class _TransactionDetailsViewState if (coin is Epiccash) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is Epiccash) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -835,33 +835,33 @@ class _TransactionDetailsViewState children: [ Text( "On chain note", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox( - height: 8, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), + const SizedBox(height: 8), SelectableText( _transaction.otherData ?? "", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -875,13 +875,12 @@ class _TransactionDetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -893,104 +892,104 @@ class _TransactionDetailsViewState (coin is Epiccash) ? "Local Note" : "Note ", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), isDesktop ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, - ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension< - StackColors>()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.link2( - context, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, ), - ], - ), + ), + ], ), + ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SelectableText( ref .watch( - pTransactionNote( - ( - txid: _transaction.txid, - walletId: walletId - ), - ), + pTransactionNote(( + txid: _transaction.txid, + walletId: walletId, + )), ) ?.value ?? "", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1002,34 +1001,36 @@ class _TransactionDetailsViewState children: [ Text( "Date", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 2, - ), + if (isDesktop) const SizedBox(height: 2), if (isDesktop) SelectableText( Format.extractDateFrom( _transaction.timestamp, ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1038,16 +1039,21 @@ class _TransactionDetailsViewState Format.extractDateFrom( _transaction.timestamp, ), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton( @@ -1061,34 +1067,36 @@ class _TransactionDetailsViewState if (coin is! NanoCurrency) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is! NanoCurrency) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Builder( builder: (context) { - final String feeString = showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - ) - ? ref + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + ) + ? ref + .watch( + pAmountFormatter(coin), + ) + .format( + fee, + withUnitName: isTokenTx, + ) + : "Pending" + : ref .watch(pAmountFormatter(coin)) .format( fee, withUnitName: isTokenTx, - ) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format( - fee, - withUnitName: isTokenTx, - ); + ); return Row( mainAxisAlignment: @@ -1102,55 +1110,56 @@ class _TransactionDetailsViewState children: [ Text( "Transaction fee", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( feeString, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), if (!isDesktop) SelectableText( feeString, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: feeString), @@ -1161,9 +1170,7 @@ class _TransactionDetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), Builder( builder: (context) { final String height; @@ -1174,10 +1181,11 @@ class _TransactionDetailsViewState if (widget.coin is Bitcoincash || widget.coin is Ecash) { - height = _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; confirmations = confirms.toString(); } else if (widget.coin is Epiccash && _transaction.slateId == null) { @@ -1192,9 +1200,10 @@ class _TransactionDetailsViewState height = "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; } else { - height = confirms > 0 - ? "${_transaction.height}" - : "Pending"; + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; } confirmations = confirms.toString(); @@ -1203,9 +1212,10 @@ class _TransactionDetailsViewState return Column( children: [ RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1218,56 +1228,58 @@ class _TransactionDetailsViewState children: [ Text( "Block height", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( height, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), if (!isDesktop) SelectableText( height, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: height), @@ -1276,13 +1288,12 @@ class _TransactionDetailsViewState ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1295,56 +1306,58 @@ class _TransactionDetailsViewState children: [ Text( "Confirmations", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), if (isDesktop) - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (isDesktop) SelectableText( confirmations, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles - .itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), if (!isDesktop) SelectableText( confirmations, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (isDesktop) IconCopyButton(data: height), @@ -1358,14 +1371,13 @@ class _TransactionDetailsViewState if (coin is Ethereum) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is Ethereum) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1373,25 +1385,32 @@ class _TransactionDetailsViewState children: [ Text( "Nonce", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), SelectableText( _transaction.nonce.toString(), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), @@ -1399,14 +1418,13 @@ class _TransactionDetailsViewState if (kDebugMode) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (kDebugMode) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1414,38 +1432,44 @@ class _TransactionDetailsViewState children: [ Text( "Tx sub type", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), SelectableText( _transaction.subType.toString(), - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), ], ), ), isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1458,50 +1482,49 @@ class _TransactionDetailsViewState children: [ Text( "Transaction ID", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox( - height: 8, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), + const SizedBox(height: 8), // Flexible( // child: FittedBox( // fit: BoxFit.scaleDown, // child: SelectableText( _transaction.txid, - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), if (coin is! Epiccash) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is! Epiccash) CustomTextButton( text: "Open in block explorer", onTap: () async { final uri = getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); + coin: coin, + txid: _transaction.txid, + ); if (ref .read( @@ -1511,8 +1534,8 @@ class _TransactionDetailsViewState false) { final shouldContinue = await showExplorerWarning( - "${uri.scheme}://${uri.host}", - ); + "${uri.scheme}://${uri.host}", + ); if (!shouldContinue) { return; @@ -1527,21 +1550,22 @@ class _TransactionDetailsViewState try { await launchUrl( uri, - mode: LaunchMode - .externalApplication, + mode: + LaunchMode + .externalApplication, ); } catch (_) { - if (mounted) { + if (context.mounted) { unawaited( showDialog( context: context, - builder: (_) => - StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), + builder: + (_) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), ), ); } @@ -1562,14 +1586,9 @@ class _TransactionDetailsViewState ], ), ), + if (isDesktop) const SizedBox(width: 12), if (isDesktop) - const SizedBox( - width: 12, - ), - if (isDesktop) - IconCopyButton( - data: _transaction.txid, - ), + IconCopyButton(data: _transaction.txid), ], ), ), @@ -1653,14 +1672,13 @@ class _TransactionDetailsViewState if (coin is Epiccash) isDesktop ? const _Divider() - : const SizedBox( - height: 12, - ), + : const SizedBox(height: 12), if (coin is Epiccash) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -1672,14 +1690,14 @@ class _TransactionDetailsViewState children: [ Text( "Slate ID", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), // Flexible( // child: FittedBox( @@ -1687,27 +1705,27 @@ class _TransactionDetailsViewState // child: SelectableText( _transaction.slateId ?? "Unknown", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), // ), // ), ], ), - if (isDesktop) - const SizedBox( - width: 12, - ), + if (isDesktop) const SizedBox(width: 12), if (isDesktop) IconCopyButton( data: _transaction.slateId ?? "Unknown", @@ -1715,10 +1733,7 @@ class _TransactionDetailsViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), ], ), ), @@ -1730,101 +1745,106 @@ class _TransactionDetailsViewState ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, - floatingActionButton: (coin is Epiccash && - _transaction.getConfirmations(currentHeight) < 1 && - _transaction.isCancelled == false) - ? ConditionalParent( - condition: isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - vertical: 16, - ), - child: child, - ), - child: SizedBox( - width: MediaQuery.of(context).size.width - 32, - child: TextButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - Theme.of(context).extension()!.textError, + floatingActionButton: + (coin is Epiccash && + _transaction.getConfirmations(currentHeight) < 1 && + _transaction.isCancelled == false) + ? ConditionalParent( + condition: isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 16, + ), + child: child, ), - ), - onPressed: () async { - final wallet = ref.read(pWallets).getWallet(walletId); + child: SizedBox( + width: MediaQuery.of(context).size.width - 32, + child: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Theme.of(context).extension()!.textError, + ), + ), + onPressed: () async { + final wallet = ref.read(pWallets).getWallet(walletId); + + if (wallet is EpiccashWallet) { + final String? id = _transaction.slateId; + if (id == null) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Could not find Epic transaction ID", + context: context, + ), + ); + return; + } - if (wallet is EpiccashWallet) { - final String? id = _transaction.slateId; - if (id == null) { unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Could not find Epic transaction ID", + showDialog( + barrierDismissible: false, context: context, + builder: + (_) => + const CancellingTransactionProgressDialog(), ), ); - return; - } - - unawaited( - showDialog( - barrierDismissible: false, - context: context, - builder: (_) => - const CancellingTransactionProgressDialog(), - ), - ); - final result = - await wallet.cancelPendingTransactionAndPost(id); - if (mounted) { - // pop progress dialog - Navigator.of(context).pop(); + final result = await wallet + .cancelPendingTransactionAndPost(id); + if (context.mounted) { + // pop progress dialog + Navigator.of(context).pop(); - if (result.isEmpty) { - await showDialog( - context: context, - builder: (_) => StackOkDialog( - title: "Transaction cancelled", - onOkPressed: (_) { - wallet.refresh(); - Navigator.of(context).popUntil( - ModalRoute.withName( - WalletView.routeName, + if (result.isEmpty) { + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Transaction cancelled", + onOkPressed: (_) { + wallet.refresh(); + Navigator.of(context).popUntil( + ModalRoute.withName( + WalletView.routeName, + ), + ); + }, ), - ); - }, - ), - ); - } else { - await showDialog( - context: context, - builder: (_) => StackOkDialog( - title: "Failed to cancel transaction", - message: result, - ), - ); + ); + } else { + await showDialog( + context: context, + builder: + (_) => StackOkDialog( + title: "Failed to cancel transaction", + message: result, + ), + ); + } } + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "ERROR: Wallet type is not Epic Cash", + context: context, + ), + ); + return; } - } else { - unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "ERROR: Wallet type is not Epic Cash", - context: context, - ), - ); - return; - } - }, - child: Text( - "Cancel Transaction", - style: STextStyles.button(context), + }, + child: Text( + "Cancel Transaction", + style: STextStyles.button(context), + ), ), ), - ), - ) - : null, + ) + : null, ), ); } @@ -1843,10 +1863,7 @@ class _Divider extends StatelessWidget { } class IconCopyButton extends StatelessWidget { - const IconCopyButton({ - super.key, - required this.data, - }); + const IconCopyButton({super.key, required this.data}); final String data; @@ -1860,9 +1877,7 @@ class IconCopyButton extends StatelessWidget { Theme.of(context).extension()!.buttonBackSecondary, elevation: 0, hoverElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), onPressed: () async { await Clipboard.setData(ClipboardData(text: data)); if (context.mounted) { @@ -1889,10 +1904,7 @@ class IconCopyButton extends StatelessWidget { } class IconPencilButton extends StatelessWidget { - const IconPencilButton({ - super.key, - this.onPressed, - }); + const IconPencilButton({super.key, this.onPressed}); final VoidCallback? onPressed; @@ -1906,9 +1918,7 @@ class IconPencilButton extends StatelessWidget { Theme.of(context).extension()!.buttonBackSecondary, elevation: 0, hoverElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), onPressed: () => onPressed?.call(), child: Padding( padding: const EdgeInsets.all(5), diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart index ed6e007d2..c821be3a8 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart @@ -10,6 +10,7 @@ import 'dart:async'; +import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -51,11 +52,8 @@ import '../transaction_search_filter_view.dart'; import 'transaction_v2_card.dart'; import 'transaction_v2_details_view.dart'; -typedef _GroupedTransactions = ({ - String label, - DateTime startDate, - List transactions -}); +typedef _GroupedTransactions = + ({String label, DateTime startDate, List transactions}); class AllTransactionsV2View extends ConsumerStatefulWidget { const AllTransactionsV2View({ @@ -108,13 +106,14 @@ class _AllTransactionsV2ViewState extends ConsumerState { // debugPrint("FILTER: $filter"); final contacts = ref.read(addressBookServiceProvider).contacts; - final notes = ref - .read(mainDBProvider) - .isar - .transactionNotes - .where() - .walletIdEqualTo(walletId) - .findAllSync(); + final notes = + ref + .read(mainDBProvider) + .isar + .transactionNotes + .where() + .walletIdEqualTo(walletId) + .findAllSync(); return transactions.where((tx) { if (!filter.sent && !filter.received) { @@ -160,23 +159,25 @@ class _AllTransactionsV2ViewState extends ConsumerState { bool contains = false; // check if address book name contains - contains |= contacts - .where( - (e) => - e.addresses - .map((e) => e.address) - .toSet() - .intersection(tx.associatedAddresses()) - .isNotEmpty && - e.name.toLowerCase().contains(keyword), - ) - .isNotEmpty; + contains |= + contacts + .where( + (e) => + e.addresses + .map((e) => e.address) + .toSet() + .intersection(tx.associatedAddresses()) + .isNotEmpty && + e.name.toLowerCase().contains(keyword), + ) + .isNotEmpty; // check if address contains - contains |= tx - .associatedAddresses() - .where((e) => e.toLowerCase().contains(keyword)) - .isNotEmpty; + contains |= + tx + .associatedAddresses() + .where((e) => e.toLowerCase().contains(keyword)) + .isNotEmpty; TransactionNote? note; final matchingNotes = notes.where((e) => e.txid == tx.txid); @@ -197,8 +198,9 @@ class _AllTransactionsV2ViewState extends ConsumerState { contains |= tx.type.name.toLowerCase().contains(keyword); // check if date contains - contains |= - Format.extractDateFrom(tx.timestamp).toLowerCase().contains(keyword); + contains |= Format.extractDateFrom( + tx.timestamp, + ).toLowerCase().contains(keyword); return contains; } @@ -212,13 +214,14 @@ class _AllTransactionsV2ViewState extends ConsumerState { } text = text.toLowerCase(); final contacts = ref.read(addressBookServiceProvider).contacts; - final notes = ref - .read(mainDBProvider) - .isar - .transactionNotes - .where() - .walletIdEqualTo(walletId) - .findAllSync(); + final notes = + ref + .read(mainDBProvider) + .isar + .transactionNotes + .where() + .walletIdEqualTo(walletId) + .findAllSync(); return transactions .where((tx) => _isKeywordMatch(tx, text, contacts, notes)) @@ -234,8 +237,11 @@ class _AllTransactionsV2ViewState extends ConsumerState { final date = DateTime.fromMillisecondsSinceEpoch(tx.timestamp * 1000); final monthYear = "${Constants.monthMap[date.month]} ${date.year}"; if (map[monthYear] == null) { - map[monthYear] = - (label: monthYear, startDate: date, transactions: [tx]); + map[monthYear] = ( + label: monthYear, + startDate: date, + transactions: [tx], + ); } else { map[monthYear]!.transactions.add(tx); } @@ -252,96 +258,94 @@ class _AllTransactionsV2ViewState extends ConsumerState { return MasterScaffold( background: Theme.of(context).extension()!.background, isDesktop: isDesktop, - appBar: isDesktop - ? DesktopAppBar( - isCompactHeight: true, - background: Theme.of(context).extension()!.popupBG, - leading: Row( - children: [ - const SizedBox( - width: 32, - ), - AppBarIconButton( - size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.arrowLeft, - width: 18, - height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: Navigator.of(context).pop, - ), - const SizedBox( - width: 12, - ), - Text( - "Transactions", - style: STextStyles.desktopH3(context), - ), - ], - ), - ) - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Transactions", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("transactionSearchFilterViewButton"), - size: 36, + appBar: + isDesktop + ? DesktopAppBar( + isCompactHeight: true, + background: Theme.of(context).extension()!.popupBG, + leading: Row( + children: [ + const SizedBox(width: 32), + AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], - color: Theme.of(context) - .extension()! - .background, icon: SvgPicture.asset( - Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), - onPressed: () { - Navigator.of(context).pushNamed( - TransactionSearchFilterView.routeName, - arguments: ref.read(pWalletCoin(walletId)), - ); - }, + onPressed: Navigator.of(context).pop, ), - ), + const SizedBox(width: 12), + Text("Transactions", style: STextStyles.desktopH3(context)), + ], ), - ], - ), + ) + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Transactions", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 20, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("transactionSearchFilterViewButton"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.filter, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + TransactionSearchFilterView.routeName, + arguments: ref.read(pWalletCoin(walletId)), + ); + }, + ), + ), + ), + ], + ), body: Padding( padding: EdgeInsets.only( left: isDesktop ? 20 : 12, @@ -356,15 +360,10 @@ class _AllTransactionsV2ViewState extends ConsumerState { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => SizedBox( - width: 570, - child: child, - ), + builder: (child) => SizedBox(width: 570, child: child), child: ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -379,15 +378,18 @@ class _AllTransactionsV2ViewState extends ConsumerState { _searchString = value; }); }, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Search...", searchFieldFocusNode, @@ -405,35 +407,33 @@ class _AllTransactionsV2ViewState extends ConsumerState { height: isDesktop ? 20 : 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), ), - if (isDesktop) - const SizedBox( - width: 20, - ), + if (isDesktop) const SizedBox(width: 20), if (isDesktop) SecondaryButton( buttonHeight: ButtonHeight.l, @@ -441,9 +441,10 @@ class _AllTransactionsV2ViewState extends ConsumerState { label: "Filter", icon: SvgPicture.asset( Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -468,25 +469,14 @@ class _AllTransactionsV2ViewState extends ConsumerState { ], ), ), - if (isDesktop) - const SizedBox( - height: 8, - ), + if (isDesktop) const SizedBox(height: 8), if (isDesktop && ref.watch(transactionFilterProvider.state).state != null) const Padding( - padding: EdgeInsets.symmetric( - vertical: 8, - ), - child: Row( - children: [ - TransactionFilterOptionBar(), - ], - ), + padding: EdgeInsets.symmetric(vertical: 8), + child: Row(children: [TransactionFilterOptionBar()]), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: Consumer( builder: (_, ref, __) { @@ -494,33 +484,35 @@ class _AllTransactionsV2ViewState extends ConsumerState { ref.watch(transactionFilterProvider.state).state; return FutureBuilder( - future: ref - .watch(mainDBProvider) - .isar - .transactionV2s - .buildQuery( - whereClauses: [ - IndexWhereClause.equalTo( - indexName: 'walletId', - value: [widget.walletId], - ), - ], - filter: widget.contractAddress == null - ? ref - .watch(pWallets) - .getWallet(widget.walletId) - .transactionFilterOperation - : ref - .read(pCurrentTokenWallet)! - .transactionFilterOperation, - sortBy: [ - const SortProperty( - property: "timestamp", - sort: Sort.desc, - ), - ], - ) - .findAll(), + future: + ref + .watch(mainDBProvider) + .isar + .transactionV2s + .buildQuery( + whereClauses: [ + IndexWhereClause.equalTo( + indexName: 'walletId', + value: [widget.walletId], + ), + ], + filter: + widget.contractAddress == null + ? ref + .watch(pWallets) + .getWallet(widget.walletId) + .transactionFilterOperation + : ref + .read(pCurrentTokenWallet)! + .transactionFilterOperation, + sortBy: [ + const SortProperty( + property: "timestamp", + sort: Sort.desc, + ), + ], + ) + .findAll(), builder: (_, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { @@ -549,43 +541,39 @@ class _AllTransactionsV2ViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (index != 0) - const SizedBox( - height: 12, - ), + if (index != 0) const SizedBox(height: 12), Text( month.label, style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (isDesktop) RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: ListView.separated( shrinkWrap: true, primary: false, - separatorBuilder: (context, _) => - Container( - height: 1, - color: Theme.of(context) - .extension()! - .background, - ), + separatorBuilder: + (context, _) => Container( + height: 1, + color: + Theme.of(context) + .extension()! + .background, + ), itemCount: month.transactions.length, - itemBuilder: (context, index) => - Padding( - padding: const EdgeInsets.all(4), - child: DesktopTransactionCardRow( - key: Key( - "transactionCard_key_${month.transactions[index].txid}", + itemBuilder: + (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: DesktopTransactionCardRow( + key: Key( + "transactionCard_key_${month.transactions[index].txid}", + ), + transaction: + month.transactions[index], + walletId: walletId, + ), ), - transaction: - month.transactions[index], - walletId: walletId, - ), - ), ), ), if (!isDesktop) @@ -652,10 +640,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - sent: false, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(sent: false); setState(() {}); } }, @@ -671,10 +659,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - received: false, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(received: false); setState(() {}); } }, @@ -691,10 +679,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - to: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(to: null); setState(() {}); } }, @@ -710,10 +698,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - from: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(from: null); setState(() {}); } }, @@ -730,10 +718,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - amount: null, - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(amount: null); setState(() {}); } }, @@ -749,10 +737,10 @@ class _TransactionFilterOptionBarState if (items.isEmpty) { ref.read(transactionFilterProvider.state).state = null; } else { - ref.read(transactionFilterProvider.state).state = - ref.read(transactionFilterProvider.state).state?.copyWith( - keyword: "", - ); + ref.read(transactionFilterProvider.state).state = ref + .read(transactionFilterProvider.state) + .state + ?.copyWith(keyword: ""); setState(() {}); } }, @@ -773,9 +761,7 @@ class _TransactionFilterOptionBarState scrollDirection: Axis.horizontal, shrinkWrap: true, itemCount: items.length, - separatorBuilder: (_, __) => const SizedBox( - width: 16, - ), + separatorBuilder: (_, __) => const SizedBox(width: 16), itemBuilder: (context, index) => items[index], ), ); @@ -804,9 +790,7 @@ class TransactionFilterOptionBarItem extends StatelessWidget { borderRadius: BorderRadius.circular(1000), ), child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 14, - ), + padding: const EdgeInsets.symmetric(horizontal: 14), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -824,9 +808,7 @@ class TransactionFilterOptionBarItem extends StatelessWidget { ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), XIcon( width: 16, height: 16, @@ -865,23 +847,25 @@ class _DesktopTransactionCardRowState bool get isTokenTx => ethContract != null; String whatIsIt(TransactionV2 tx, int height) => tx.statusLabel( - currentChainHeight: height, - minConfirms: minConfirms, - minCoinbaseConfirms: ref + currentChainHeight: height, + minConfirms: minConfirms, + minCoinbaseConfirms: + ref .read(pWallets) .getWallet(widget.walletId) .cryptoCurrency .minCoinbaseConfirms, - ); + ); @override void initState() { walletId = widget.walletId; - minConfirms = ref - .read(pWallets) - .getWallet(widget.walletId) - .cryptoCurrency - .minConfirms; + minConfirms = + ref + .read(pWallets) + .getWallet(widget.walletId) + .cryptoCurrency + .minConfirms; _transaction = widget.transaction; if (_transaction.subType == TransactionSubType.ethToken) { @@ -901,17 +885,25 @@ class _DesktopTransactionCardRowState localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final baseCurrency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final baseCurrency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); final coin = ref.watch(pWalletCoin(walletId)); - final price = ref - .watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin)), - ) - .item1; + Decimal? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => + isTokenTx + ? value.getTokenPrice(_transaction.contractAddress!)?.value + : value.getPrice(coin)?.value, + ), + ); + } late final String prefix; if (Util.isDesktop) { @@ -979,8 +971,9 @@ class _DesktopTransactionCardRowState color: Theme.of(context).extension()!.popupBG, elevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: RawMaterialButton( shape: RoundedRectangleBorder( @@ -992,34 +985,28 @@ class _DesktopTransactionCardRowState if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: TransactionV2DetailsView( - transaction: _transaction, - coin: coin, - walletId: walletId, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TransactionV2DetailsView( + transaction: _transaction, + coin: coin, + walletId: walletId, + ), + ), ); } else { unawaited( Navigator.of(context).pushNamed( TransactionV2DetailsView.routeName, - arguments: ( - tx: _transaction, - coin: coin, - walletId: walletId, - ), + arguments: (tx: _transaction, coin: coin, walletId: walletId), ), ); } }, child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row( children: [ TxIcon( @@ -1027,18 +1014,14 @@ class _DesktopTransactionCardRowState currentHeight: currentHeight, coin: coin, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( flex: 3, child: Text( - whatIsIt( - _transaction, - currentHeight, - ), - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + whatIsIt(_transaction, currentHeight), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark, ), ), @@ -1062,24 +1045,18 @@ class _DesktopTransactionCardRowState flex: 6, child: Text( "$prefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark, ), ), ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) + if (price != null) Expanded( flex: 4, child: Text( - "$prefix${(amount.decimal * price).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} $baseCurrency", + "$prefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.desktopTextExtraExtraSmall(context), ), ), diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart index 34e5c662b..fbc9c0009 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -25,10 +26,7 @@ import '../../sub_widgets/tx_icon.dart'; import 'transaction_v2_details_view.dart'; class TransactionCardV2 extends ConsumerStatefulWidget { - const TransactionCardV2({ - super.key, - required this.transaction, - }); + const TransactionCardV2({super.key, required this.transaction}); final TransactionV2 transaction; @@ -47,25 +45,24 @@ class _TransactionCardStateV2 extends ConsumerState { bool get isTokenTx => tokenContract != null; - String whatIsIt( - CryptoCurrency coin, - int currentHeight, - ) => + String whatIsIt(CryptoCurrency coin, int currentHeight) => _transaction.isCancelled && coin is Ethereum ? "Failed" : _transaction.statusLabel( - currentChainHeight: currentHeight, - minConfirms: ref - .read(pWallets) - .getWallet(walletId) - .cryptoCurrency - .minConfirms, - minCoinbaseConfirms: ref - .read(pWallets) - .getWallet(walletId) - .cryptoCurrency - .minCoinbaseConfirms, - ); + currentChainHeight: currentHeight, + minConfirms: + ref + .read(pWallets) + .getWallet(walletId) + .cryptoCurrency + .minConfirms, + minCoinbaseConfirms: + ref + .read(pWallets) + .getWallet(walletId) + .cryptoCurrency + .minCoinbaseConfirms, + ); @override void initState() { @@ -106,18 +103,23 @@ class _TransactionCardStateV2 extends ConsumerState { localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final baseCurrency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final baseCurrency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); - final price = ref - .watch( - priceAnd24hChangeNotifierProvider.select( - (value) => isTokenTx - ? value.getTokenPrice(tokenContract!.address) - : value.getPrice(coin), - ), - ) - .item1; + Decimal? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => + isTokenTx + ? value.getTokenPrice(tokenContract!.address)?.value + : value.getPrice(coin)?.value, + ), + ); + } final currentHeight = ref.watch(pWalletChainHeight(walletId)); @@ -174,8 +176,9 @@ class _TransactionCardStateV2 extends ConsumerState { color: Theme.of(context).extension()!.popupBG, elevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: Padding( padding: const EdgeInsets.all(6), @@ -189,25 +192,22 @@ class _TransactionCardStateV2 extends ConsumerState { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: TransactionV2DetailsView( - transaction: _transaction, - coin: coin, - walletId: walletId, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TransactionV2DetailsView( + transaction: _transaction, + coin: coin, + walletId: walletId, + ), + ), ); } else { unawaited( Navigator.of(context).pushNamed( TransactionV2DetailsView.routeName, - arguments: ( - tx: _transaction, - coin: coin, - walletId: walletId, - ), + arguments: (tx: _transaction, coin: coin, walletId: walletId), ), ); } @@ -221,9 +221,7 @@ class _TransactionCardStateV2 extends ConsumerState { coin: coin, currentHeight: currentHeight, ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -236,17 +234,12 @@ class _TransactionCardStateV2 extends ConsumerState { child: FittedBox( fit: BoxFit.scaleDown, child: Text( - whatIsIt( - coin, - currentHeight, - ), + whatIsIt(coin, currentHeight), style: STextStyles.itemSubtitle12(context), ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Flexible( child: FittedBox( fit: BoxFit.scaleDown, @@ -262,9 +255,7 @@ class _TransactionCardStateV2 extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, // crossAxisAlignment: CrossAxisAlignment.end, @@ -278,29 +269,15 @@ class _TransactionCardStateV2 extends ConsumerState { ), ), ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) - const SizedBox( - width: 10, - ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) + if (price != null) const SizedBox(width: 10), + if (price != null) Flexible( child: FittedBox( fit: BoxFit.scaleDown, child: Builder( builder: (_) { return Text( - "$prefix${Amount.fromDecimal( - amount.decimal * price, - fractionDigits: 2, - ).fiatString( - locale: locale, - )} $baseCurrency", + "$prefix${Amount.fromDecimal(amount.decimal * price!, fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.label(context), ); }, diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index c98876f1d..c4f158367 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -10,6 +10,7 @@ import 'dart:async'; +import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -588,6 +589,20 @@ class _TransactionV2DetailsViewState coin.minCoinbaseConfirms, ); + Decimal? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => + isTokenTx + ? value.getTokenPrice(_transaction.contractAddress!)?.value + : value.getPrice(coin)?.value, + ), + ); + } + return ConditionalParent( condition: !isDesktop, builder: (child) => Background(child: child), @@ -743,21 +758,42 @@ class _TransactionV2DetailsViewState ), ), const SizedBox(height: 2), - if (ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.externalCalls, - ), - )) - SelectableText( - "$amountPrefix${(amount.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1))).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, + if (price != null) + Builder( + builder: (context) { + final total = (amount.decimal * + price!) + .toAmount( + fractionDigits: 2, + ); + final formatted = total.fiatString( + locale: ref.watch( + localeServiceChangeNotifierProvider + .select( + (value) => + value.locale, + ), + ), + ); + final ticker = ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value.currency, ), + ); + return SelectableText( + "$amountPrefix$formatted $ticker", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ); + }, ), ], ), @@ -1893,7 +1929,7 @@ class _TransactionV2DetailsViewState .externalApplication, ); } catch (_) { - if (mounted) { + if (context.mounted) { unawaited( showDialog( context: context, @@ -2143,7 +2179,7 @@ class _TransactionV2DetailsViewState final result = await wallet .cancelPendingTransactionAndPost(id); - if (mounted) { + if (context.mounted) { // pop progress dialog Navigator.of(context).pop(); diff --git a/lib/pages/wallets_view/sub_widgets/favorite_card.dart b/lib/pages/wallets_view/sub_widgets/favorite_card.dart index d9f730804..1133731dc 100644 --- a/lib/pages/wallets_view/sub_widgets/favorite_card.dart +++ b/lib/pages/wallets_view/sub_widgets/favorite_card.dart @@ -10,6 +10,7 @@ import 'dart:io'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -67,53 +68,63 @@ class _FavoriteCardState extends ConsumerState { prefsChangeNotifierProvider.select((value) => value.externalCalls), ); + Decimal? price; + if (externalCalls) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin)?.value, + ), + ); + } return ConditionalParent( condition: Util.isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (_) { - setState(() { - _hovering = true; - }); - }, - onExit: (_) { - setState(() { - _hovering = false; - }); - }, - child: AnimatedScale( - duration: const Duration(milliseconds: 200), - scale: _hovering ? 1.05 : 1, - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - decoration: _hovering - ? BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - boxShadow: [ - Theme.of(context) - .extension()! - .standardBoxShadow, - Theme.of(context) - .extension()! - .standardBoxShadow, - Theme.of(context) - .extension()! - .standardBoxShadow, - ], - ) - : BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - child: child, + builder: + (child) => MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) { + setState(() { + _hovering = true; + }); + }, + onExit: (_) { + setState(() { + _hovering = false; + }); + }, + child: AnimatedScale( + duration: const Duration(milliseconds: 200), + scale: _hovering ? 1.05 : 1, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + decoration: + _hovering + ? BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + boxShadow: [ + Theme.of( + context, + ).extension()!.standardBoxShadow, + Theme.of( + context, + ).extension()!.standardBoxShadow, + Theme.of( + context, + ).extension()!.standardBoxShadow, + ], + ) + : BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + child: child, + ), + ), ), - ), - ), child: GestureDetector( onTap: () async { final wallet = ref.read(pWallets).getWallet(walletId); @@ -133,8 +144,9 @@ class _FavoriteCardState extends ConsumerState { final Future loadFuture; if (wallet is ExternalWallet) { - loadFuture = - wallet.init().then((value) async => await (wallet).open()); + loadFuture = wallet.init().then( + (value) async => await (wallet).open(), + ); } else { loadFuture = wallet.init(); } @@ -147,15 +159,13 @@ class _FavoriteCardState extends ConsumerState { if (mounted) { if (Util.isDesktop) { - await Navigator.of(context).pushNamed( - DesktopWalletView.routeName, - arguments: walletId, - ); + await Navigator.of( + context, + ).pushNamed(DesktopWalletView.routeName, arguments: walletId); } else { - await Navigator.of(context).pushNamed( - WalletView.routeName, - arguments: walletId, - ); + await Navigator.of( + context, + ).pushNamed(WalletView.routeName, arguments: walletId); } } }, @@ -183,17 +193,16 @@ class _FavoriteCardState extends ConsumerState { child: Text( ref.watch(pWalletName(walletId)), style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of( + context, + ).extension()!.textFavoriteCard, ), overflow: TextOverflow.fade, ), ), SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), @@ -202,36 +211,24 @@ class _FavoriteCardState extends ConsumerState { ), Builder( builder: (context) { - final balance = ref.watch( - pWalletBalance(walletId), - ); + final balance = ref.watch(pWalletBalance(walletId)); Amount total = balance.total; if (coin is Firo) { - total += ref - .watch( - pWalletBalanceSecondary(walletId), - ) - .total; - total += ref - .watch( - pWalletBalanceTertiary(walletId), - ) - .total; + total += + ref.watch(pWalletBalanceSecondary(walletId)).total; + total += + ref.watch(pWalletBalanceTertiary(walletId)).total; } Amount fiatTotal = Amount.zero; - if (externalCalls && total > Amount.zero) { - fiatTotal = (total.decimal * - ref - .watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value.getPrice(coin), - ), - ) - .item1) - .toAmount(fractionDigits: 2); + if (externalCalls && + total > Amount.zero && + price != null) { + fiatTotal = (total.decimal * price).toAmount( + fractionDigits: 2, + ); } return Column( @@ -243,35 +240,26 @@ class _FavoriteCardState extends ConsumerState { ref.watch(pAmountFormatter(coin)).format(total), style: STextStyles.titleBold12(context).copyWith( fontSize: 16, - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of(context) + .extension()! + .textFavoriteCard, ), ), ), - if (externalCalls) - const SizedBox( - height: 4, - ), - if (externalCalls) + if (externalCalls && price != null) + const SizedBox(height: 4), + if (externalCalls && price != null) Text( - "${fiatTotal.fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider.select( - (value) => value.locale, - ), - ), - )} ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - )}", - style: - STextStyles.itemSubtitle12(context).copyWith( + "${fiatTotal.fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.itemSubtitle12( + context, + ).copyWith( fontSize: 10, - color: Theme.of(context) - .extension()! - .textFavoriteCard, + color: + Theme.of(context) + .extension()! + .textFavoriteCard, ), ), ], @@ -300,11 +288,6 @@ class CardOverlayStack extends StatelessWidget { @override Widget build(BuildContext context) { - return Stack( - children: [ - background, - child, - ], - ); + return Stack(children: [background, child]); } } diff --git a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart index 938baac71..64d9ecbc9 100644 --- a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart +++ b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart @@ -46,8 +46,9 @@ class WalletListItem extends ConsumerWidget { // debugPrint("BUILD: $runtimeType"); final walletCountString = walletCount == 1 ? "$walletCount wallet" : "$walletCount wallets"; - final currency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final currency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); return RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -57,8 +58,9 @@ class WalletListItem extends ConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 13), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), onPressed: () async { // Check if Tor is enabled... @@ -66,11 +68,10 @@ class WalletListItem extends ConsumerWidget { // ... and if the coin supports Tor. if (!coin.torSupport) { // If not, show a Tor warning dialog. - final shouldContinue = await showDialog( + final shouldContinue = + await showDialog( context: context, - builder: (_) => TorWarningDialog( - coin: coin, - ), + builder: (_) => TorWarningDialog(coin: coin), ) ?? false; if (!shouldContinue) { @@ -100,8 +101,9 @@ class WalletListItem extends ConsumerWidget { final Future loadFuture; if (wallet is ExternalWallet) { - loadFuture = - wallet.init().then((value) async => await (wallet).open()); + loadFuture = wallet.init().then( + (value) async => await (wallet).open(), + ); } else { loadFuture = wallet.init(); } @@ -113,63 +115,67 @@ class WalletListItem extends ConsumerWidget { ); if (context.mounted) { unawaited( - Navigator.of(context).pushNamed( - WalletView.routeName, - arguments: wallet.walletId, - ), + Navigator.of( + context, + ).pushNamed(WalletView.routeName, arguments: wallet.walletId), ); } } else { unawaited( - Navigator.of(context).pushNamed( - WalletsOverview.routeName, - arguments: coin, - ), + Navigator.of( + context, + ).pushNamed(WalletsOverview.routeName, arguments: coin), ); } }, child: Row( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 28, height: 28, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Consumer( builder: (_, ref, __) { - final tuple = ref.watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin)), - ); - final calls = - ref.watch(prefsChangeNotifierProvider).externalCalls; + Color percentChangedColor = + Theme.of(context).extension()!.textDark; + String? priceString; + double? percentChange; + if (ref.watch( + prefsChangeNotifierProvider.select((s) => s.externalCalls), + )) { + final price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ); - final priceString = - tuple.item1.toAmount(fractionDigits: 2).fiatString( + if (price != null) { + priceString = price.value + .toAmount(fractionDigits: 2) + .fiatString( locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), ); + percentChange = price.change24h; - final double percentChange = tuple.item2; - - var percentChangedColor = - Theme.of(context).extension()!.textDark; - if (percentChange > 0) { - percentChangedColor = Theme.of(context) - .extension()! - .accentColorGreen; - } else if (percentChange < 0) { - percentChangedColor = Theme.of(context) - .extension()! - .accentColorRed; + if (percentChange > 0) { + percentChangedColor = + Theme.of( + context, + ).extension()!.accentColorGreen; + } else if (percentChange < 0) { + percentChangedColor = + Theme.of( + context, + ).extension()!.accentColorRed; + } + } } return Column( @@ -182,16 +188,14 @@ class WalletListItem extends ConsumerWidget { style: STextStyles.titleBold12(context), ), const Spacer(), - if (calls) + if (priceString != null) Text( "$priceString $currency/${coin.ticker}", style: STextStyles.itemSubtitle(context), ), ], ), - const SizedBox( - height: 1, - ), + const SizedBox(height: 1), Row( children: [ Text( @@ -199,12 +203,12 @@ class WalletListItem extends ConsumerWidget { style: STextStyles.itemSubtitle(context), ), const Spacer(), - if (calls) + if (percentChange != null) Text( "${percentChange.toStringAsFixed(2)}%", - style: STextStyles.itemSubtitle(context).copyWith( - color: percentChangedColor, - ), + style: STextStyles.itemSubtitle( + context, + ).copyWith(color: percentChangedColor), ), ], ), diff --git a/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart b/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart index 023b9fb79..476a3eb24 100644 --- a/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart @@ -10,6 +10,7 @@ import 'dart:io'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; @@ -63,6 +64,15 @@ class _DesktopPaynymSendDialogState final coin = ref.watch(pWalletCoin(widget.walletId)); + Decimal? price; + if (ref.watch(prefsChangeNotifierProvider.select((s) => s.externalCalls))) { + price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin)?.value, + ), + ); + } + return DesktopDialog( maxHeight: double.infinity, maxWidth: 580, @@ -90,15 +100,11 @@ class _DesktopPaynymSendDialogState child: Row( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 36, height: 36, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -108,15 +114,14 @@ class _DesktopPaynymSendDialogState overflow: TextOverflow.ellipsis, maxLines: 1, ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( "Available balance", style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ], @@ -128,7 +133,9 @@ class _DesktopPaynymSendDialogState crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalance(widget.walletId)) .spendable, @@ -136,28 +143,18 @@ class _DesktopPaynymSendDialogState style: STextStyles.titleBold12(context), textAlign: TextAlign.right, ), - const SizedBox( - height: 2, - ), - Text( - "${(ref.watch(pWalletBalance(widget.walletId)).spendable.decimal * ref.watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value.getPrice(coin).item1, - ), - )).toAmount(fractionDigits: 2).fiatString( - locale: locale, - )} ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, + if (price != null) const SizedBox(height: 2), + if (price != null) + Text( + "${(ref.watch(pWalletBalance(widget.walletId)).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.baseXS(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), - )}", - style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + textAlign: TextAlign.right, ), - textAlign: TextAlign.right, - ), ], ), ), @@ -165,15 +162,9 @@ class _DesktopPaynymSendDialogState ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, right: 32, bottom: 32), child: DesktopSend( walletId: widget.walletId, accountLite: widget.accountLite, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart b/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart index 066ae9073..45b5d710e 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart @@ -10,6 +10,7 @@ import 'dart:io'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; @@ -53,12 +54,11 @@ class _WalletTableState extends ConsumerState { return ConditionalParent( condition: index + 1 == walletsByCoin.length, - builder: (child) => Padding( - padding: const EdgeInsets.only( - bottom: 16, - ), - child: child, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: child, + ), child: DesktopWalletSummaryRow( key: Key("DesktopWalletSummaryRow_key_${coin.identifier}"), coin: coin, @@ -66,9 +66,7 @@ class _WalletTableState extends ConsumerState { ), ); }, - separatorBuilder: (_, __) => const SizedBox( - height: 10, - ), + separatorBuilder: (_, __) => const SizedBox(height: 10), itemCount: walletsByCoin.length, ); } @@ -96,11 +94,10 @@ class _DesktopWalletSummaryRowState // ... and if the coin supports Tor. if (!widget.coin.torSupport) { // If not, show a Tor warning dialog. - final shouldContinue = await showDialog( + final shouldContinue = + await showDialog( context: context, - builder: (_) => TorWarningDialog( - coin: widget.coin, - ), + builder: (_) => TorWarningDialog(coin: widget.coin), ) ?? false; if (!shouldContinue) { @@ -121,8 +118,12 @@ class _DesktopWalletSummaryRowState await _checkTor(); if (mounted) { - final wallet = ref.read(pWallets).wallets.firstWhere( - (e) => e.cryptoCurrency.identifier == widget.coin.identifier); + final wallet = ref + .read(pWallets) + .wallets + .firstWhere( + (e) => e.cryptoCurrency.identifier == widget.coin.identifier, + ); final canContinue = await checkShowNodeTorSettingsMismatch( context: context, @@ -139,8 +140,9 @@ class _DesktopWalletSummaryRowState final Future loadFuture; if (wallet is ExternalWallet) { - loadFuture = - wallet.init().then((value) async => await (wallet).open()); + loadFuture = wallet.init().then( + (value) async => await (wallet).open(), + ); } else { loadFuture = wallet.init(); } @@ -152,10 +154,9 @@ class _DesktopWalletSummaryRowState ); if (mounted) { - await Navigator.of(context).pushNamed( - DesktopWalletView.routeName, - arguments: wallet.walletId, - ); + await Navigator.of( + context, + ).pushNamed(DesktopWalletView.routeName, arguments: wallet.walletId); } } } finally { @@ -173,40 +174,41 @@ class _DesktopWalletSummaryRowState if (mounted) { await showDialog( context: context, - builder: (_) => DesktopDialog( - maxHeight: 600, - maxWidth: 700, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (_) => DesktopDialog( + maxHeight: 600, + maxWidth: 700, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "${widget.coin.prettyName} (${widget.coin.ticker}) wallets", - style: STextStyles.desktopH3(context), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "${widget.coin.prettyName} (${widget.coin.ticker}) wallets", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: WalletsOverview( + coin: widget.coin, + navigatorState: Navigator.of(context), + ), ), ), - const DesktopDialogCloseButton(), ], ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: WalletsOverview( - coin: widget.coin, - navigatorState: Navigator.of(context), - ), - ), - ), - ], - ), - ), + ), ); } } finally { @@ -216,6 +218,12 @@ class _DesktopWalletSummaryRowState @override Widget build(BuildContext context) { + final price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(widget.coin), + ), + ); + return Breathing( child: RoundedWhiteContainer( padding: const EdgeInsets.all(20), @@ -229,15 +237,11 @@ class _DesktopWalletSummaryRowState child: Row( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(widget.coin)), - ), + File(ref.watch(coinIconProvider(widget.coin))), width: 28, height: 28, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( widget.coin.prettyName, style: STextStyles.desktopTextExtraSmall(context).copyWith( @@ -260,12 +264,11 @@ class _DesktopWalletSummaryRowState ), ), ), - Expanded( - flex: 6, - child: TablePriceInfo( - coin: widget.coin, + if (price != null) + Expanded( + flex: 6, + child: TablePriceInfo(coin: widget.coin, price: price), ), - ), ], ), ), @@ -274,43 +277,30 @@ class _DesktopWalletSummaryRowState } class TablePriceInfo extends ConsumerWidget { - const TablePriceInfo({super.key, required this.coin}); + const TablePriceInfo({super.key, required this.coin, required this.price}); final CryptoCurrency coin; + final ({Decimal value, double change24h}) price; @override Widget build(BuildContext context, WidgetRef ref) { - final tuple = ref.watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value.getPrice(coin), - ), - ); - final currency = ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), + prefsChangeNotifierProvider.select((value) => value.currency), ); final priceString = Amount.fromDecimal( - tuple.item1, + price.value, fractionDigits: 2, ).fiatString( - locale: ref - .watch( - localeServiceChangeNotifierProvider.notifier, - ) - .locale, + locale: ref.watch(localeServiceChangeNotifierProvider.notifier).locale, ); - final double percentChange = tuple.item2; - var percentChangedColor = Theme.of(context).extension()!.textDark; - if (percentChange > 0) { + if (price.change24h > 0) { percentChangedColor = Theme.of(context).extension()!.accentColorGreen; - } else if (percentChange < 0) { + } else if (price.change24h < 0) { percentChangedColor = Theme.of(context).extension()!.accentColorRed; } @@ -325,10 +315,10 @@ class TablePriceInfo extends ConsumerWidget { ), ), Text( - "${percentChange.toStringAsFixed(2)}%", - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: percentChangedColor, - ), + "${price.change24h.toStringAsFixed(2)}%", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith(color: percentChangedColor), ), ], ); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 009893e7e..9dc0b0f91 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -155,13 +155,19 @@ class _DesktopSendState extends ConsumerState { try { _processQrCodeData(qrResult); } catch (e, s) { - Logging.instance - .e("Error processing QR code data", error: e, stackTrace: s); + Logging.instance.e( + "Error processing QR code data", + error: e, + stackTrace: s, + ); } } } catch (e, s) { - Logging.instance - .e("Error opening QR code scanner dialog", error: e, stackTrace: s); + Logging.instance.e( + "Error opening QR code scanner dialog", + error: e, + stackTrace: s, + ); } } @@ -204,10 +210,7 @@ class _DesktopSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -221,29 +224,20 @@ class _DesktopSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Text( "You are about to send your entire balance. Would you like to continue?", textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Row( children: [ Expanded( @@ -255,9 +249,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: ButtonHeight.l, @@ -301,7 +293,8 @@ class _DesktopSendState extends ConsumerState { padding: const EdgeInsets.all(32), child: BuildingTransactionDialog( coin: wallet.info.coin, - isSpark: wallet is FiroWallet && + isSpark: + wallet is FiroWallet && ref .read(publicPrivateBalanceStateProvider.state) .state == @@ -319,11 +312,7 @@ class _DesktopSendState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); TxData txData; Future txDataFuture; @@ -344,11 +333,12 @@ class _DesktopSendState extends ConsumerState { ], satsPerVByte: isCustomFee ? customFeeRate : null, feeRateType: feeRate, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } else if (wallet is FiroWallet) { @@ -367,30 +357,28 @@ class _DesktopSendState extends ConsumerState { ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } else { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } @@ -400,11 +388,7 @@ class _DesktopSendState extends ConsumerState { txDataFuture = wallet.prepareSendLelantus( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], ), ); @@ -413,25 +397,23 @@ class _DesktopSendState extends ConsumerState { case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: ref.read(pValidSparkSendToAddress) - ? null - : [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], - sparkRecipients: ref.read(pValidSparkSendToAddress) - ? [ - ( - address: _address!, - amount: amount, - memo: memoController.text, - isChange: false, - ), - ] - : null, + recipients: + ref.read(pValidSparkSendToAddress) + ? null + : [ + (address: _address!, amount: amount, isChange: false), + ], + sparkRecipients: + ref.read(pValidSparkSendToAddress) + ? [ + ( + address: _address!, + amount: amount, + memo: memoController.text, + isChange: false, + ), + ] + : null, ), ); break; @@ -440,29 +422,21 @@ class _DesktopSendState extends ConsumerState { final memo = isStellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); txData = results.first as TxData; @@ -473,35 +447,29 @@ class _DesktopSendState extends ConsumerState { note: _note ?? "PayNym send", ); } else { - txData = txData.copyWith( - note: _note ?? "", - ); + txData = txData.copyWith(note: _note ?? ""); if (coin is Epiccash) { - txData = txData.copyWith( - noteOnChain: _onChainNote ?? "", - ); + txData = txData.copyWith(noteOnChain: _onChainNote ?? ""); } } // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: ConfirmTransactionView( - txData: txData, - walletId: walletId, - onSuccess: clearSendForm, - isPaynymTransaction: isPaynymSend, - routeOnSuccessName: DesktopHomeView.routeName, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: ConfirmTransactionView( + txData: txData, + walletId: walletId, + onSuccess: clearSendForm, + isPaynymTransaction: isPaynymSend, + routeOnSuccessName: DesktopHomeView.routeName, + ), + ), ), ); } @@ -509,10 +477,7 @@ class _DesktopSendState extends ConsumerState { Logging.instance.e("Desktop send: ", error: e, stackTrace: s); if (mounted) { // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( @@ -522,10 +487,7 @@ class _DesktopSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -539,25 +501,18 @@ class _DesktopSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Text( e.toString(), textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Row( children: [ Expanded( @@ -572,9 +527,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), ], ), ], @@ -602,9 +555,9 @@ class _DesktopSendState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( - cryptoAmountController.text, - ); + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse(cryptoAmountController.text); final Amount? amount; if (cryptoAmount != null) { amount = cryptoAmount; @@ -615,9 +568,9 @@ class _DesktopSendState extends ConsumerState { _cachedAmountToSend = amount; final price = - ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1; + ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin)?.value; - if (price > Decimal.zero) { + if (price != null && price > Decimal.zero) { final String fiatAmountString = (amount.decimal * price) .toAmount(fractionDigits: 2) .fiatString( @@ -685,14 +638,15 @@ class _DesktopSendState extends ConsumerState { } else { final wallet = ref.read(pWallets).getWallet(walletId); if (wallet is SparkInterface) { - ref.read(pValidSparkSendToAddress.notifier).state = - SparkInterface.validateSparkAddress( + ref + .read(pValidSparkSendToAddress.notifier) + .state = SparkInterface.validateSparkAddress( address: address ?? "", isTestNet: wallet.cryptoCurrency.network.isTestNet, ); - ref.read(pIsExchangeAddress.state).state = - (coin as Firo).isExchangeAddress(address ?? ""); + ref.read(pIsExchangeAddress.state).state = (coin as Firo) + .isExchangeAddress(address ?? ""); if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && ref.read(pIsExchangeAddress) && @@ -705,8 +659,8 @@ class _DesktopSendState extends ConsumerState { } } - ref.read(pValidSendToAddress.notifier).state = - wallet.cryptoCurrency.validateAddress(address ?? ""); + ref.read(pValidSendToAddress.notifier).state = wallet.cryptoCurrency + .validateAddress(address ?? ""); } } @@ -725,9 +679,9 @@ class _DesktopSendState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); + final amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: coin.fractionDigits); cryptoAmountController.text = ref .read(pAmountFormatter(coin)) .format(amount, withUnitName: false); @@ -818,26 +772,26 @@ class _DesktopSendState extends ConsumerState { final Amount? amount; if (baseAmount != null) { final _price = - ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1; + ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin)?.value; - if (_price == Decimal.zero) { + if (_price == null || _price == Decimal.zero) { amount = Decimal.zero.toAmount(fractionDigits: coin.fractionDigits); } else { - amount = baseAmount <= Amount.zero - ? Decimal.zero.toAmount(fractionDigits: coin.fractionDigits) - : (baseAmount.decimal / _price) - .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) - .toAmount(fractionDigits: coin.fractionDigits); + amount = + baseAmount <= Amount.zero + ? Decimal.zero.toAmount(fractionDigits: coin.fractionDigits) + : (baseAmount.decimal / _price) + .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) + .toAmount(fractionDigits: coin.fractionDigits); } if (_cachedAmountToSend != null && _cachedAmountToSend == amount) { return; } _cachedAmountToSend = amount; - final amountString = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final amountString = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChangeLock = true; cryptoAmountController.text = amountString; @@ -865,10 +819,9 @@ class _DesktopSendState extends ConsumerState { } Amount _selectedUtxosAmount(Set utxos) => Amount( - rawValue: - utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), - fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, - ); + rawValue: utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), + fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, + ); Future _sendAllTapped(bool showCoinControl) async { final Amount amount; @@ -891,20 +844,20 @@ class _DesktopSendState extends ConsumerState { amount = ref.read(pWalletBalance(walletId)).spendable; } - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); } void _showDesktopCoinControl() async { final amount = ref.read(pSendAmount); await showDialog( context: context, - builder: (context) => DesktopCoinControlUseDialog( - walletId: widget.walletId, - amountToSend: amount, - ), + builder: + (context) => DesktopCoinControlUseDialog( + walletId: widget.walletId, + amountToSend: amount, + ), ); } @@ -1033,7 +986,8 @@ class _DesktopSendState extends ConsumerState { } }); - final showCoinControl = ref.watch( + final showCoinControl = + ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, ), @@ -1044,23 +998,19 @@ class _DesktopSendState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), if (coin is Firo) Text( "Send from", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - if (coin is Firo) - const SizedBox( - height: 10, - ), + if (coin is Firo) const SizedBox(height: 10), if (coin is Firo) DropdownButtonHideUnderline( child: DropdownButton2( @@ -1075,11 +1025,11 @@ class _DesktopSendState extends ConsumerState { "Spark balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalanceTertiary(walletId)) .spendable, @@ -1099,11 +1049,11 @@ class _DesktopSendState extends ConsumerState { "Lelantus balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalanceSecondary(walletId)) .spendable, @@ -1121,11 +1071,11 @@ class _DesktopSendState extends ConsumerState { "Public balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref.watch(pWalletBalance(walletId)).spendable, ), style: STextStyles.itemSubtitle(context), @@ -1157,45 +1107,37 @@ class _DesktopSendState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), ), ), - if (coin is Firo) - const SizedBox( - height: 20, - ), + if (coin is Firo) const SizedBox(height: 20), if (isPaynymSend) Text( "Send to PayNym address", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (isPaynymSend) - const SizedBox( - height: 10, - ), + if (isPaynymSend) const SizedBox(height: 10), if (isPaynymSend) TextField( key: const Key("sendViewPaynymAddressFieldKey"), controller: sendToController, enabled: false, readOnly: true, - style: STextStyles.desktopTextFieldLabel(context).copyWith( - fontSize: 16, - ), + style: STextStyles.desktopTextFieldLabel( + context, + ).copyWith(fontSize: 16), decoration: const InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 18, @@ -1203,19 +1145,17 @@ class _DesktopSendState extends ConsumerState { ), ), ), - if (isPaynymSend) - const SizedBox( - height: 20, - ), + if (isPaynymSend) const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Amount", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), @@ -1229,9 +1169,7 @@ class _DesktopSendState extends ConsumerState { ), ], ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1241,12 +1179,13 @@ class _DesktopSendState extends ConsumerState { key: const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1270,9 +1209,10 @@ class _DesktopSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -1281,19 +1221,17 @@ class _DesktopSendState extends ConsumerState { child: Text( ref.watch(pAmountUnit(coin)).unitForCoin(coin), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - if (Prefs.instance.externalCalls) - const SizedBox( - height: 10, - ), + if (Prefs.instance.externalCalls) const SizedBox(height: 10), if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, @@ -1304,18 +1242,16 @@ class _DesktopSendState extends ConsumerState { key: const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ - AmountInputFormatter( - decimals: 2, - locale: locale, - ), + AmountInputFormatter(decimals: 2, locale: locale), // // regex to validate a fiat amount with 2 decimal places // TextInputFormatter.withFunction((oldValue, newValue) => // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') @@ -1332,9 +1268,10 @@ class _DesktopSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -1342,23 +1279,22 @@ class _DesktopSendState extends ConsumerState { padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - if (showCoinControl) - const SizedBox( - height: 10, - ), + if (showCoinControl) const SizedBox(height: 10), if (showCoinControl) RoundedContainer( color: Colors.transparent, @@ -1372,31 +1308,28 @@ class _DesktopSendState extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall(context), ), CustomTextButton( - text: ref.watch(desktopUseUTXOs.state).state.isEmpty - ? "Select coins" - : "Selected coins (${ref.watch(desktopUseUTXOs.state).state.length})", + text: + ref.watch(desktopUseUTXOs.state).state.isEmpty + ? "Select coins" + : "Selected coins (${ref.watch(desktopUseUTXOs.state).state.length})", onTap: _showDesktopCoinControl, ), ], ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), if (!isPaynymSend) Text( "Send to", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - if (!isPaynymSend) - const SizedBox( - height: 10, - ), + if (!isPaynymSend) const SizedBox(height: 10), if (!isPaynymSend) ClipRRect( borderRadius: BorderRadius.circular( @@ -1424,7 +1357,10 @@ class _DesktopSendState extends ConsumerState { final trimmed = newValue; if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { - final parsed = AddressUtils.parsePaymentUri(trimmed, logging: Logging.instance); + final parsed = AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); if (parsed != null) { _applyUri(parsed); } else { @@ -1443,9 +1379,10 @@ class _DesktopSendState extends ConsumerState { }, focusNode: _addressFocusNode, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -1461,76 +1398,80 @@ class _DesktopSendState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _addressToggleFlag ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: pasteAddress, - child: sendToController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + key: const Key( + "sendViewPasteAddressFieldButtonKey", ), + onTap: pasteAddress, + child: + sendToController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( key: const Key("sendViewAddressBookButtonKey"), onTap: () async { - final entry = - await showDialog( + final entry = await showDialog< + ContactAddressEntry? + >( context: context, - builder: (context) => DesktopDialog( - maxWidth: 696, - maxHeight: 600, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 696, + maxHeight: 600, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: STextStyles.desktopH3( - context, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Address book", + style: STextStyles.desktopH3( + context, + ), + ), ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: AddressBookAddressChooser( + coin: coin, ), ), - const DesktopDialogCloseButton(), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: coin, - ), - ), - ], - ), - ), + ), ); if (entry != null) { @@ -1552,9 +1493,7 @@ class _DesktopSendState extends ConsumerState { TextFieldIconButton( semanticsLabel: "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key( - "sendViewScanQrButtonKey", - ), + key: const Key("sendViewScanQrButtonKey"), onTap: scanWebcam, child: const QrCodeIcon(), ), @@ -1575,18 +1514,20 @@ class _DesktopSendState extends ConsumerState { } else if (coin is Firo) { if (firoType == FiroType.lelantus) { if (_data != null && _data.contactLabel == _address) { - error = SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: coin.network.isTestNet, - ) - ? "Lelantus to Spark not supported" - : null; + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: coin.network.isTestNet, + ) + ? "Lelantus to Spark not supported" + : null; } else if (ref.watch(pValidSparkSendToAddress)) { error = "Lelantus to Spark not supported"; } else { - error = ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; } } else { if (_data != null && _data.contactLabel == _address) { @@ -1614,17 +1555,15 @@ class _DesktopSendState extends ConsumerState { return Align( alignment: Alignment.topLeft, child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), + padding: const EdgeInsets.only(left: 12.0, top: 4.0), child: Text( error, textAlign: TextAlign.left, style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + color: + Theme.of( + context, + ).extension()!.textError, ), ), ), @@ -1635,9 +1574,7 @@ class _DesktopSendState extends ConsumerState { if (isStellar || (ref.watch(pValidSparkSendToAddress) && firoType != FiroType.lelantus)) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (isStellar || (ref.watch(pValidSparkSendToAddress) && firoType != FiroType.lelantus)) @@ -1659,9 +1596,10 @@ class _DesktopSendState extends ConsumerState { setState(() {}); }, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -1678,9 +1616,10 @@ class _DesktopSendState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -1688,9 +1627,10 @@ class _DesktopSendState extends ConsumerState { TextFieldIconButton( key: const Key("sendViewPasteMemoButtonKey"), onTap: pasteMemo, - child: memoController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + child: + memoController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), ), ], ), @@ -1699,14 +1639,11 @@ class _DesktopSendState extends ConsumerState { ), ), ), - if (!isPaynymSend) - const SizedBox( - height: 20, - ), + if (!isPaynymSend) const SizedBox(height: 20), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) ConditionalParent( - condition: ref.watch(pWallets).getWallet(walletId) - is ElectrumXInterface && + condition: + ref.watch(pWallets).getWallet(walletId) is ElectrumXInterface && !(((coin is Firo) && (ref.watch(publicPrivateBalanceStateProvider.state).state == FiroType.lelantus || @@ -1714,165 +1651,163 @@ class _DesktopSendState extends ConsumerState { .watch(publicPrivateBalanceStateProvider.state) .state == FiroType.spark))), - builder: (child) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - child, - CustomTextButton( - text: "Edit", - onTap: () async { - feeSelectionResult = await showDialog< - ( - FeeRateType, - String?, - String?, - )?>( - context: context, - builder: (_) => DesktopFeeDialog( - walletId: walletId, - ), - ); - - if (feeSelectionResult != null) { - if (isCustomFee && - feeSelectionResult!.$1 != FeeRateType.custom) { - isCustomFee = false; - } else if (!isCustomFee && - feeSelectionResult!.$1 == FeeRateType.custom) { - isCustomFee = true; - } - } - - setState(() {}); - }, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + child, + CustomTextButton( + text: "Edit", + onTap: () async { + feeSelectionResult = + await showDialog<(FeeRateType, String?, String?)?>( + context: context, + builder: + (_) => DesktopFeeDialog(walletId: walletId), + ); + + if (feeSelectionResult != null) { + if (isCustomFee && + feeSelectionResult!.$1 != FeeRateType.custom) { + isCustomFee = false; + } else if (!isCustomFee && + feeSelectionResult!.$1 == FeeRateType.custom) { + isCustomFee = true; + } + } + + setState(() {}); + }, + ), + ], ), - ], - ), child: Text( "Transaction fee" "${isCustomFee ? "" : " (${coin is Ethereum ? "max" : "estimated"})"}", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), ), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) if (!isCustomFee) Padding( padding: const EdgeInsets.all(10), - child: (feeSelectionResult?.$2 == null) - ? FutureBuilder( - future: ref.watch( - pWallets.select( - (value) => value.getWallet(walletId).fees, + child: + (feeSelectionResult?.$2 == null) + ? FutureBuilder( + future: ref.watch( + pWallets.select( + (value) => value.getWallet(walletId).fees, + ), ), - ), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - return DesktopFeeItem( - feeObject: snapshot.data, - feeRateType: FeeRateType.average, - walletId: walletId, - isButton: false, - feeFor: ({ - required Amount amount, - required FeeRateType feeRateType, - required int feeRate, - required CryptoCurrency coin, - }) async { - if (ref - .read(feeSheetSessionCacheProvider) - .average[amount] == - null) { - final wallet = - ref.read(pWallets).getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero.TransactionPriority.medium.value, - ); - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = fee; - } else if ((coin is Firo) && + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + return DesktopFeeItem( + feeObject: snapshot.data, + feeRateType: FeeRateType.average, + walletId: walletId, + isButton: false, + feeFor: ({ + required Amount amount, + required FeeRateType feeRateType, + required int feeRate, + required CryptoCurrency coin, + }) async { + if (ref + .read(feeSheetSessionCacheProvider) + .average[amount] == + null) { + final wallet = ref + .read(pWallets) + .getWallet(walletId); + + if (coin is Monero || coin is Wownero) { + final fee = await wallet.estimateFeeFor( + amount, + lib_monero + .TransactionPriority + .medium + .value, + ); ref + .read(feeSheetSessionCacheProvider) + .average[amount] = + fee; + } else if ((coin is Firo) && + ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) { + final firoWallet = wallet as FiroWallet; + + if (ref .read( publicPrivateBalanceStateProvider .state, ) - .state != - FiroType.public) { - final firoWallet = wallet as FiroWallet; - - if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.lelantus) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await firoWallet - .estimateFeeForLelantus(amount); - } else if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.spark) { + .state == + FiroType.lelantus) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForLelantus(amount); + } else if (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state == + FiroType.spark) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForSpark(amount); + } + } else { ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await firoWallet - .estimateFeeForSpark(amount); + .read(feeSheetSessionCacheProvider) + .average[amount] = await wallet + .estimateFeeFor(amount, feeRate); } - } else { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await wallet.estimateFeeFor( - amount, - feeRate, - ); } - } - return ref - .read(feeSheetSessionCacheProvider) - .average[amount]!; - }, - isSelected: true, - ); - } else { - return Row( - children: [ - AnimatedText( - stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + return ref + .read(feeSheetSessionCacheProvider) + .average[amount]!; + }, + isSelected: true, + ); + } else { + return Row( + children: [ + AnimatedText( + stringsToLoopThrough: stringsToLoopThrough, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + ), ), - ), - ], - ); - } - }, - ) - : (coin is Firo) && + ], + ); + } + }, + ) + : (coin is Firo) && ref .watch( publicPrivateBalanceStateProvider.state, @@ -1880,54 +1815,49 @@ class _DesktopSendState extends ConsumerState { .state == FiroType.lelantus ? Text( - "~${ref.watch(pAmountFormatter(coin)).format( - Amount( - rawValue: BigInt.parse("3794"), - fractionDigits: coin.fractionDigits, - ), - indicatePrecisionLoss: false, - )}", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, - ) - : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - feeSelectionResult?.$2 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( + "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, + ).extension()!.textFieldActiveText, + ), + textAlign: TextAlign.left, + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + feeSelectionResult?.$2 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, ), - Text( - feeSelectionResult?.$3 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ), + textAlign: TextAlign.left, + ), + Text( + feeSelectionResult?.$3 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), - ], - ), + ), + ], + ), ), if (isCustomFee) Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, - ), + padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( coin: coin, onSatVByteChanged: (rate) { @@ -1935,9 +1865,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), PrimaryButton( buttonHeight: ButtonHeight.l, label: "Preview send", diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 647b1e1cc..a69c6ef05 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -33,7 +33,6 @@ import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/clipboard_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/logger.dart'; -import '../../../../utilities/prefs.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; @@ -109,16 +108,15 @@ class _DesktopTokenSendState extends ConsumerState { final tokenWallet = ref.read(pCurrentTokenWallet)!; final Amount amount = _amountToSend!; - final Amount availableBalance = ref - .read( - pTokenBalance( - ( - walletId: walletId, - contractAddress: tokenWallet.tokenContract.address - ), - ), - ) - .spendable; + final Amount availableBalance = + ref + .read( + pTokenBalance(( + walletId: walletId, + contractAddress: tokenWallet.tokenContract.address, + )), + ) + .spendable; // confirm send all if (amount == availableBalance) { @@ -131,10 +129,7 @@ class _DesktopTokenSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -148,29 +143,20 @@ class _DesktopTokenSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Text( "You are about to send your entire balance. Would you like to continue?", textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Row( children: [ Expanded( @@ -182,9 +168,7 @@ class _DesktopTokenSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: ButtonHeight.l, @@ -241,71 +225,51 @@ class _DesktopTokenSendState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); TxData txData; Future txDataFuture; txDataFuture = tokenWallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], feeRateType: ref.read(feeRateTypeStateProvider), nonce: int.tryParse(nonceController.text), ), ); - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); txData = results.first as TxData; if (!wasCancelled && mounted) { - txData = txData.copyWith( - note: _note ?? "", - ); + txData = txData.copyWith(note: _note ?? ""); // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: ConfirmTransactionView( - txData: txData, - walletId: walletId, - onSuccess: clearSendForm, - isTokenTx: true, - routeOnSuccessName: DesktopHomeView.routeName, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: ConfirmTransactionView( + txData: txData, + walletId: walletId, + onSuccess: clearSendForm, + isTokenTx: true, + routeOnSuccessName: DesktopHomeView.routeName, + ), + ), ), ); } } catch (e) { if (mounted) { // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( @@ -315,10 +279,7 @@ class _DesktopTokenSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -332,25 +293,18 @@ class _DesktopTokenSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: SelectableText( e.toString(), textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Row( children: [ Expanded( @@ -365,9 +319,7 @@ class _DesktopTokenSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), ], ), ], @@ -395,7 +347,9 @@ class _DesktopTokenSendState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse( cryptoAmountController.text, ethContract: ref.read(pCurrentTokenWallet)!.tokenContract, ); @@ -408,14 +362,15 @@ class _DesktopTokenSendState extends ConsumerState { } _cachedAmountToSend = _amountToSend; - final price = ref - .read(priceAnd24hChangeNotifierProvider) - .getTokenPrice( - ref.read(pCurrentTokenWallet)!.tokenContract.address, - ) - .item1; + final price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getTokenPrice( + ref.read(pCurrentTokenWallet)!.tokenContract.address, + ) + ?.value; - if (price > Decimal.zero) { + if (price != null && price > Decimal.zero) { final String fiatAmountString = Amount.fromDecimal( _amountToSend!.decimal * price, fractionDigits: 2, @@ -495,10 +450,9 @@ class _DesktopTokenSendState extends ConsumerState { fractionDigits: ref.read(pCurrentTokenWallet)!.tokenContract.decimals, ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _amountToSend = amount; } @@ -554,33 +508,39 @@ class _DesktopTokenSendState extends ConsumerState { if (baseAmountString.isNotEmpty && baseAmountString != "." && baseAmountString != ",") { - final baseAmount = baseAmountString.contains(",") - ? Decimal.parse(baseAmountString.replaceFirst(",", ".")) - .toAmount(fractionDigits: 2) - : Decimal.parse(baseAmountString).toAmount(fractionDigits: 2); - - final Decimal _price = ref - .read(priceAnd24hChangeNotifierProvider) - .getTokenPrice( - ref.read(pCurrentTokenWallet)!.tokenContract.address, - ) - .item1; - - if (_price == Decimal.zero) { + final baseAmount = + baseAmountString.contains(",") + ? Decimal.parse( + baseAmountString.replaceFirst(",", "."), + ).toAmount(fractionDigits: 2) + : Decimal.parse(baseAmountString).toAmount(fractionDigits: 2); + + final Decimal? _price = + ref + .read(priceAnd24hChangeNotifierProvider) + .getTokenPrice( + ref.read(pCurrentTokenWallet)!.tokenContract.address, + ) + ?.value; + + if (_price == null || _price == Decimal.zero) { _amountToSend = Decimal.zero.toAmount(fractionDigits: tokenDecimals); } else { - _amountToSend = baseAmount <= Amount.zero - ? Decimal.zero.toAmount(fractionDigits: tokenDecimals) - : (baseAmount.decimal / _price) - .toDecimal(scaleOnInfinitePrecision: tokenDecimals) - .toAmount(fractionDigits: tokenDecimals); + _amountToSend = + baseAmount <= Amount.zero + ? Decimal.zero.toAmount(fractionDigits: tokenDecimals) + : (baseAmount.decimal / _price) + .toDecimal(scaleOnInfinitePrecision: tokenDecimals) + .toAmount(fractionDigits: tokenDecimals); } if (_cachedAmountToSend != null && _cachedAmountToSend == _amountToSend) { return; } _cachedAmountToSend = _amountToSend; - final amountString = ref.read(pAmountFormatter(coin)).format( + final amountString = ref + .read(pAmountFormatter(coin)) + .format( _amountToSend!, withUnitName: false, ethContract: ref.read(pCurrentTokenWallet)!.tokenContract, @@ -602,19 +562,15 @@ class _DesktopTokenSendState extends ConsumerState { Future sendAllTapped() async { cryptoAmountController.text = ref .read( - pTokenBalance( - ( - walletId: walletId, - contractAddress: - ref.read(pCurrentTokenWallet)!.tokenContract.address - ), - ), + pTokenBalance(( + walletId: walletId, + contractAddress: + ref.read(pCurrentTokenWallet)!.tokenContract.address, + )), ) .spendable .decimal - .toStringAsFixed( - ref.read(pCurrentTokenWallet)!.tokenContract.decimals, - ); + .toStringAsFixed(ref.read(pCurrentTokenWallet)!.tokenContract.decimals); } @override @@ -702,16 +658,15 @@ class _DesktopTokenSendState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), if (coin is Firo) Text( "Send from", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), @@ -721,9 +676,10 @@ class _DesktopTokenSendState extends ConsumerState { Text( "Amount", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), @@ -733,9 +689,7 @@ class _DesktopTokenSendState extends ConsumerState { ), ], ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -745,20 +699,22 @@ class _DesktopTokenSendState extends ConsumerState { key: const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( decimals: tokenContract.decimals, unit: ref.watch(pAmountUnit(coin)), locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), ), // regex to validate a crypto amount with 8 decimal places @@ -780,9 +736,10 @@ class _DesktopTokenSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -791,20 +748,23 @@ class _DesktopTokenSendState extends ConsumerState { child: Text( ref.watch(pAmountUnit(coin)).unitForContract(tokenContract), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - if (Prefs.instance.externalCalls) - const SizedBox( - height: 10, - ), - if (Prefs.instance.externalCalls) + if (ref.watch( + prefsChangeNotifierProvider.select((s) => s.externalCalls), + )) + const SizedBox(height: 10), + if (ref.watch( + prefsChangeNotifierProvider.select((s) => s.externalCalls), + )) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -814,19 +774,21 @@ class _DesktopTokenSendState extends ConsumerState { key: const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( decimals: 2, locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), ), // // regex to validate a fiat amount with 2 decimal places @@ -845,9 +807,10 @@ class _DesktopTokenSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -855,34 +818,33 @@ class _DesktopTokenSendState extends ConsumerState { padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Text( "Send to", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -915,9 +877,10 @@ class _DesktopTokenSendState extends ConsumerState { }, focusNode: _addressFocusNode, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -933,78 +896,83 @@ class _DesktopTokenSendState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _addressToggleFlag ? TextFieldIconButton( - key: const Key( - "sendTokenViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _updatePreviewButtonState( - _address, - _amountToSend, - ); - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) + key: const Key( + "sendTokenViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, + _amountToSend, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "sendTokenViewPasteAddressFieldButtonKey", - ), - onTap: pasteAddress, - child: sendToController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + key: const Key( + "sendTokenViewPasteAddressFieldButtonKey", ), + onTap: pasteAddress, + child: + sendToController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( key: const Key("sendTokenViewAddressBookButtonKey"), onTap: () async { - final entry = - await showDialog( + final entry = await showDialog< + ContactAddressEntry? + >( context: context, - builder: (context) => DesktopDialog( - maxWidth: 696, - maxHeight: 600, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 696, + maxHeight: 600, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: - STextStyles.desktopH3(context), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Address book", + style: STextStyles.desktopH3( + context, + ), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: AddressBookAddressChooser( + coin: coin, ), ), - const DesktopDialogCloseButton(), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: coin, - ), - ), - ], - ), - ), + ), ); if (entry != null) { @@ -1034,9 +1002,7 @@ class _DesktopTokenSendState extends ConsumerState { ), Builder( builder: (_) { - final error = _updateInvalidAddressText( - _address ?? "", - ); + final error = _updateInvalidAddressText(_address ?? ""); if (error == null || error.isEmpty) { return Container(); @@ -1044,10 +1010,7 @@ class _DesktopTokenSendState extends ConsumerState { return Align( alignment: Alignment.topLeft, child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), + padding: const EdgeInsets.only(left: 12.0, top: 4.0), child: Text( error, textAlign: TextAlign.left, @@ -1061,40 +1024,31 @@ class _DesktopTokenSendState extends ConsumerState { } }, ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Text( "Transaction fee (max)", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), - DesktopFeeDropDown( - walletId: walletId, - isToken: true, - ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 10), + DesktopFeeDropDown(walletId: walletId, isToken: true), + const SizedBox(height: 20), Text( "Nonce", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1110,9 +1064,10 @@ class _DesktopTokenSendState extends ConsumerState { keyboardType: const TextInputType.numberWithOptions(), focusNode: _nonceFocusNode, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -1130,16 +1085,15 @@ class _DesktopTokenSendState extends ConsumerState { ), ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), PrimaryButton( buttonHeight: ButtonHeight.l, label: "Preview send", enabled: ref.watch(previewTokenTxButtonStateProvider.state).state, - onPressed: ref.watch(previewTokenTxButtonStateProvider.state).state - ? previewSend - : null, + onPressed: + ref.watch(previewTokenTxButtonStateProvider.state).state + ? previewSend + : null, ), ], ); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart index fdc0f99b7..dc09c757d 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart @@ -84,7 +84,7 @@ class _WDesktopWalletSummaryState extends ConsumerState { ) : null; - final priceTuple = + final price = widget.isToken ? ref.watch( priceAnd24hChangeNotifierProvider.select( @@ -150,9 +150,9 @@ class _WDesktopWalletSummaryState extends ConsumerState { style: STextStyles.desktopH3(context), ), ), - if (externalCalls) + if (externalCalls && price != null) SelectableText( - "${Amount.fromDecimal(priceTuple.item1 * balanceToShow.decimal, fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", + "${Amount.fromDecimal(price.value * balanceToShow.decimal, fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart index 73f384f82..ecc80aa28 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart @@ -66,12 +66,14 @@ class _WFiroDesktopWalletSummaryState if (ref.watch( prefsChangeNotifierProvider.select((value) => value.externalCalls), )) { - final priceTuple = ref.watch( - priceAnd24hChangeNotifierProvider.select( - (value) => value.getPrice(coin), - ), - ); - price = priceTuple.item1; + price = + ref + .watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ) + ?.value; } final _showAvailable = diff --git a/lib/services/price.dart b/lib/services/price.dart index 801e720e2..75a4ad664 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -13,7 +13,6 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:tuple/tuple.dart'; import '../app_config.dart'; import '../db/hive/db.dart'; @@ -54,13 +53,15 @@ class PriceAPI { static const refreshInterval = 60; // initialize to older than current time minus at least refreshInterval - static DateTime _lastCalled = - DateTime.now().subtract(const Duration(seconds: refreshInterval + 10)); + static DateTime _lastCalled = DateTime.now().subtract( + const Duration(seconds: refreshInterval + 10), + ); static String _lastUsedBaseCurrency = ""; - static const Duration refreshIntervalDuration = - Duration(seconds: refreshInterval); + static const Duration refreshIntervalDuration = Duration( + seconds: refreshInterval, + ); final HTTP client; @@ -72,7 +73,7 @@ class PriceAPI { } Future _updateCachedPrices( - Map> data, + Map data, ) async { final Map map = {}; @@ -81,30 +82,29 @@ class PriceAPI { if (entry == null) { map[coin.prettyName] = ["0", 0.0]; } else { - map[coin.prettyName] = [entry.item1.toString(), entry.item2]; + map[coin.prettyName] = [entry.value.toString(), entry.change24h]; } } - await DB.instance - .put(boxName: DB.boxNamePriceCache, key: 'cache', value: map); + await DB.instance.put( + boxName: DB.boxNamePriceCache, + key: 'cache', + value: map, + ); } - Map> get _cachedPrices { + Map get _cachedPrices { final map = DB.instance.get(boxName: DB.boxNamePriceCache, key: 'cache') - as Map? ?? - {}; + as Map? ?? + {}; // init with 0 - final result = { - for (final coin in AppConfig.coins) coin: Tuple2(Decimal.zero, 0.0), - }; + final Map result = {}; for (final entry in map.entries) { - result[AppConfig.getCryptoCurrencyByPrettyName( - entry.key as String, - )] = Tuple2( - Decimal.parse(entry.value[0] as String), - entry.value[1] as double, + result[AppConfig.getCryptoCurrencyByPrettyName(entry.key as String)] = ( + value: Decimal.parse(entry.value[0] as String), + change24h: entry.value[1] as double, ); } @@ -117,9 +117,8 @@ class PriceAPI { .where((e) => e != null) .join(","); - Future>> getPricesAnd24hChange({ - required String baseCurrency, - }) async { + Future> + getPricesAnd24hChange({required String baseCurrency}) async { final now = DateTime.now(); if (_lastUsedBaseCurrency != baseCurrency || now.difference(_lastCalled) > refreshIntervalDuration) { @@ -132,12 +131,10 @@ class PriceAPI { final externalCalls = Prefs.instance.externalCalls; if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return _cachedPrices; } - final Map> result = {}; + final Map result = {}; try { final uri = Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency" @@ -148,9 +145,10 @@ class PriceAPI { final coinGeckoResponse = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); final coinGeckoData = jsonDecode(coinGeckoResponse.body) as List; @@ -159,12 +157,17 @@ class PriceAPI { final String coinName = map["name"] as String; final coin = AppConfig.getCryptoCurrencyByPrettyName(coinName); - final price = Decimal.parse(map["current_price"].toString()); - final change24h = map["price_change_percentage_24h"] != null - ? double.parse(map["price_change_percentage_24h"].toString()) - : 0.0; - - result[coin] = Tuple2(price, change24h); + try { + final price = Decimal.parse(map["current_price"].toString()); + final change24h = + map["price_change_percentage_24h"] != null + ? double.parse(map["price_change_percentage_24h"].toString()) + : 0.0; + + result[coin] = (value: price, change24h: change24h); + } catch (_) { + result.remove(coin); + } } // update cache @@ -172,8 +175,11 @@ class PriceAPI { return _cachedPrices; } catch (e, s) { - Logging.instance - .e("getPricesAnd24hChange($baseCurrency): ", error: e, stackTrace: s); + Logging.instance.e( + "getPricesAnd24hChange($baseCurrency): ", + error: e, + stackTrace: s, + ); // return previous cached values return _cachedPrices; } @@ -185,9 +191,7 @@ class PriceAPI { if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return null; } const uriString = @@ -197,9 +201,10 @@ class PriceAPI { final response = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); final json = jsonDecode(response.body) as List; @@ -214,22 +219,22 @@ class PriceAPI { } } - Future>> - getPricesAnd24hChangeForEthTokens({ + Future> + getPricesAnd24hChangeForEthTokens({ required Set contractAddresses, required String baseCurrency, }) async { - final Map> tokenPrices = {}; + final Map tokenPrices = {}; if (AppConfig.coins.whereType().isEmpty || - contractAddresses.isEmpty) return tokenPrices; + contractAddresses.isEmpty) { + return tokenPrices; + } final externalCalls = Prefs.instance.externalCalls; if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return tokenPrices; } diff --git a/lib/services/price_service.dart b/lib/services/price_service.dart index fb30c8477..43eb68e32 100644 --- a/lib/services/price_service.dart +++ b/lib/services/price_service.dart @@ -13,13 +13,12 @@ import 'dart:async'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:isar/isar.dart'; + import '../db/isar/main_db.dart'; import '../models/isar/models/isar_models.dart'; import '../networking/http.dart'; -import 'price.dart'; -import '../app_config.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; -import 'package:tuple/tuple.dart'; +import 'price.dart'; class PriceService extends ChangeNotifier { late final String baseTicker; @@ -29,25 +28,26 @@ class PriceService extends ChangeNotifier { final Duration updateInterval = const Duration(seconds: 60); Timer? _timer; - final Map> _cachedPrices = { - for (final coin in AppConfig.coins) coin: Tuple2(Decimal.zero, 0.0), - }; + final Map _cachedPrices = + {}; - final Map> _cachedTokenPrices = {}; + final Map _cachedTokenPrices = + {}; final _priceAPI = PriceAPI(HTTP()); - Tuple2 getPrice(CryptoCurrency coin) => _cachedPrices[coin]!; + ({Decimal value, double change24h})? getPrice(CryptoCurrency coin) => + _cachedPrices[coin]; - Tuple2 getTokenPrice(String contractAddress) => - _cachedTokenPrices[contractAddress.toLowerCase()] ?? - Tuple2(Decimal.zero, 0); + ({Decimal value, double change24h})? getTokenPrice(String contractAddress) => + _cachedTokenPrices[contractAddress.toLowerCase()]; PriceService(this.baseTicker); Future updatePrice() async { - final priceMap = - await _priceAPI.getPricesAnd24hChange(baseCurrency: baseTicker); + final priceMap = await _priceAPI.getPricesAnd24hChange( + baseCurrency: baseTicker, + ); bool shouldNotify = false; for (final map in priceMap.entries) { diff --git a/lib/widgets/transaction_card.dart b/lib/widgets/transaction_card.dart index cab5043d6..f4227005e 100644 --- a/lib/widgets/transaction_card.dart +++ b/lib/widgets/transaction_card.dart @@ -143,30 +143,35 @@ class _TransactionCardState extends ConsumerState { localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final baseCurrency = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + final baseCurrency = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); - final price = ref - .watch( - priceAnd24hChangeNotifierProvider.select( - (value) => isTokenTx - ? value.getTokenPrice(_transaction.otherData!) - : value.getPrice(coin), - ), - ) - .item1; + final price = + ref + .watch( + priceAnd24hChangeNotifierProvider.select( + (value) => + isTokenTx + ? value.getTokenPrice(_transaction.otherData!) + : value.getPrice(coin), + ), + ) + ?.value; final currentHeight = ref.watch( - pWallets - .select((value) => value.getWallet(walletId).info.cachedChainHeight), + pWallets.select( + (value) => value.getWallet(walletId).info.cachedChainHeight, + ), ); return Material( color: Theme.of(context).extension()!.popupBG, elevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: Padding( padding: const EdgeInsets.all(6), @@ -191,25 +196,22 @@ class _TransactionCardState extends ConsumerState { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: TransactionDetailsView( - transaction: _transaction, - coin: coin, - walletId: walletId, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TransactionDetailsView( + transaction: _transaction, + coin: coin, + walletId: walletId, + ), + ), ); } else { unawaited( Navigator.of(context).pushNamed( TransactionDetailsView.routeName, - arguments: Tuple3( - _transaction, - coin, - walletId, - ), + arguments: Tuple3(_transaction, coin, walletId), ), ); } @@ -223,9 +225,7 @@ class _TransactionCardState extends ConsumerState { coin: coin, currentHeight: currentHeight, ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -243,17 +243,15 @@ class _TransactionCardState extends ConsumerState { ? "Failed" : "Cancelled" : whatIsIt( - _transaction.type, - coin, - currentHeight, - ), + _transaction.type, + coin, + currentHeight, + ), style: STextStyles.itemSubtitle12(context), ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Flexible( child: FittedBox( fit: BoxFit.scaleDown, @@ -271,9 +269,7 @@ class _TransactionCardState extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, // crossAxisAlignment: CrossAxisAlignment.end, @@ -287,17 +283,19 @@ class _TransactionCardState extends ConsumerState { ), ), ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) - const SizedBox( - width: 10, - ), - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - )) + if (price != null && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, + ), + )) + const SizedBox(width: 10), + if (price != null && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, + ), + )) Flexible( child: FittedBox( fit: BoxFit.scaleDown, @@ -306,12 +304,7 @@ class _TransactionCardState extends ConsumerState { final amount = _transaction.realAmount; return Text( - "$prefix${Amount.fromDecimal( - amount.decimal * price, - fractionDigits: 2, - ).fiatString( - locale: locale, - )} $baseCurrency", + "$prefix${Amount.fromDecimal(amount.decimal * price, fractionDigits: 2).fiatString(locale: locale)} $baseCurrency", style: STextStyles.label(context), ); }, diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index a146a9abf..ac6790693 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -3,41 +3,41 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i11; -import 'dart:typed_data' as _i26; -import 'dart:ui' as _i17; +import 'dart:async' as _i10; +import 'dart:typed_data' as _i25; +import 'dart:ui' as _i16; -import 'package:decimal/decimal.dart' as _i23; -import 'package:isar/isar.dart' as _i9; -import 'package:logger/logger.dart' as _i20; +import 'package:decimal/decimal.dart' as _i22; +import 'package:isar/isar.dart' as _i8; +import 'package:logger/logger.dart' as _i19; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i16; +import 'package:mockito/src/dummies.dart' as _i15; import 'package:stackwallet/db/isar/main_db.dart' as _i3; -import 'package:stackwallet/models/isar/models/block_explorer.dart' as _i28; +import 'package:stackwallet/models/isar/models/block_explorer.dart' as _i27; import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart' as _i30; -import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i27; -import 'package:stackwallet/models/isar/models/isar_models.dart' as _i29; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i25; -import 'package:stackwallet/networking/http.dart' as _i8; -import 'package:stackwallet/services/locale_service.dart' as _i15; +import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i26; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i28; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i24; +import 'package:stackwallet/networking/http.dart' as _i7; +import 'package:stackwallet/services/locale_service.dart' as _i14; import 'package:stackwallet/services/node_service.dart' as _i2; -import 'package:stackwallet/services/price_service.dart' as _i22; -import 'package:stackwallet/services/wallets.dart' as _i10; -import 'package:stackwallet/themes/theme_service.dart' as _i24; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i21; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i19; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i18; +import 'package:stackwallet/services/price_service.dart' as _i21; +import 'package:stackwallet/services/wallets.dart' as _i9; +import 'package:stackwallet/themes/theme_service.dart' as _i23; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i20; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i18; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i17; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i13; -import 'package:stackwallet/utilities/prefs.dart' as _i14; + as _i12; +import 'package:stackwallet/utilities/prefs.dart' as _i13; import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart' as _i4; -import 'package:stackwallet/wallets/isar/models/wallet_info.dart' as _i12; +import 'package:stackwallet/wallets/isar/models/wallet_info.dart' as _i11; import 'package:stackwallet/wallets/wallet/wallet.dart' as _i5; import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart' as _i6; -import 'package:tuple/tuple.dart' as _i7; +import 'package:tuple/tuple.dart' as _i29; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -103,9 +103,8 @@ class _FakeDuration_4 extends _i1.SmartFake implements Duration { ); } -class _FakeTuple2_5 extends _i1.SmartFake - implements _i7.Tuple2 { - _FakeTuple2_5( +class _FakeHTTP_5 extends _i1.SmartFake implements _i7.HTTP { + _FakeHTTP_5( Object parent, Invocation parentInvocation, ) : super( @@ -114,8 +113,8 @@ class _FakeTuple2_5 extends _i1.SmartFake ); } -class _FakeHTTP_6 extends _i1.SmartFake implements _i8.HTTP { - _FakeHTTP_6( +class _FakeIsar_6 extends _i1.SmartFake implements _i8.Isar { + _FakeIsar_6( Object parent, Invocation parentInvocation, ) : super( @@ -124,19 +123,9 @@ class _FakeHTTP_6 extends _i1.SmartFake implements _i8.HTTP { ); } -class _FakeIsar_7 extends _i1.SmartFake implements _i9.Isar { - _FakeIsar_7( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeQueryBuilder_8 extends _i1.SmartFake - implements _i9.QueryBuilder { - _FakeQueryBuilder_8( +class _FakeQueryBuilder_7 extends _i1.SmartFake + implements _i8.QueryBuilder { + _FakeQueryBuilder_7( Object parent, Invocation parentInvocation, ) : super( @@ -148,7 +137,7 @@ class _FakeQueryBuilder_8 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i10.Wallets { +class MockWallets extends _i1.Mock implements _i9.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -221,9 +210,9 @@ class MockWallets extends _i1.Mock implements _i10.Wallets { ); @override - _i11.Future deleteWallet( - _i12.WalletInfo? info, - _i13.SecureStorageInterface? secureStorage, + _i10.Future deleteWallet( + _i11.WalletInfo? info, + _i12.SecureStorageInterface? secureStorage, ) => (super.noSuchMethod( Invocation.method( @@ -233,13 +222,13 @@ class MockWallets extends _i1.Mock implements _i10.Wallets { secureStorage, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future load( - _i14.Prefs? prefs, + _i10.Future load( + _i13.Prefs? prefs, _i3.MainDB? mainDB, ) => (super.noSuchMethod( @@ -250,13 +239,13 @@ class MockWallets extends _i1.Mock implements _i10.Wallets { mainDB, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future loadAfterStackRestore( - _i14.Prefs? prefs, + _i10.Future loadAfterStackRestore( + _i13.Prefs? prefs, List<_i5.Wallet<_i4.CryptoCurrency>>? wallets, bool? isDesktop, ) => @@ -269,15 +258,15 @@ class MockWallets extends _i1.Mock implements _i10.Wallets { isDesktop, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i15.LocaleService { +class MockLocaleService extends _i1.Mock implements _i14.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -285,7 +274,7 @@ class MockLocaleService extends _i1.Mock implements _i15.LocaleService { @override String get locale => (super.noSuchMethod( Invocation.getter(#locale), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#locale), ), @@ -298,18 +287,18 @@ class MockLocaleService extends _i1.Mock implements _i15.LocaleService { ) as bool); @override - _i11.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i10.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - void addListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -318,7 +307,7 @@ class MockLocaleService extends _i1.Mock implements _i15.LocaleService { ); @override - void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -348,7 +337,7 @@ class MockLocaleService extends _i1.Mock implements _i15.LocaleService { /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i14.Prefs { +class MockPrefs extends _i1.Mock implements _i13.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -412,13 +401,13 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ); @override - _i18.SyncingType get syncType => (super.noSuchMethod( + _i17.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i18.SyncingType.currentWalletOnly, - ) as _i18.SyncingType); + returnValue: _i17.SyncingType.currentWalletOnly, + ) as _i17.SyncingType); @override - set syncType(_i18.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i17.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -459,7 +448,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { @override String get language => (super.noSuchMethod( Invocation.getter(#language), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#language), ), @@ -477,7 +466,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { @override String get currency => (super.noSuchMethod( Invocation.getter(#currency), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#currency), ), @@ -607,13 +596,13 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ); @override - _i19.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i18.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i19.BackupFrequencyType.everyTenMinutes, - ) as _i19.BackupFrequencyType); + returnValue: _i18.BackupFrequencyType.everyTenMinutes, + ) as _i18.BackupFrequencyType); @override - set backupFrequencyType(_i19.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i18.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -720,7 +709,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { @override String get themeId => (super.noSuchMethod( Invocation.getter(#themeId), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#themeId), ), @@ -738,7 +727,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { @override String get systemBrightnessLightThemeId => (super.noSuchMethod( Invocation.getter(#systemBrightnessLightThemeId), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#systemBrightnessLightThemeId), ), @@ -757,7 +746,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { @override String get systemBrightnessDarkThemeId => (super.noSuchMethod( Invocation.getter(#systemBrightnessDarkThemeId), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#systemBrightnessDarkThemeId), ), @@ -843,13 +832,13 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ); @override - _i20.Level get logLevel => (super.noSuchMethod( + _i19.Level get logLevel => (super.noSuchMethod( Invocation.getter(#logLevel), - returnValue: _i20.Level.all, - ) as _i20.Level); + returnValue: _i19.Level.all, + ) as _i19.Level); @override - set logLevel(_i20.Level? logLevel) => super.noSuchMethod( + set logLevel(_i19.Level? logLevel) => super.noSuchMethod( Invocation.setter( #logLevel, logLevel, @@ -864,67 +853,67 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ) as bool); @override - _i11.Future init() => (super.noSuchMethod( + _i10.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i10.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future isExternalCallsSet() => (super.noSuchMethod( + _i10.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i11.Future saveUserID(String? userId) => (super.noSuchMethod( + _i10.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i10.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i21.AmountUnit amountUnit(_i4.CryptoCurrency? coin) => (super.noSuchMethod( + _i20.AmountUnit amountUnit(_i4.CryptoCurrency? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i21.AmountUnit.normal, - ) as _i21.AmountUnit); + returnValue: _i20.AmountUnit.normal, + ) as _i20.AmountUnit); @override void updateAmountUnit({ required _i4.CryptoCurrency? coin, - required _i21.AmountUnit? amountUnit, + required _i20.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -997,7 +986,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ); @override - void addListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1006,7 +995,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { ); @override - void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1036,7 +1025,7 @@ class MockPrefs extends _i1.Mock implements _i14.Prefs { /// A class which mocks [PriceService]. /// /// See the documentation for Mockito's code generation for more information. -class MockPriceService extends _i1.Mock implements _i22.PriceService { +class MockPriceService extends _i1.Mock implements _i21.PriceService { MockPriceService() { _i1.throwOnMissingStub(this); } @@ -1044,7 +1033,7 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { @override String get baseTicker => (super.noSuchMethod( Invocation.getter(#baseTicker), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#baseTicker), ), @@ -1069,11 +1058,11 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { ) as Duration); @override - _i11.Future> get tokenContractAddressesToCheck => + _i10.Future> get tokenContractAddressesToCheck => (super.noSuchMethod( Invocation.getter(#tokenContractAddressesToCheck), - returnValue: _i11.Future>.value({}), - ) as _i11.Future>); + returnValue: _i10.Future>.value({}), + ) as _i10.Future>); @override bool get hasListeners => (super.noSuchMethod( @@ -1082,46 +1071,30 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { ) as bool); @override - _i7.Tuple2<_i23.Decimal, double> getPrice(_i4.CryptoCurrency? coin) => - (super.noSuchMethod( - Invocation.method( - #getPrice, - [coin], - ), - returnValue: _FakeTuple2_5<_i23.Decimal, double>( - this, - Invocation.method( - #getPrice, - [coin], - ), - ), - ) as _i7.Tuple2<_i23.Decimal, double>); + ({double change24h, _i22.Decimal value})? getPrice( + _i4.CryptoCurrency? coin) => + (super.noSuchMethod(Invocation.method( + #getPrice, + [coin], + )) as ({double change24h, _i22.Decimal value})?); @override - _i7.Tuple2<_i23.Decimal, double> getTokenPrice(String? contractAddress) => - (super.noSuchMethod( - Invocation.method( - #getTokenPrice, - [contractAddress], - ), - returnValue: _FakeTuple2_5<_i23.Decimal, double>( - this, - Invocation.method( - #getTokenPrice, - [contractAddress], - ), - ), - ) as _i7.Tuple2<_i23.Decimal, double>); + ({double change24h, _i22.Decimal value})? getTokenPrice( + String? contractAddress) => + (super.noSuchMethod(Invocation.method( + #getTokenPrice, + [contractAddress], + )) as ({double change24h, _i22.Decimal value})?); @override - _i11.Future updatePrice() => (super.noSuchMethod( + _i10.Future updatePrice() => (super.noSuchMethod( Invocation.method( #updatePrice, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override void cancel() => super.noSuchMethod( @@ -1151,7 +1124,7 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { ); @override - void addListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1160,7 +1133,7 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { ); @override - void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i16.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1181,22 +1154,22 @@ class MockPriceService extends _i1.Mock implements _i22.PriceService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i24.ThemeService { +class MockThemeService extends _i1.Mock implements _i23.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i8.HTTP get client => (super.noSuchMethod( + _i7.HTTP get client => (super.noSuchMethod( Invocation.getter(#client), - returnValue: _FakeHTTP_6( + returnValue: _FakeHTTP_5( this, Invocation.getter(#client), ), - ) as _i8.HTTP); + ) as _i7.HTTP); @override - set client(_i8.HTTP? _client) => super.noSuchMethod( + set client(_i7.HTTP? _client) => super.noSuchMethod( Invocation.setter( #client, _client, @@ -1214,10 +1187,10 @@ class MockThemeService extends _i1.Mock implements _i24.ThemeService { ) as _i3.MainDB); @override - List<_i25.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i24.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i25.StackTheme>[], - ) as List<_i25.StackTheme>); + returnValue: <_i24.StackTheme>[], + ) as List<_i24.StackTheme>); @override void init(_i3.MainDB? db) => super.noSuchMethod( @@ -1229,79 +1202,79 @@ class MockThemeService extends _i1.Mock implements _i24.ThemeService { ); @override - _i11.Future install({required _i26.Uint8List? themeArchiveData}) => + _i10.Future install({required _i25.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future remove({required String? themeId}) => (super.noSuchMethod( + _i10.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i10.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future verifyInstalled({required String? themeId}) => + _i10.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i11.Future> fetchThemes() => + _i10.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i11.Future>.value( - <_i24.StackThemeMetaData>[]), - ) as _i11.Future>); + returnValue: _i10.Future>.value( + <_i23.StackThemeMetaData>[]), + ) as _i10.Future>); @override - _i11.Future<_i26.Uint8List> fetchTheme( - {required _i24.StackThemeMetaData? themeMetaData}) => + _i10.Future<_i25.Uint8List> fetchTheme( + {required _i23.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i11.Future<_i26.Uint8List>.value(_i26.Uint8List(0)), - ) as _i11.Future<_i26.Uint8List>); + returnValue: _i10.Future<_i25.Uint8List>.value(_i25.Uint8List(0)), + ) as _i10.Future<_i25.Uint8List>); @override - _i25.StackTheme? getTheme({required String? themeId}) => + _i24.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i25.StackTheme?); + )) as _i24.StackTheme?); } /// A class which mocks [MainDB]. @@ -1313,166 +1286,166 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { } @override - _i9.Isar get isar => (super.noSuchMethod( + _i8.Isar get isar => (super.noSuchMethod( Invocation.getter(#isar), - returnValue: _FakeIsar_7( + returnValue: _FakeIsar_6( this, Invocation.getter(#isar), ), - ) as _i9.Isar); + ) as _i8.Isar); @override - _i11.Future initMainDB({_i9.Isar? mock}) => (super.noSuchMethod( + _i10.Future initMainDB({_i8.Isar? mock}) => (super.noSuchMethod( Invocation.method( #initMainDB, [], {#mock: mock}, ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i11.Future putWalletInfo(_i12.WalletInfo? walletInfo) => + _i10.Future putWalletInfo(_i11.WalletInfo? walletInfo) => (super.noSuchMethod( Invocation.method( #putWalletInfo, [walletInfo], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future updateWalletInfo(_i12.WalletInfo? walletInfo) => + _i10.Future updateWalletInfo(_i11.WalletInfo? walletInfo) => (super.noSuchMethod( Invocation.method( #updateWalletInfo, [walletInfo], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - List<_i27.ContactEntry> getContactEntries() => (super.noSuchMethod( + List<_i26.ContactEntry> getContactEntries() => (super.noSuchMethod( Invocation.method( #getContactEntries, [], ), - returnValue: <_i27.ContactEntry>[], - ) as List<_i27.ContactEntry>); + returnValue: <_i26.ContactEntry>[], + ) as List<_i26.ContactEntry>); @override - _i11.Future deleteContactEntry({required String? id}) => + _i10.Future deleteContactEntry({required String? id}) => (super.noSuchMethod( Invocation.method( #deleteContactEntry, [], {#id: id}, ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i11.Future isContactEntryExists({required String? id}) => + _i10.Future isContactEntryExists({required String? id}) => (super.noSuchMethod( Invocation.method( #isContactEntryExists, [], {#id: id}, ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i27.ContactEntry? getContactEntry({required String? id}) => + _i26.ContactEntry? getContactEntry({required String? id}) => (super.noSuchMethod(Invocation.method( #getContactEntry, [], {#id: id}, - )) as _i27.ContactEntry?); + )) as _i26.ContactEntry?); @override - _i11.Future putContactEntry( - {required _i27.ContactEntry? contactEntry}) => + _i10.Future putContactEntry( + {required _i26.ContactEntry? contactEntry}) => (super.noSuchMethod( Invocation.method( #putContactEntry, [], {#contactEntry: contactEntry}, ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i28.TransactionBlockExplorer? getTransactionBlockExplorer( + _i27.TransactionBlockExplorer? getTransactionBlockExplorer( {required _i4.CryptoCurrency? cryptoCurrency}) => (super.noSuchMethod(Invocation.method( #getTransactionBlockExplorer, [], {#cryptoCurrency: cryptoCurrency}, - )) as _i28.TransactionBlockExplorer?); + )) as _i27.TransactionBlockExplorer?); @override - _i11.Future putTransactionBlockExplorer( - _i28.TransactionBlockExplorer? explorer) => + _i10.Future putTransactionBlockExplorer( + _i27.TransactionBlockExplorer? explorer) => (super.noSuchMethod( Invocation.method( #putTransactionBlockExplorer, [explorer], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i9.QueryBuilder<_i29.Address, _i29.Address, _i9.QAfterWhereClause> + _i8.QueryBuilder<_i28.Address, _i28.Address, _i8.QAfterWhereClause> getAddresses(String? walletId) => (super.noSuchMethod( Invocation.method( #getAddresses, [walletId], ), - returnValue: _FakeQueryBuilder_8<_i29.Address, _i29.Address, - _i9.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_7<_i28.Address, _i28.Address, + _i8.QAfterWhereClause>( this, Invocation.method( #getAddresses, [walletId], ), ), - ) as _i9 - .QueryBuilder<_i29.Address, _i29.Address, _i9.QAfterWhereClause>); + ) as _i8 + .QueryBuilder<_i28.Address, _i28.Address, _i8.QAfterWhereClause>); @override - _i11.Future putAddress(_i29.Address? address) => (super.noSuchMethod( + _i10.Future putAddress(_i28.Address? address) => (super.noSuchMethod( Invocation.method( #putAddress, [address], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i11.Future> putAddresses(List<_i29.Address>? addresses) => + _i10.Future> putAddresses(List<_i28.Address>? addresses) => (super.noSuchMethod( Invocation.method( #putAddresses, [addresses], ), - returnValue: _i11.Future>.value([]), - ) as _i11.Future>); + returnValue: _i10.Future>.value([]), + ) as _i10.Future>); @override - _i11.Future> updateOrPutAddresses(List<_i29.Address>? addresses) => + _i10.Future> updateOrPutAddresses(List<_i28.Address>? addresses) => (super.noSuchMethod( Invocation.method( #updateOrPutAddresses, [addresses], ), - returnValue: _i11.Future>.value([]), - ) as _i11.Future>); + returnValue: _i10.Future>.value([]), + ) as _i10.Future>); @override - _i11.Future<_i29.Address?> getAddress( + _i10.Future<_i28.Address?> getAddress( String? walletId, String? address, ) => @@ -1484,13 +1457,13 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { address, ], ), - returnValue: _i11.Future<_i29.Address?>.value(), - ) as _i11.Future<_i29.Address?>); + returnValue: _i10.Future<_i28.Address?>.value(), + ) as _i10.Future<_i28.Address?>); @override - _i11.Future updateAddress( - _i29.Address? oldAddress, - _i29.Address? newAddress, + _i10.Future updateAddress( + _i28.Address? oldAddress, + _i28.Address? newAddress, ) => (super.noSuchMethod( Invocation.method( @@ -1500,50 +1473,50 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { newAddress, ], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i9.QueryBuilder<_i29.Transaction, _i29.Transaction, _i9.QAfterWhereClause> + _i8.QueryBuilder<_i28.Transaction, _i28.Transaction, _i8.QAfterWhereClause> getTransactions(String? walletId) => (super.noSuchMethod( Invocation.method( #getTransactions, [walletId], ), - returnValue: _FakeQueryBuilder_8<_i29.Transaction, _i29.Transaction, - _i9.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_7<_i28.Transaction, _i28.Transaction, + _i8.QAfterWhereClause>( this, Invocation.method( #getTransactions, [walletId], ), ), - ) as _i9.QueryBuilder<_i29.Transaction, _i29.Transaction, - _i9.QAfterWhereClause>); + ) as _i8.QueryBuilder<_i28.Transaction, _i28.Transaction, + _i8.QAfterWhereClause>); @override - _i11.Future putTransaction(_i29.Transaction? transaction) => + _i10.Future putTransaction(_i28.Transaction? transaction) => (super.noSuchMethod( Invocation.method( #putTransaction, [transaction], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i11.Future> putTransactions( - List<_i29.Transaction>? transactions) => + _i10.Future> putTransactions( + List<_i28.Transaction>? transactions) => (super.noSuchMethod( Invocation.method( #putTransactions, [transactions], ), - returnValue: _i11.Future>.value([]), - ) as _i11.Future>); + returnValue: _i10.Future>.value([]), + ) as _i10.Future>); @override - _i11.Future<_i29.Transaction?> getTransaction( + _i10.Future<_i28.Transaction?> getTransaction( String? walletId, String? txid, ) => @@ -1555,11 +1528,11 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { txid, ], ), - returnValue: _i11.Future<_i29.Transaction?>.value(), - ) as _i11.Future<_i29.Transaction?>); + returnValue: _i10.Future<_i28.Transaction?>.value(), + ) as _i10.Future<_i28.Transaction?>); @override - _i11.Stream<_i29.Transaction?> watchTransaction({ + _i10.Stream<_i28.Transaction?> watchTransaction({ required int? id, bool? fireImmediately = false, }) => @@ -1572,11 +1545,11 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i11.Stream<_i29.Transaction?>.empty(), - ) as _i11.Stream<_i29.Transaction?>); + returnValue: _i10.Stream<_i28.Transaction?>.empty(), + ) as _i10.Stream<_i28.Transaction?>); @override - _i9.QueryBuilder<_i29.UTXO, _i29.UTXO, _i9.QAfterWhereClause> getUTXOs( + _i8.QueryBuilder<_i28.UTXO, _i28.UTXO, _i8.QAfterWhereClause> getUTXOs( String? walletId) => (super.noSuchMethod( Invocation.method( @@ -1584,17 +1557,17 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { [walletId], ), returnValue: - _FakeQueryBuilder_8<_i29.UTXO, _i29.UTXO, _i9.QAfterWhereClause>( + _FakeQueryBuilder_7<_i28.UTXO, _i28.UTXO, _i8.QAfterWhereClause>( this, Invocation.method( #getUTXOs, [walletId], ), ), - ) as _i9.QueryBuilder<_i29.UTXO, _i29.UTXO, _i9.QAfterWhereClause>); + ) as _i8.QueryBuilder<_i28.UTXO, _i28.UTXO, _i8.QAfterWhereClause>); @override - _i9.QueryBuilder<_i29.UTXO, _i29.UTXO, _i9.QAfterFilterCondition> + _i8.QueryBuilder<_i28.UTXO, _i28.UTXO, _i8.QAfterFilterCondition> getUTXOsByAddress( String? walletId, String? address, @@ -1607,8 +1580,8 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { address, ], ), - returnValue: _FakeQueryBuilder_8<_i29.UTXO, _i29.UTXO, - _i9.QAfterFilterCondition>( + returnValue: _FakeQueryBuilder_7<_i28.UTXO, _i28.UTXO, + _i8.QAfterFilterCondition>( this, Invocation.method( #getUTXOsByAddress, @@ -1618,33 +1591,33 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { ], ), ), - ) as _i9 - .QueryBuilder<_i29.UTXO, _i29.UTXO, _i9.QAfterFilterCondition>); + ) as _i8 + .QueryBuilder<_i28.UTXO, _i28.UTXO, _i8.QAfterFilterCondition>); @override - _i11.Future putUTXO(_i29.UTXO? utxo) => (super.noSuchMethod( + _i10.Future putUTXO(_i28.UTXO? utxo) => (super.noSuchMethod( Invocation.method( #putUTXO, [utxo], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future putUTXOs(List<_i29.UTXO>? utxos) => (super.noSuchMethod( + _i10.Future putUTXOs(List<_i28.UTXO>? utxos) => (super.noSuchMethod( Invocation.method( #putUTXOs, [utxos], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future updateUTXOs( + _i10.Future updateUTXOs( String? walletId, - List<_i29.UTXO>? utxos, + List<_i28.UTXO>? utxos, ) => (super.noSuchMethod( Invocation.method( @@ -1654,11 +1627,11 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { utxos, ], ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i10.Future.value(false), + ) as _i10.Future); @override - _i11.Stream<_i29.UTXO?> watchUTXO({ + _i10.Stream<_i28.UTXO?> watchUTXO({ required int? id, bool? fireImmediately = false, }) => @@ -1671,54 +1644,54 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i11.Stream<_i29.UTXO?>.empty(), - ) as _i11.Stream<_i29.UTXO?>); + returnValue: _i10.Stream<_i28.UTXO?>.empty(), + ) as _i10.Stream<_i28.UTXO?>); @override - _i9.QueryBuilder<_i29.TransactionNote, _i29.TransactionNote, - _i9.QAfterWhereClause> getTransactionNotes( + _i8.QueryBuilder<_i28.TransactionNote, _i28.TransactionNote, + _i8.QAfterWhereClause> getTransactionNotes( String? walletId) => (super.noSuchMethod( Invocation.method( #getTransactionNotes, [walletId], ), - returnValue: _FakeQueryBuilder_8<_i29.TransactionNote, - _i29.TransactionNote, _i9.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_7<_i28.TransactionNote, + _i28.TransactionNote, _i8.QAfterWhereClause>( this, Invocation.method( #getTransactionNotes, [walletId], ), ), - ) as _i9.QueryBuilder<_i29.TransactionNote, _i29.TransactionNote, - _i9.QAfterWhereClause>); + ) as _i8.QueryBuilder<_i28.TransactionNote, _i28.TransactionNote, + _i8.QAfterWhereClause>); @override - _i11.Future putTransactionNote(_i29.TransactionNote? transactionNote) => + _i10.Future putTransactionNote(_i28.TransactionNote? transactionNote) => (super.noSuchMethod( Invocation.method( #putTransactionNote, [transactionNote], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future putTransactionNotes( - List<_i29.TransactionNote>? transactionNotes) => + _i10.Future putTransactionNotes( + List<_i28.TransactionNote>? transactionNotes) => (super.noSuchMethod( Invocation.method( #putTransactionNotes, [transactionNotes], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future<_i29.TransactionNote?> getTransactionNote( + _i10.Future<_i28.TransactionNote?> getTransactionNote( String? walletId, String? txid, ) => @@ -1730,11 +1703,11 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { txid, ], ), - returnValue: _i11.Future<_i29.TransactionNote?>.value(), - ) as _i11.Future<_i29.TransactionNote?>); + returnValue: _i10.Future<_i28.TransactionNote?>.value(), + ) as _i10.Future<_i28.TransactionNote?>); @override - _i11.Stream<_i29.TransactionNote?> watchTransactionNote({ + _i10.Stream<_i28.TransactionNote?> watchTransactionNote({ required int? id, bool? fireImmediately = false, }) => @@ -1747,39 +1720,39 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i11.Stream<_i29.TransactionNote?>.empty(), - ) as _i11.Stream<_i29.TransactionNote?>); + returnValue: _i10.Stream<_i28.TransactionNote?>.empty(), + ) as _i10.Stream<_i28.TransactionNote?>); @override - _i9.QueryBuilder<_i29.AddressLabel, _i29.AddressLabel, _i9.QAfterWhereClause> + _i8.QueryBuilder<_i28.AddressLabel, _i28.AddressLabel, _i8.QAfterWhereClause> getAddressLabels(String? walletId) => (super.noSuchMethod( Invocation.method( #getAddressLabels, [walletId], ), - returnValue: _FakeQueryBuilder_8<_i29.AddressLabel, - _i29.AddressLabel, _i9.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_7<_i28.AddressLabel, + _i28.AddressLabel, _i8.QAfterWhereClause>( this, Invocation.method( #getAddressLabels, [walletId], ), ), - ) as _i9.QueryBuilder<_i29.AddressLabel, _i29.AddressLabel, - _i9.QAfterWhereClause>); + ) as _i8.QueryBuilder<_i28.AddressLabel, _i28.AddressLabel, + _i8.QAfterWhereClause>); @override - _i11.Future putAddressLabel(_i29.AddressLabel? addressLabel) => + _i10.Future putAddressLabel(_i28.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #putAddressLabel, [addressLabel], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - int putAddressLabelSync(_i29.AddressLabel? addressLabel) => + int putAddressLabelSync(_i28.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #putAddressLabelSync, @@ -1789,18 +1762,18 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { ) as int); @override - _i11.Future putAddressLabels(List<_i29.AddressLabel>? addressLabels) => + _i10.Future putAddressLabels(List<_i28.AddressLabel>? addressLabels) => (super.noSuchMethod( Invocation.method( #putAddressLabels, [addressLabels], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future<_i29.AddressLabel?> getAddressLabel( + _i10.Future<_i28.AddressLabel?> getAddressLabel( String? walletId, String? addressString, ) => @@ -1812,11 +1785,11 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { addressString, ], ), - returnValue: _i11.Future<_i29.AddressLabel?>.value(), - ) as _i11.Future<_i29.AddressLabel?>); + returnValue: _i10.Future<_i28.AddressLabel?>.value(), + ) as _i10.Future<_i28.AddressLabel?>); @override - _i29.AddressLabel? getAddressLabelSync( + _i28.AddressLabel? getAddressLabelSync( String? walletId, String? addressString, ) => @@ -1826,10 +1799,10 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { walletId, addressString, ], - )) as _i29.AddressLabel?); + )) as _i28.AddressLabel?); @override - _i11.Stream<_i29.AddressLabel?> watchAddressLabel({ + _i10.Stream<_i28.AddressLabel?> watchAddressLabel({ required int? id, bool? fireImmediately = false, }) => @@ -1842,55 +1815,55 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i11.Stream<_i29.AddressLabel?>.empty(), - ) as _i11.Stream<_i29.AddressLabel?>); + returnValue: _i10.Stream<_i28.AddressLabel?>.empty(), + ) as _i10.Stream<_i28.AddressLabel?>); @override - _i11.Future updateAddressLabel(_i29.AddressLabel? addressLabel) => + _i10.Future updateAddressLabel(_i28.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #updateAddressLabel, [addressLabel], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i11.Future deleteWalletBlockchainData(String? walletId) => + _i10.Future deleteWalletBlockchainData(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteWalletBlockchainData, [walletId], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future deleteAddressLabels(String? walletId) => + _i10.Future deleteAddressLabels(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteAddressLabels, [walletId], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future deleteTransactionNotes(String? walletId) => + _i10.Future deleteTransactionNotes(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteTransactionNotes, [walletId], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future addNewTransactionData( - List<_i7.Tuple2<_i29.Transaction, _i29.Address?>>? transactionsData, + _i10.Future addNewTransactionData( + List<_i29.Tuple2<_i28.Transaction, _i28.Address?>>? transactionsData, String? walletId, ) => (super.noSuchMethod( @@ -1901,93 +1874,93 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { walletId, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future> updateOrPutTransactionV2s( + _i10.Future> updateOrPutTransactionV2s( List<_i30.TransactionV2>? transactions) => (super.noSuchMethod( Invocation.method( #updateOrPutTransactionV2s, [transactions], ), - returnValue: _i11.Future>.value([]), - ) as _i11.Future>); + returnValue: _i10.Future>.value([]), + ) as _i10.Future>); @override - _i9.QueryBuilder<_i29.EthContract, _i29.EthContract, _i9.QWhere> + _i8.QueryBuilder<_i28.EthContract, _i28.EthContract, _i8.QWhere> getEthContracts() => (super.noSuchMethod( Invocation.method( #getEthContracts, [], ), - returnValue: _FakeQueryBuilder_8<_i29.EthContract, _i29.EthContract, - _i9.QWhere>( + returnValue: _FakeQueryBuilder_7<_i28.EthContract, _i28.EthContract, + _i8.QWhere>( this, Invocation.method( #getEthContracts, [], ), ), - ) as _i9 - .QueryBuilder<_i29.EthContract, _i29.EthContract, _i9.QWhere>); + ) as _i8 + .QueryBuilder<_i28.EthContract, _i28.EthContract, _i8.QWhere>); @override - _i11.Future<_i29.EthContract?> getEthContract(String? contractAddress) => + _i10.Future<_i28.EthContract?> getEthContract(String? contractAddress) => (super.noSuchMethod( Invocation.method( #getEthContract, [contractAddress], ), - returnValue: _i11.Future<_i29.EthContract?>.value(), - ) as _i11.Future<_i29.EthContract?>); + returnValue: _i10.Future<_i28.EthContract?>.value(), + ) as _i10.Future<_i28.EthContract?>); @override - _i29.EthContract? getEthContractSync(String? contractAddress) => + _i28.EthContract? getEthContractSync(String? contractAddress) => (super.noSuchMethod(Invocation.method( #getEthContractSync, [contractAddress], - )) as _i29.EthContract?); + )) as _i28.EthContract?); @override - _i11.Future putEthContract(_i29.EthContract? contract) => + _i10.Future putEthContract(_i28.EthContract? contract) => (super.noSuchMethod( Invocation.method( #putEthContract, [contract], ), - returnValue: _i11.Future.value(0), - ) as _i11.Future); + returnValue: _i10.Future.value(0), + ) as _i10.Future); @override - _i11.Future putEthContracts(List<_i29.EthContract>? contracts) => + _i10.Future putEthContracts(List<_i28.EthContract>? contracts) => (super.noSuchMethod( Invocation.method( #putEthContracts, [contracts], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); @override - _i11.Future getHighestUsedMintIndex({required String? walletId}) => + _i10.Future getHighestUsedMintIndex({required String? walletId}) => (super.noSuchMethod( Invocation.method( #getHighestUsedMintIndex, [], {#walletId: walletId}, ), - returnValue: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i10.Future.value(), + ) as _i10.Future); } /// A class which mocks [IThemeAssets]. /// /// See the documentation for Mockito's code generation for more information. -class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { +class MockIThemeAssets extends _i1.Mock implements _i24.IThemeAssets { MockIThemeAssets() { _i1.throwOnMissingStub(this); } @@ -1995,7 +1968,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get bellNew => (super.noSuchMethod( Invocation.getter(#bellNew), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#bellNew), ), @@ -2004,7 +1977,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get buy => (super.noSuchMethod( Invocation.getter(#buy), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#buy), ), @@ -2013,7 +1986,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get exchange => (super.noSuchMethod( Invocation.getter(#exchange), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#exchange), ), @@ -2022,7 +1995,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get personaIncognito => (super.noSuchMethod( Invocation.getter(#personaIncognito), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#personaIncognito), ), @@ -2031,7 +2004,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get personaEasy => (super.noSuchMethod( Invocation.getter(#personaEasy), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#personaEasy), ), @@ -2040,7 +2013,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get stack => (super.noSuchMethod( Invocation.getter(#stack), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#stack), ), @@ -2049,7 +2022,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get stackIcon => (super.noSuchMethod( Invocation.getter(#stackIcon), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#stackIcon), ), @@ -2058,7 +2031,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get receive => (super.noSuchMethod( Invocation.getter(#receive), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#receive), ), @@ -2067,7 +2040,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get receivePending => (super.noSuchMethod( Invocation.getter(#receivePending), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#receivePending), ), @@ -2076,7 +2049,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get receiveCancelled => (super.noSuchMethod( Invocation.getter(#receiveCancelled), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#receiveCancelled), ), @@ -2085,7 +2058,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get send => (super.noSuchMethod( Invocation.getter(#send), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#send), ), @@ -2094,7 +2067,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get sendPending => (super.noSuchMethod( Invocation.getter(#sendPending), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#sendPending), ), @@ -2103,7 +2076,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get sendCancelled => (super.noSuchMethod( Invocation.getter(#sendCancelled), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#sendCancelled), ), @@ -2112,7 +2085,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get themeSelector => (super.noSuchMethod( Invocation.getter(#themeSelector), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#themeSelector), ), @@ -2121,7 +2094,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get themePreview => (super.noSuchMethod( Invocation.getter(#themePreview), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#themePreview), ), @@ -2130,7 +2103,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get txExchange => (super.noSuchMethod( Invocation.getter(#txExchange), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#txExchange), ), @@ -2139,7 +2112,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get txExchangePending => (super.noSuchMethod( Invocation.getter(#txExchangePending), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#txExchangePending), ), @@ -2148,7 +2121,7 @@ class MockIThemeAssets extends _i1.Mock implements _i25.IThemeAssets { @override String get txExchangeFailed => (super.noSuchMethod( Invocation.getter(#txExchangeFailed), - returnValue: _i16.dummyValue( + returnValue: _i15.dummyValue( this, Invocation.getter(#txExchangeFailed), ), From 5bd1bcb278ab567bc24f5bd963b2cf157872d218 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Apr 2025 07:01:18 -0600 Subject: [PATCH 006/206] update liblelantus ref --- crypto_plugins/flutter_liblelantus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_liblelantus b/crypto_plugins/flutter_liblelantus index 7b325030b..081ae89d8 160000 --- a/crypto_plugins/flutter_liblelantus +++ b/crypto_plugins/flutter_liblelantus @@ -1 +1 @@ -Subproject commit 7b325030bce46a423aa46497d1a608b7a8a58976 +Subproject commit 081ae89d8f47f5575a19dc03663727cf0d271f2c From 0f801cc02ea59c9b449c2bdf99e26bbe68e81c63 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Apr 2025 13:58:15 -0600 Subject: [PATCH 007/206] replace deprecated calls and formatting --- .../crypto_currency/coins/ethereum.dart | 24 ++-- lib/wallets/wallet/impl/ethereum_wallet.dart | 65 ++++----- .../impl/sub_wallets/eth_token_wallet.dart | 126 +++++++++--------- 3 files changed, 98 insertions(+), 117 deletions(-) diff --git a/lib/wallets/crypto_currency/coins/ethereum.dart b/lib/wallets/crypto_currency/coins/ethereum.dart index 1d7bb53ed..bb12d0bb4 100644 --- a/lib/wallets/crypto_currency/coins/ethereum.dart +++ b/lib/wallets/crypto_currency/coins/ethereum.dart @@ -48,18 +48,18 @@ class Ethereum extends Bip39Currency { @override NodeModel get defaultNode => NodeModel( - host: "https://eth.stackwallet.com", - port: 443, - name: DefaultNodes.defaultName, - id: DefaultNodes.buildId(this), - useSSL: true, - enabled: true, - coinName: identifier, - isFailover: true, - isDown: false, - torEnabled: true, - clearnetEnabled: true, - ); + host: "https://eth.stackwallet.com", + port: 443, + name: DefaultNodes.defaultName, + id: DefaultNodes.buildId(this), + useSSL: true, + enabled: true, + coinName: identifier, + isFailover: true, + isDown: false, + torEnabled: true, + clearnetEnabled: true, + ); @override // Not used for eth diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index e61da1df6..71d5a7279 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -59,7 +59,8 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { Amount estimateEthFee(int feeRate, int gasLimit, int decimals) { final gweiAmount = feeRate.toDecimal() / (Decimal.ten.pow(9).toDecimal()); - final fee = gasLimit.toDecimal() * + final fee = + gasLimit.toDecimal() * gweiAmount.toDecimal( scaleOnInfinitePrecision: cryptoCurrency.fractionDigits, ); @@ -95,9 +96,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: amount.raw.toString(), - addresses: [ - addressTo, - ], + addresses: [addressTo], walletOwns: addressTo == myAddress, ); final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( @@ -132,16 +131,15 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), version: -1, - type: addressTo == myAddress - ? TransactionType.sentToSelf - : TransactionType.outgoing, + type: + addressTo == myAddress + ? TransactionType.sentToSelf + : TransactionType.outgoing, subType: TransactionSubType.none, otherData: jsonEncode(otherData), ); - return txData.copyWith( - tempTx: txn, - ); + return txData.copyWith(tempTx: txn); } // ==================== Overrides ============================================ @@ -151,11 +149,11 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { @override FilterOperation? get transactionFilterOperation => FilterGroup.not( - const FilterCondition.equalTo( - property: r"subType", - value: TransactionSubType.ethToken, - ), - ); + const FilterCondition.equalTo( + property: r"subType", + value: TransactionSubType.ethToken, + ), + ); @override FilterOperation? get changeAddressFilterOperation => @@ -235,10 +233,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { fractionDigits: cryptoCurrency.fractionDigits, ), ); - await info.updateBalance( - newBalance: balance, - isar: mainDB.isar, - ); + await info.updateBalance(newBalance: balance, isar: mainDB.isar); } catch (e, s) { Logging.instance.w( "$runtimeType wallet failed to update balance: ", @@ -254,10 +249,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final client = getEthClient(); final height = await client.getBlockNumber(); - await info.updateCachedChainHeight( - newHeight: height, - isar: mainDB.isar, - ); + await info.updateCachedChainHeight(newHeight: height, isar: mainDB.isar); } catch (e, s) { Logging.instance.w( "$runtimeType Exception caught in chainHeight: ", @@ -279,7 +271,8 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { int firstBlock = 0; if (!isRescan) { - firstBlock = await mainDB.isar.transactionV2s + firstBlock = + await mainDB.isar.transactionV2s .where() .walletIdEqualTo(walletId) .heightProperty() @@ -311,8 +304,9 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { return; } - final txsResponse = - await EthereumAPI.getEthTransactionNonces(response.value!); + final txsResponse = await EthereumAPI.getEthTransactionNonces( + response.value!, + ); if (txsResponse.value != null) { final allTxs = txsResponse.value!; @@ -351,9 +345,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: transactionAmount.raw.toString(), - addresses: [ - addressTo, - ], + addresses: [addressTo], walletOwns: addressTo == thisAddress, ); final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( @@ -424,7 +416,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { @override Future prepareSend({required TxData txData}) async { final int - rate; // TODO: use BigInt for feeObject whenever FeeObject gets redone + rate; // TODO: use BigInt for feeObject whenever FeeObject gets redone final feeObject = await fees; switch (txData.feeRateType!) { case FeeRateType.fast: @@ -472,7 +464,8 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { // value: web3.EtherAmount.inWei(amount.raw), // ); - final nonce = txData.nonce ?? + final nonce = + txData.nonce ?? await client.getTransactionCount( myWeb3Address, atBlock: const web3.BlockNum.pending(), @@ -488,10 +481,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final tx = web3.Transaction( to: web3.EthereumAddress.fromHex(address), - gasPrice: web3.EtherAmount.fromUnitAndValue( - web3.EtherUnit.wei, - rate, - ), + gasPrice: web3.EtherAmount.fromInt(web3.EtherUnit.wei, rate), maxGas: (cryptoCurrency as Ethereum).gasLimit, value: web3.EtherAmount.inWei(amount.raw), nonce: nonce, @@ -523,10 +513,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { ); final data = (prepareTempTx ?? _prepareTempTx)( - txData.copyWith( - txid: txid, - txHash: txid, - ), + txData.copyWith(txid: txid, txHash: txid), (await getCurrentReceivingAddress())!.value, ); diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index 845b0282b..29f96438e 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -29,7 +29,7 @@ class EthTokenWallet extends Wallet { int get isarTransactionVersion => 2; EthTokenWallet(this.ethWallet, this._tokenContract) - : super(ethWallet.cryptoCurrency); + : super(ethWallet.cryptoCurrency); final EthereumWallet ethWallet; @@ -39,7 +39,7 @@ class EthTokenWallet extends Wallet { late web3dart.DeployedContract _deployedContract; late web3dart.ContractFunction _sendFunction; - static const _gasLimit = 65000; + static const gasLimit = 65000; // =========================================================================== @@ -85,9 +85,7 @@ class EthTokenWallet extends Wallet { final output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: amount.raw.toString(), - addresses: [ - addressTo, - ], + addresses: [addressTo], walletOwns: addressTo == myAddress, ); final input = InputV2.isarCantDoRequiredInDefaultConstructor( @@ -116,16 +114,15 @@ class EthTokenWallet extends Wallet { inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), version: -1, - type: addressTo == myAddress - ? TransactionType.sentToSelf - : TransactionType.outgoing, + type: + addressTo == myAddress + ? TransactionType.sentToSelf + : TransactionType.outgoing, subType: TransactionSubType.ethToken, otherData: jsonEncode(otherData), ); - return txData.copyWith( - tempTx: tempTx, - ); + return txData.copyWith(tempTx: tempTx); } // =========================================================================== @@ -143,8 +140,9 @@ class EthTokenWallet extends Wallet { try { await super.init(); - final contractAddress = - web3dart.EthereumAddress.fromHex(tokenContract.address); + final contractAddress = web3dart.EthereumAddress.fromHex( + tokenContract.address, + ); // first try to update the abi regardless just in case something has changed try { @@ -153,8 +151,11 @@ class EthTokenWallet extends Wallet { usingContractAddress: contractAddress.hex, ); } catch (e, s) { - Logging.instance - .w("$runtimeType _updateTokenABI(): ", error: e, stackTrace: s); + Logging.instance.w( + "$runtimeType _updateTokenABI(): ", + error: e, + stackTrace: s, + ); } try { @@ -176,8 +177,8 @@ class EthTokenWallet extends Wallet { // Some failure, try for proxy contract final contractAddressResponse = await EthereumAPI.getProxyTokenImplementationAddress( - contractAddress.hex, - ); + contractAddress.hex, + ); if (contractAddressResponse.value != null) { _tokenContract = await _updateTokenABI( @@ -198,8 +199,11 @@ class EthTokenWallet extends Wallet { _sendFunction = _deployedContract.function('transfer'); } catch (e, s) { - Logging.instance - .w("$runtimeType wallet failed init(): ", error: e, stackTrace: s); + Logging.instance.w( + "$runtimeType wallet failed init(): ", + error: e, + stackTrace: s, + ); } } @@ -229,7 +233,8 @@ class EthTokenWallet extends Wallet { final myAddress = (await getCurrentReceivingAddress())!.value; final myWeb3Address = web3dart.EthereumAddress.fromHex(myAddress); - final nonce = txData.nonce ?? + final nonce = + txData.nonce ?? await client.getTransactionCount( myWeb3Address, atBlock: const web3dart.BlockNum.pending(), @@ -239,14 +244,14 @@ class EthTokenWallet extends Wallet { final address = txData.recipients!.first.address; await updateBalance(); - final info = await mainDB.isar.tokenWalletInfo - .where() - .walletIdTokenAddressEqualTo(walletId, tokenContract.address) - .findFirst(); - final availableBalance = info?.getCachedBalance().spendable ?? - Amount.zeroWith( - fractionDigits: tokenContract.decimals, - ); + final info = + await mainDB.isar.tokenWalletInfo + .where() + .walletIdTokenAddressEqualTo(walletId, tokenContract.address) + .findFirst(); + final availableBalance = + info?.getCachedBalance().spendable ?? + Amount.zeroWith(fractionDigits: tokenContract.decimals); if (amount > availableBalance) { throw Exception("Insufficient balance"); } @@ -255,11 +260,8 @@ class EthTokenWallet extends Wallet { contract: _deployedContract, function: _sendFunction, parameters: [web3dart.EthereumAddress.fromHex(address), amount.raw], - maxGas: _gasLimit, - gasPrice: web3dart.EtherAmount.fromUnitAndValue( - web3dart.EtherUnit.wei, - fee, - ), + maxGas: gasLimit, + gasPrice: web3dart.EtherAmount.fromInt(web3dart.EtherUnit.wei, fee), nonce: nonce, ); @@ -289,7 +291,7 @@ class EthTokenWallet extends Wallet { Future estimateFeeFor(Amount amount, int feeRate) async { return ethWallet.estimateEthFee( feeRate, - _gasLimit, + gasLimit, cryptoCurrency.fractionDigits, ); } @@ -317,10 +319,11 @@ class EthTokenWallet extends Wallet { @override Future updateBalance() async { try { - final info = await mainDB.isar.tokenWalletInfo - .where() - .walletIdTokenAddressEqualTo(walletId, tokenContract.address) - .findFirst(); + final info = + await mainDB.isar.tokenWalletInfo + .where() + .walletIdTokenAddressEqualTo(walletId, tokenContract.address) + .findFirst(); final response = await EthereumAPI.getWalletTokenBalance( address: (await getCurrentReceivingAddress())!.value, contractAddress: tokenContract.address, @@ -364,8 +367,9 @@ class EthTokenWallet extends Wallet { @override Future updateTransactions() async { try { - final String addressString = - checksumEthereumAddress((await getCurrentReceivingAddress())!.value); + final String addressString = checksumEthereumAddress( + (await getCurrentReceivingAddress())!.value, + ); final response = await EthereumAPI.getTokenTransactions( address: addressString, @@ -374,8 +378,9 @@ class EthTokenWallet extends Wallet { if (response.value == null) { if (response.exception != null && - response.exception!.message - .contains("response is empty but status code is 200")) { + response.exception!.message.contains( + "response is empty but status code is 200", + )) { Logging.instance.d( "No ${tokenContract.name} transfers found for $addressString", ); @@ -404,12 +409,7 @@ class EthTokenWallet extends Wallet { final txExtra = response2.value!.firstWhere( (e) => e.hash == tokenDto.transactionHash, ); - data.add( - ( - tx: tokenDto, - extra: txExtra, - ), - ); + data.add((tx: tokenDto, extra: txExtra)); } catch (e, s) { // Server indexing failed for some reason. Instead of hard crashing or // showing no transactions we just skip it here. Not ideal but better @@ -443,12 +443,8 @@ class EthTokenWallet extends Wallet { } final Amount txFee = tuple.extra.gasUsed * tuple.extra.gasPrice; - final addressFrom = _addressFromTopic( - tuple.tx.topics[1], - ); - final addressTo = _addressFromTopic( - tuple.tx.topics[2], - ); + final addressFrom = _addressFromTopic(tuple.tx.topics[1]); + final addressTo = _addressFromTopic(tuple.tx.topics[2]); final TransactionType txType; if (addressTo == addressString) { @@ -483,9 +479,7 @@ class EthTokenWallet extends Wallet { final output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: amount.raw.toString(), - addresses: [ - addressTo, - ], + addresses: [addressTo], walletOwns: addressTo == addressString, ); final input = InputV2.isarCantDoRequiredInDefaultConstructor( @@ -544,15 +538,15 @@ class EthTokenWallet extends Wallet { @override FilterOperation? get transactionFilterOperation => FilterGroup.and([ - FilterCondition.equalTo( - property: r"contractAddress", - value: tokenContract.address, - ), - const FilterCondition.equalTo( - property: r"subType", - value: TransactionSubType.ethToken, - ), - ]); + FilterCondition.equalTo( + property: r"contractAddress", + value: tokenContract.address, + ), + const FilterCondition.equalTo( + property: r"subType", + value: TransactionSubType.ethToken, + ), + ]); @override Future checkSaveInitialReceivingAddress() async { From 84d63c2384ff6fd0fbf91099a973904824f86ace Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Apr 2025 14:41:51 -0600 Subject: [PATCH 008/206] fix eth sent amount display bug --- .../blockchain_data/v2/transaction_v2.dart | 41 ++--- .../tx_v2/all_transactions_v2_view.dart | 3 + .../tx_v2/boost_transaction_view.dart | 159 +++++++++--------- .../tx_v2/transaction_v2_card.dart | 2 + .../tx_v2/transaction_v2_details_view.dart | 3 + 5 files changed, 105 insertions(+), 103 deletions(-) diff --git a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart index b7a92c26e..378e93d0f 100644 --- a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart +++ b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart @@ -135,8 +135,9 @@ class TransactionV2 { return Amount.zeroWith(fractionDigits: fractionDigits); } - final inSum = - inputs.map((e) => e.value).reduce((value, element) => value += element); + final inSum = inputs + .map((e) => e.value) + .reduce((value, element) => value += element); final outSum = outputs .map((e) => e.value) .reduce((value, element) => value += element); @@ -161,15 +162,20 @@ class TransactionV2 { } Amount getAmountSparkSelfMinted({required int fractionDigits}) { - final outSum = outputs.where((e) { - final op = e.scriptPubKeyHex.substring(0, 2).toUint8ListFromHex.first; - return e.walletOwns && (op == OP_SPARKMINT); - }).fold(BigInt.zero, (p, e) => p + e.value); + final outSum = outputs + .where((e) { + final op = e.scriptPubKeyHex.substring(0, 2).toUint8ListFromHex.first; + return e.walletOwns && (op == OP_SPARKMINT); + }) + .fold(BigInt.zero, (p, e) => p + e.value); return Amount(rawValue: outSum, fractionDigits: fractionDigits); } - Amount getAmountSentFromThisWallet({required int fractionDigits}) { + Amount getAmountSentFromThisWallet({ + required int fractionDigits, + required bool subtractFee, + }) { if (_isMonero()) { if (type == TransactionType.outgoing) { return _getMoneroAmount()!; @@ -182,15 +188,11 @@ class TransactionV2 { .where((e) => e.walletOwns) .fold(BigInt.zero, (p, e) => p + e.value); - Amount amount = Amount( - rawValue: inSum, - fractionDigits: fractionDigits, - ) - - getAmountReceivedInThisWallet( - fractionDigits: fractionDigits, - ); + Amount amount = + Amount(rawValue: inSum, fractionDigits: fractionDigits) - + getAmountReceivedInThisWallet(fractionDigits: fractionDigits); - if (subType != TransactionSubType.ethToken) { + if (subtractFee) { amount = amount - getFee(fractionDigits: fractionDigits); } @@ -204,9 +206,9 @@ class TransactionV2 { } Set associatedAddresses() => { - ...inputs.map((e) => e.addresses).expand((e) => e), - ...outputs.map((e) => e.addresses).expand((e) => e), - }; + ...inputs.map((e) => e.addresses).expand((e) => e), + ...outputs.map((e) => e.addresses).expand((e) => e), + }; Amount? _getOverrideFee() { try { @@ -238,7 +240,8 @@ class TransactionV2 { required int minConfirms, required int minCoinbaseConfirms, }) { - String prettyConfirms() => "(" + String prettyConfirms() => + "(" "${getConfirmations(currentChainHeight)}" "/" "${(isCoinbase() ? minCoinbaseConfirms : minConfirms)}" diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart index c821be3a8..353264600 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart @@ -33,6 +33,7 @@ import '../../../../utilities/constants.dart'; import '../../../../utilities/format.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; +import '../../../../wallets/crypto_currency/coins/ethereum.dart'; import '../../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; @@ -931,6 +932,7 @@ class _DesktopTransactionCardRowState case TransactionType.outgoing: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); break; @@ -962,6 +964,7 @@ class _DesktopTransactionCardRowState case TransactionType.unknown: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); break; } diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart index 34abbb43e..5219b3f26 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart @@ -23,6 +23,7 @@ import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/show_loading.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; +import '../../../../wallets/crypto_currency/coins/ethereum.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; import '../../../../widgets/background.dart'; @@ -37,10 +38,7 @@ import '../../../../widgets/stack_dialog.dart'; import '../../../send_view/confirm_transaction_view.dart'; class BoostTransactionView extends ConsumerStatefulWidget { - const BoostTransactionView({ - super.key, - required this.transaction, - }); + const BoostTransactionView({super.key, required this.transaction}); static const String routeName = "/boostTransaction"; @@ -73,10 +71,11 @@ class _BoostTransactionViewState extends ConsumerState { if (_newRate <= rate) { await showDialog( context: context, - builder: (_) => const StackOkDialog( - title: "Error", - message: "New fee rate must be greater than the current rate.", - ), + builder: + (_) => const StackOkDialog( + title: "Error", + message: "New fee rate must be greater than the current rate.", + ), ); return; } @@ -99,11 +98,12 @@ class _BoostTransactionViewState extends ConsumerState { if (txData == null && mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "RBF send error", - message: ex?.toString() ?? "Unknown error found", - maxWidth: 600, - ), + builder: + (_) => StackOkDialog( + title: "RBF send error", + message: ex?.toString() ?? "Unknown error found", + maxWidth: 600, + ), ); return; } else { @@ -112,17 +112,18 @@ class _BoostTransactionViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: ConfirmTransactionView( - txData: txData!, - walletId: walletId, - onSuccess: () {}, - // isPaynymTransaction: isPaynymSend, TODO ? - routeOnSuccessName: DesktopHomeView.routeName, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: ConfirmTransactionView( + txData: txData!, + walletId: walletId, + onSuccess: () {}, + // isPaynymTransaction: isPaynymSend, TODO ? + routeOnSuccessName: DesktopHomeView.routeName, + ), + ), ), ); } else if (mounted) { @@ -130,12 +131,13 @@ class _BoostTransactionViewState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: txData!, - walletId: walletId, - // isPaynymTransaction: isPaynymSend, TODO ? - onSuccess: () {}, - ), + builder: + (_) => ConfirmTransactionView( + txData: txData!, + walletId: walletId, + // isPaynymTransaction: isPaynymSend, TODO ? + onSuccess: () {}, + ), settings: const RouteSettings( name: ConfirmTransactionView.routeName, ), @@ -159,6 +161,7 @@ class _BoostTransactionViewState extends ConsumerState { ); amount = _transaction.getAmountSentFromThisWallet( fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, + subtractFee: ref.read(pWalletCoin(walletId)) is! Ethereum, ); rate = (fee.raw ~/ BigInt.from(_transaction.vSize!)).toInt(); _newRate = rate + 1; @@ -169,61 +172,56 @@ class _BoostTransactionViewState extends ConsumerState { @override Widget build(BuildContext context) { final coin = ref.watch(pWalletCoin(walletId)); - final String feeString = ref.watch(pAmountFormatter(coin)).format( - fee, - ); - final String amountString = ref.watch(pAmountFormatter(coin)).format( - amount, - ); + final String feeString = ref.watch(pAmountFormatter(coin)).format(fee); + final String amountString = ref + .watch(pAmountFormatter(coin)) + .format(amount); final String feeRateString = "$rate sats/vByte"; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Boost transaction", - style: STextStyles.navBarTitle(context), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Boost transaction", + style: STextStyles.navBarTitle(context), + ), + ), + body: child, ), ), - body: child, - ), - ), child: Padding( - padding: isDesktop - ? const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.only(left: 32, right: 32, bottom: 32) + : const EdgeInsets.all(12), child: ConditionalParent( condition: isDesktop, builder: (child) { return Column( children: [ RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, padding: const EdgeInsets.all(0), child: child, ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), PrimaryButton( buttonHeight: ButtonHeight.l, label: "Preview send", @@ -238,10 +236,11 @@ class _BoostTransactionViewState extends ConsumerState { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => RoundedWhiteContainer( - padding: EdgeInsets.zero, - child: child, - ), + builder: + (child) => RoundedWhiteContainer( + padding: EdgeInsets.zero, + child: child, + ), child: Column( children: [ DetailItem( @@ -277,15 +276,9 @@ class _BoostTransactionViewState extends ConsumerState { ), ), if (!isDesktop) const Spacer(), + if (!isDesktop) const SizedBox(height: 16), if (!isDesktop) - const SizedBox( - height: 16, - ), - if (!isDesktop) - PrimaryButton( - label: "Preview send", - onPressed: _previewTxn, - ), + PrimaryButton(label: "Preview send", onPressed: _previewTxn), ], ), ), @@ -305,9 +298,7 @@ class _Divider extends StatelessWidget { color: Theme.of(context).extension()!.backgroundAppBar, ); } else { - return const SizedBox( - height: 12, - ); + return const SizedBox(height: 12); } } } diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart index fbc9c0009..9af007aef 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart @@ -136,6 +136,7 @@ class _TransactionCardStateV2 extends ConsumerState { case TransactionType.outgoing: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); break; @@ -167,6 +168,7 @@ class _TransactionCardStateV2 extends ConsumerState { case TransactionType.unknown: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); break; } diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index c4f158367..06469c92b 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -233,6 +233,7 @@ class _TransactionV2DetailsViewState case TransactionType.unknown: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); break; @@ -277,6 +278,7 @@ class _TransactionV2DetailsViewState case TransactionType.outgoing: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); data = _transaction.outputs @@ -363,6 +365,7 @@ class _TransactionV2DetailsViewState case TransactionType.unknown: amount = _transaction.getAmountSentFromThisWallet( fractionDigits: fractionDigits, + subtractFee: coin is! Ethereum, ); data = _transaction.inputs From 17c43eb6c0fbdb4f7f8e7b0b5e2692f7c7e6afef Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Apr 2025 15:02:29 -0600 Subject: [PATCH 009/206] log acceptable error as INFO (and some auto formatting) --- lib/utilities/address_utils.dart | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index 171dc09b2..d14e4e809 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -33,8 +33,9 @@ class AddressUtils { /// Return only recognized parameters. static Map _filterParams(Map params) { return Map.fromEntries( - params.entries - .where((entry) => recognizedParams.contains(entry.key.toLowerCase())), + params.entries.where( + (entry) => recognizedParams.contains(entry.key.toLowerCase()), + ), ); } @@ -52,8 +53,10 @@ class AddressUtils { result["address"] = u.path; } else if (result["scheme"] == "monero") { // Monero addresses can contain '?' which Uri.parse interprets as query start. - final addressEnd = - uri.indexOf('?', 7); // 7 is the length of "monero:". + final addressEnd = uri.indexOf( + '?', + 7, + ); // 7 is the length of "monero:". if (addressEnd != -1) { result["address"] = uri.substring(7, addressEnd); } else { @@ -130,10 +133,7 @@ class AddressUtils { /// Centralized method to handle various cryptocurrency URIs and return a common object. /// /// Returns null on failure to parse - static PaymentUriData? parsePaymentUri( - String uri, { - Logging? logging, - }) { + static PaymentUriData? parsePaymentUri(String uri, {Logging? logging}) { try { final Map parsedData = _parseUri(uri); @@ -155,7 +155,7 @@ class AddressUtils { additionalParams: filteredParams, ); } catch (e, s) { - logging?.e("", error: e, stackTrace: s); + logging?.i("Invalid payment URI: $uri", error: e, stackTrace: s); return null; } } @@ -259,8 +259,8 @@ class PaymentUriData { final Map additionalParams; CryptoCurrency? get coin => AddressUtils._getCryptoCurrencyByScheme( - scheme ?? "", // empty will just return null - ); + scheme ?? "", // empty will just return null + ); PaymentUriData({ required this.address, @@ -273,7 +273,8 @@ class PaymentUriData { }); @override - String toString() => "PaymentUriData { " + String toString() => + "PaymentUriData { " "coin: $coin, " "address: $address, " "amount: $amount, " From 724e5cd397bfde5ec2bad82ff1c560ecb63d3e46 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Apr 2025 15:03:13 -0600 Subject: [PATCH 010/206] don't refresh provider that is not used for eth --- lib/pages/namecoin_names/confirm_name_transaction_view.dart | 5 ++++- lib/pages/send_view/confirm_transaction_view.dart | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/pages/namecoin_names/confirm_name_transaction_view.dart b/lib/pages/namecoin_names/confirm_name_transaction_view.dart index 61e8646ab..11dbb5c16 100644 --- a/lib/pages/namecoin_names/confirm_name_transaction_view.dart +++ b/lib/pages/namecoin_names/confirm_name_transaction_view.dart @@ -33,6 +33,7 @@ import '../../utilities/constants.dart'; import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; +import '../../wallets/crypto_currency/coins/ethereum.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/models/tx_data.dart'; import '../../wallets/wallet/impl/namecoin_wallet.dart'; @@ -136,7 +137,9 @@ class _ConfirmNameTransactionViewState ]); txids.add(txData.txid!); - ref.refresh(desktopUseUTXOs); + if (coin is! Ethereum) { + ref.refresh(desktopUseUTXOs); + } // save note for (final txid in txids) { diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 33f07dbd5..0b7a70224 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -33,6 +33,7 @@ import '../../utilities/constants.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/coins/epiccash.dart'; +import '../../wallets/crypto_currency/coins/ethereum.dart'; import '../../wallets/crypto_currency/intermediate/nano_currency.dart'; import '../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; @@ -181,7 +182,9 @@ class _ConfirmTransactionViewState } else { txids.add((results.first as TxData).txid!); } - ref.refresh(desktopUseUTXOs); + if (coin is! Ethereum) { + ref.refresh(desktopUseUTXOs); + } // save note for (final txid in txids) { From 4b61ca39b15cfc7db8a3ed1bfdc908582cfa59e0 Mon Sep 17 00:00:00 2001 From: Julian Date: Sat, 5 Apr 2025 07:18:05 -0600 Subject: [PATCH 011/206] auto format on save --- lib/services/ethereum/ethereum_api.dart | 322 ++++++++---------------- 1 file changed, 102 insertions(+), 220 deletions(-) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index fccce0ceb..3d726247e 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -62,9 +62,10 @@ abstract class EthereumAPI { url: Uri.parse( "$stackBaseServer/export?addrs=$address&firstBlock=$firstBlock", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -80,17 +81,11 @@ abstract class EthereumAPI { txns.add(txn); } } - return EthereumResponse( - txns, - null, - ); + return EthereumResponse(txns, null); } else { // nice that the api returns an empty body instead of being // consistent and returning a json object with no transactions - return EthereumResponse( - [], - null, - ); + return EthereumResponse([], null); } } else { throw EthApiException( @@ -99,10 +94,7 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { Logging.instance.e("getEthTransactions()", error: e); Logging.instance.d( @@ -110,10 +102,7 @@ abstract class EthereumAPI { error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -122,21 +111,18 @@ abstract class EthereumAPI { ) async { try { final response = await client.post( - url: Uri.parse( - "$stackBaseServer/v1/mainnet", - ), + url: Uri.parse("$stackBaseServer/v1/mainnet"), headers: {'Content-Type': 'application/json'}, body: json.encode({ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", - "params": [ - txid, - ], + "params": [txid], "id": DateTime.now().millisecondsSinceEpoch, }), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -167,39 +153,29 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getEthTransactionByHash()", - error: e, - ); + Logging.instance.e("getEthTransactionByHash()", error: e); Logging.instance.d( "getEthTransactionByHash($txid)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } static Future>>> - getEthTransactionNonces( - List txns, - ) async { + getEthTransactionNonces(List txns) async { try { final response = await client.get( url: Uri.parse( "$stackBaseServer/transactions?transactions=${txns.map((e) => e.hash).join(" ")}&raw=true", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -210,23 +186,19 @@ abstract class EthereumAPI { final List> result = []; for (final dto in txns) { - final data = - list.firstWhere((e) => e["hash"] == dto.hash, orElse: () => {}); + final data = list.firstWhere( + (e) => e["hash"] == dto.hash, + orElse: () => {}, + ); final nonce = (data["nonce"] as String?)?.toBigIntFromHex.toInt(); result.add(Tuple2(dto, nonce)); } - return EthereumResponse( - result, - null, - ); + return EthereumResponse(result, null); } else { // nice that the api returns an empty body instead of being // consistent and returning a json object with no transactions - return EthereumResponse( - [], - null, - ); + return EthereumResponse([], null); } } else { throw EthApiException( @@ -235,37 +207,29 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getEthTransactionNonces()", - error: e, - ); + Logging.instance.e("getEthTransactionNonces()", error: e); Logging.instance.d( "getEthTransactionNonces($txns)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } static Future>> - getEthTokenTransactionsByTxids(List txids) async { + getEthTokenTransactionsByTxids(List txids) async { try { final response = await client.get( url: Uri.parse( "$stackBaseServer/transactions?transactions=${txids.join(" ")}", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -281,10 +245,7 @@ abstract class EthereumAPI { txns.add(txn); } - return EthereumResponse( - txns, - null, - ); + return EthereumResponse(txns, null); } else { throw EthApiException( "getEthTokenTransactionsByTxids($txids) response is empty but status code is " @@ -298,24 +259,15 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getEthTokenTransactionsByTxids()", - error: e, - ); + Logging.instance.e("getEthTokenTransactionsByTxids()", error: e); Logging.instance.d( "getEthTokenTransactionsByTxids($txids)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -328,9 +280,10 @@ abstract class EthereumAPI { url: Uri.parse( "$stackBaseServer/export?addrs=$address&emitter=$tokenContractAddress&logs=true", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -340,22 +293,17 @@ abstract class EthereumAPI { final List txns = []; for (final map in list!) { - final txn = - EthTokenTxDto.fromMap(Map.from(map as Map)); + final txn = EthTokenTxDto.fromMap( + Map.from(map as Map), + ); txns.add(txn); } - return EthereumResponse( - txns, - null, - ); + return EthereumResponse(txns, null); } else { // nice that the api returns an empty body instead of being // consistent and returning a json object with no transactions - return EthereumResponse( - [], - null, - ); + return EthereumResponse([], null); } } else { throw EthApiException( @@ -364,28 +312,19 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getTokenTransactions()", - error: e, - ); + Logging.instance.e("getTokenTransactions()", error: e); Logging.instance.d( "getTokenTransactions($address, $tokenContractAddress)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } -// ONLY FETCHES WALLET TOKENS WITH A NON ZERO BALANCE + // ONLY FETCHES WALLET TOKENS WITH A NON ZERO BALANCE // static Future>> getWalletTokens({ // required String address, // }) async { @@ -468,9 +407,10 @@ abstract class EthereumAPI { ); final response = await client.get( url: uri, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -495,20 +435,10 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getWalletTokenBalance()", - error: e, - stackTrace: s, - ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + Logging.instance.e("getWalletTokenBalance()", error: e, stackTrace: s); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -516,14 +446,13 @@ abstract class EthereumAPI { required String address, }) async { try { - final uri = Uri.parse( - "$stackBaseServer/state?addrs=$address&parts=all", - ); + final uri = Uri.parse("$stackBaseServer/state?addrs=$address&parts=all"); final response = await client.get( url: uri, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -533,10 +462,7 @@ abstract class EthereumAPI { final nonce = map["nonce"] as int; - return EthereumResponse( - nonce, - null, - ); + return EthereumResponse(nonce, null); } else { throw EthApiException(json["message"] as String); } @@ -547,32 +473,21 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getAddressNonce()", - error: e, - stackTrace: s, - ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + Logging.instance.e("getAddressNonce()", error: e, stackTrace: s); + return EthereumResponse(null, EthApiException(e.toString())); } } static Future> getGasOracle() async { try { final response = await client.get( - url: Uri.parse( - "$stackBaseServer/gas-prices", - ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + url: Uri.parse("$stackBaseServer/gas-prices"), + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -604,20 +519,10 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { - Logging.instance.e( - "getGasOracle()", - error: e, - stackTrace: s, - ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + Logging.instance.e("getGasOracle()", error: e, stackTrace: s); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -642,9 +547,10 @@ abstract class EthereumAPI { url: Uri.parse( "$stackBaseServer/names?terms=$contractAddress&autoname=$contractAddress&all", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); } @@ -658,9 +564,10 @@ abstract class EthereumAPI { // "$stackBaseServer/tokens?addrs=$contractAddress&parts=all", "$stackBaseServer/names?terms=$contractAddress&all", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { @@ -713,10 +620,7 @@ abstract class EthereumAPI { ); } - return EthereumResponse( - token, - null, - ); + return EthereumResponse(token, null); } else { throw EthApiException(response.body); } @@ -727,20 +631,14 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { Logging.instance.e( "getTokenByContractAddress()", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -753,18 +651,16 @@ abstract class EthereumAPI { url: Uri.parse( "$stackBaseServer/abis?addrs=$contractAddress&verbose=true", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { final json = jsonDecode(response.body)["data"] as List; - return EthereumResponse( - jsonEncode(json), - null, - ); + return EthereumResponse(jsonEncode(json), null); } else { throw EthApiException( "getTokenAbi($name, $contractAddress) failed with status code: " @@ -772,20 +668,14 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { Logging.instance.e( "getTokenAbi($name, $contractAddress)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } @@ -798,19 +688,17 @@ abstract class EthereumAPI { url: Uri.parse( "$stackBaseServer/state?addrs=$contractAddress&parts=proxy", ), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code == 200) { final json = jsonDecode(response.body); final list = json["data"] as List; final map = Map.from(list.first as Map); - return EthereumResponse( - map["proxy"] as String, - null, - ); + return EthereumResponse(map["proxy"] as String, null); } else { throw EthApiException( "getProxyTokenImplementationAddress($contractAddress) failed with" @@ -818,20 +706,14 @@ abstract class EthereumAPI { ); } } on EthApiException catch (e) { - return EthereumResponse( - null, - e, - ); + return EthereumResponse(null, e); } catch (e, s) { Logging.instance.e( "getProxyTokenImplementationAddress($contractAddress)", error: e, stackTrace: s, ); - return EthereumResponse( - null, - EthApiException(e.toString()), - ); + return EthereumResponse(null, EthApiException(e.toString())); } } } From 0b4eafb3c467239fb88b22d2cd42083c59201c14 Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 5 Apr 2025 10:45:05 -0600 Subject: [PATCH 012/206] refactor eth transaction nonce fetching --- lib/dto/ethereum/eth_tx_dto.dart | 77 ++++---- lib/dto/ethereum/pending_eth_tx_dto.dart | 160 ---------------- lib/services/ethereum/ethereum_api.dart | 117 ------------ lib/wallets/wallet/impl/ethereum_wallet.dart | 190 ++++++++++--------- 4 files changed, 140 insertions(+), 404 deletions(-) delete mode 100644 lib/dto/ethereum/pending_eth_tx_dto.dart diff --git a/lib/dto/ethereum/eth_tx_dto.dart b/lib/dto/ethereum/eth_tx_dto.dart index 10a46d740..0801d7050 100644 --- a/lib/dto/ethereum/eth_tx_dto.dart +++ b/lib/dto/ethereum/eth_tx_dto.dart @@ -31,26 +31,28 @@ class EthTxDTO { required this.hasToken, required this.gasCost, required this.gasUsed, + required this.nonce, }); factory EthTxDTO.fromMap(Map map) => EthTxDTO( - hash: map['hash'] as String, - blockHash: map['blockHash'] as String, - blockNumber: map['blockNumber'] as int, - transactionIndex: map['transactionIndex'] as int, - timestamp: map['timestamp'] as int, - from: map['from'] as String, - to: map['to'] as String, - value: _amountFromJsonNum(map['value'])!, - gas: _amountFromJsonNum(map['gas'])!, - gasPrice: _amountFromJsonNum(map['gasPrice'])!, - maxFeePerGas: _amountFromJsonNum(map['maxFeePerGas']), - maxPriorityFeePerGas: _amountFromJsonNum(map['maxPriorityFeePerGas']), - isError: map['isError'] as bool? ?? false, - hasToken: map['hasToken'] as bool? ?? false, - gasCost: _amountFromJsonNum(map['gasCost'])!, - gasUsed: _amountFromJsonNum(map['gasUsed'])!, - ); + hash: map['hash'] as String, + blockHash: map['blockHash'] as String, + blockNumber: map['blockNumber'] as int, + transactionIndex: map['transactionIndex'] as int, + timestamp: map['timestamp'] as int, + from: map['from'] as String, + to: map['to'] as String, + value: _amountFromJsonNum(map['value'])!, + gas: _amountFromJsonNum(map['gas'])!, + gasPrice: _amountFromJsonNum(map['gasPrice'])!, + maxFeePerGas: _amountFromJsonNum(map['maxFeePerGas']), + maxPriorityFeePerGas: _amountFromJsonNum(map['maxPriorityFeePerGas']), + isError: map['isError'] as bool? ?? false, + hasToken: map['hasToken'] as bool? ?? false, + gasCost: _amountFromJsonNum(map['gasCost'])!, + gasUsed: _amountFromJsonNum(map['gasUsed'])!, + nonce: map['nonce'] as int?, + ); final String hash; final String blockHash; @@ -68,6 +70,7 @@ class EthTxDTO { final bool hasToken; final Amount gasCost; final Amount gasUsed; + final int? nonce; static Amount? _amountFromJsonNum(dynamic json) { if (json == null) { @@ -97,25 +100,26 @@ class EthTxDTO { String? compressedTx, Amount? gasCost, Amount? gasUsed, - }) => - EthTxDTO( - hash: hash ?? this.hash, - blockHash: blockHash ?? this.blockHash, - blockNumber: blockNumber ?? this.blockNumber, - transactionIndex: transactionIndex ?? this.transactionIndex, - timestamp: timestamp ?? this.timestamp, - from: from ?? this.from, - to: to ?? this.to, - value: value ?? this.value, - gas: gas ?? this.gas, - gasPrice: gasPrice ?? this.gasPrice, - maxFeePerGas: maxFeePerGas ?? this.maxFeePerGas, - maxPriorityFeePerGas: maxPriorityFeePerGas ?? this.maxPriorityFeePerGas, - isError: isError ?? this.isError, - hasToken: hasToken ?? this.hasToken, - gasCost: gasCost ?? this.gasCost, - gasUsed: gasUsed ?? this.gasUsed, - ); + int? nonce, + }) => EthTxDTO( + hash: hash ?? this.hash, + blockHash: blockHash ?? this.blockHash, + blockNumber: blockNumber ?? this.blockNumber, + transactionIndex: transactionIndex ?? this.transactionIndex, + timestamp: timestamp ?? this.timestamp, + from: from ?? this.from, + to: to ?? this.to, + value: value ?? this.value, + gas: gas ?? this.gas, + gasPrice: gasPrice ?? this.gasPrice, + maxFeePerGas: maxFeePerGas ?? this.maxFeePerGas, + maxPriorityFeePerGas: maxPriorityFeePerGas ?? this.maxPriorityFeePerGas, + isError: isError ?? this.isError, + hasToken: hasToken ?? this.hasToken, + gasCost: gasCost ?? this.gasCost, + gasUsed: gasUsed ?? this.gasUsed, + nonce: nonce ?? this.nonce, + ); Map toMap() { final map = {}; @@ -135,6 +139,7 @@ class EthTxDTO { map['hasToken'] = hasToken; map['gasCost'] = gasCost.toString(); map['gasUsed'] = gasUsed.toString(); + map['nonce'] = nonce; return map; } diff --git a/lib/dto/ethereum/pending_eth_tx_dto.dart b/lib/dto/ethereum/pending_eth_tx_dto.dart deleted file mode 100644 index a19a95f61..000000000 --- a/lib/dto/ethereum/pending_eth_tx_dto.dart +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -/// blockHash : null -/// blockNumber : null -/// from : "0x..." -/// gas : "0x7e562" -/// maxPriorityFeePerGas : "0x444380" -/// maxFeePerGas : "0x342570c00" -/// hash : "0x...da64e4" -/// input : "....." -/// nonce : "0x70" -/// to : "0x00....." -/// transactionIndex : null -/// value : "0x0" -/// type : "0x2" -/// accessList : [] -/// chainId : "0x1" -/// v : "0x0" -/// r : "0xd..." -/// s : "0x17d...6e6" - -class PendingEthTxDto { - PendingEthTxDto({ - required this.blockHash, - required this.blockNumber, - required this.from, - required this.gas, - required this.maxPriorityFeePerGas, - required this.maxFeePerGas, - required this.hash, - required this.input, - required this.nonce, - required this.to, - required this.transactionIndex, - required this.value, - required this.type, - required this.accessList, - required this.chainId, - required this.v, - required this.r, - required this.s, - }); - - factory PendingEthTxDto.fromMap(Map map) => PendingEthTxDto( - blockHash: map['blockHash'] as String?, - blockNumber: map['blockNumber'] as int?, - from: map['from'] as String, - gas: map['gas'] as String, - maxPriorityFeePerGas: map['maxPriorityFeePerGas'] as String, - maxFeePerGas: map['maxFeePerGas'] as String, - hash: map['hash'] as String, - input: map['input'] as String, - nonce: map['nonce'] as String, - to: map['to'] as String, - transactionIndex: map['transactionIndex'] as int?, - value: map['value'] as String, - type: map['type'] as String, - accessList: map['accessList'] as List? ?? [], - chainId: map['chainId'] as String, - v: map['v'] as String, - r: map['r'] as String, - s: map['s'] as String, - ); - - final String? blockHash; - final int? blockNumber; - final String from; - final String gas; - final String maxPriorityFeePerGas; - final String maxFeePerGas; - final String hash; - final String input; - final String nonce; - final String to; - final int? transactionIndex; - final String value; - final String type; - final List accessList; - final String chainId; - final String v; - final String r; - final String s; - - PendingEthTxDto copyWith({ - String? blockHash, - int? blockNumber, - String? from, - String? gas, - String? maxPriorityFeePerGas, - String? maxFeePerGas, - String? hash, - String? input, - String? nonce, - String? to, - int? transactionIndex, - String? value, - String? type, - List? accessList, - String? chainId, - String? v, - String? r, - String? s, - }) => - PendingEthTxDto( - blockHash: blockHash ?? this.blockHash, - blockNumber: blockNumber ?? this.blockNumber, - from: from ?? this.from, - gas: gas ?? this.gas, - maxPriorityFeePerGas: maxPriorityFeePerGas ?? this.maxPriorityFeePerGas, - maxFeePerGas: maxFeePerGas ?? this.maxFeePerGas, - hash: hash ?? this.hash, - input: input ?? this.input, - nonce: nonce ?? this.nonce, - to: to ?? this.to, - transactionIndex: transactionIndex ?? this.transactionIndex, - value: value ?? this.value, - type: type ?? this.type, - accessList: accessList ?? this.accessList, - chainId: chainId ?? this.chainId, - v: v ?? this.v, - r: r ?? this.r, - s: s ?? this.s, - ); - - Map toMap() { - final map = {}; - map['blockHash'] = blockHash; - map['blockNumber'] = blockNumber; - map['from'] = from; - map['gas'] = gas; - map['maxPriorityFeePerGas'] = maxPriorityFeePerGas; - map['maxFeePerGas'] = maxFeePerGas; - map['hash'] = hash; - map['input'] = input; - map['nonce'] = nonce; - map['to'] = to; - map['transactionIndex'] = transactionIndex; - map['value'] = value; - map['type'] = type; - map['accessList'] = accessList; - map['chainId'] = chainId; - map['v'] = v; - map['r'] = r; - map['s'] = s; - return map; - } - - @override - String toString() { - return toMap().toString(); - } -} diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 3d726247e..badb3f96d 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -10,18 +10,14 @@ import 'dart:convert'; -import 'package:tuple/tuple.dart'; - import '../../dto/ethereum/eth_token_tx_dto.dart'; import '../../dto/ethereum/eth_token_tx_extra_dto.dart'; import '../../dto/ethereum/eth_tx_dto.dart'; -import '../../dto/ethereum/pending_eth_tx_dto.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../models/paymint/fee_object_model.dart'; import '../../networking/http.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/eth_commons.dart'; -import '../../utilities/extensions/extensions.dart'; import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; @@ -106,119 +102,6 @@ abstract class EthereumAPI { } } - static Future> getEthTransactionByHash( - String txid, - ) async { - try { - final response = await client.post( - url: Uri.parse("$stackBaseServer/v1/mainnet"), - headers: {'Content-Type': 'application/json'}, - body: json.encode({ - "jsonrpc": "2.0", - "method": "eth_getTransactionByHash", - "params": [txid], - "id": DateTime.now().millisecondsSinceEpoch, - }), - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - if (response.code == 200) { - if (response.body.isNotEmpty) { - try { - final json = jsonDecode(response.body) as Map; - final result = json["result"] as Map; - return EthereumResponse( - PendingEthTxDto.fromMap(Map.from(result)), - null, - ); - } catch (_) { - throw EthApiException( - "getEthTransactionByHash($txid) failed with response: " - "${response.body}", - ); - } - } else { - throw EthApiException( - "getEthTransactionByHash($txid) response is empty but status code is " - "${response.code}", - ); - } - } else { - throw EthApiException( - "getEthTransactionByHash($txid) failed with status code: " - "${response.code}", - ); - } - } on EthApiException catch (e) { - return EthereumResponse(null, e); - } catch (e, s) { - Logging.instance.e("getEthTransactionByHash()", error: e); - Logging.instance.d( - "getEthTransactionByHash($txid)", - error: e, - stackTrace: s, - ); - return EthereumResponse(null, EthApiException(e.toString())); - } - } - - static Future>>> - getEthTransactionNonces(List txns) async { - try { - final response = await client.get( - url: Uri.parse( - "$stackBaseServer/transactions?transactions=${txns.map((e) => e.hash).join(" ")}&raw=true", - ), - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - if (response.code == 200) { - if (response.body.isNotEmpty) { - final json = jsonDecode(response.body) as Map; - final list = List>.from(json["data"] as List); - - final List> result = []; - - for (final dto in txns) { - final data = list.firstWhere( - (e) => e["hash"] == dto.hash, - orElse: () => {}, - ); - - final nonce = (data["nonce"] as String?)?.toBigIntFromHex.toInt(); - result.add(Tuple2(dto, nonce)); - } - return EthereumResponse(result, null); - } else { - // nice that the api returns an empty body instead of being - // consistent and returning a json object with no transactions - return EthereumResponse([], null); - } - } else { - throw EthApiException( - "getEthTransactionNonces($txns) failed with status code: " - "${response.code}", - ); - } - } on EthApiException catch (e) { - return EthereumResponse(null, e); - } catch (e, s) { - Logging.instance.e("getEthTransactionNonces()", error: e); - Logging.instance.d( - "getEthTransactionNonces($txns)", - error: e, - stackTrace: s, - ); - return EthereumResponse(null, EthApiException(e.toString())); - } - } - static Future>> getEthTokenTransactionsByTxids(List txids) async { try { diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index 71d5a7279..f10109ff9 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -7,6 +7,7 @@ import 'package:http/http.dart'; import 'package:isar/isar.dart'; import 'package:web3dart/web3dart.dart' as web3; +import '../../../dto/ethereum/eth_tx_dto.dart'; import '../../../models/balance.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; @@ -293,8 +294,8 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { if (response.value == null) { Logging.instance.w( - "Failed to refresh transactions for ${cryptoCurrency.prettyName} ${info.name} " - "$walletId: ${response.exception}", + "Failed to refresh transactions for ${cryptoCurrency.prettyName}" + " ${info.name} $walletId: ${response.exception}", ); return; } @@ -304,107 +305,114 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { return; } - final txsResponse = await EthereumAPI.getEthTransactionNonces( - response.value!, - ); - - if (txsResponse.value != null) { - final allTxs = txsResponse.value!; - final List txns = []; - for (final tuple in allTxs) { - final element = tuple.item1; - - if (element.hasToken && !element.isError) { - continue; + web3.Web3Client? client; + final List allTxs = []; + for (final dto in response.value!) { + if (dto.nonce == null) { + client ??= getEthClient(); + final txInfo = await client.getTransactionByHash(dto.hash); + if (txInfo == null) { + // Something strange is happening + Logging.instance.w( + "Could not find transaction via RPC that was found use TrueBlocks " + "API.\nOffending tx: $dto", + ); + } else { + final updated = dto.copyWith(nonce: txInfo.nonce); + allTxs.add(updated); } + } else { + allTxs.add(dto); + } + } - //Calculate fees (GasLimit * gasPrice) - // int txFee = element.gasPrice * element.gasUsed; - final Amount txFee = element.gasCost; - final transactionAmount = element.value; - final addressFrom = checksumEthereumAddress(element.from); - final addressTo = checksumEthereumAddress(element.to); - - bool isIncoming; - bool txFailed = false; - if (addressFrom == thisAddress) { - if (element.isError) { - txFailed = true; - } - isIncoming = false; - } else if (addressTo == thisAddress) { - isIncoming = true; - } else { - continue; + final List txns = []; + for (final element in allTxs) { + if (element.hasToken && !element.isError) { + continue; + } + + //Calculate fees (GasLimit * gasPrice) + // int txFee = element.gasPrice * element.gasUsed; + final Amount txFee = element.gasCost; + final transactionAmount = element.value; + final addressFrom = checksumEthereumAddress(element.from); + final addressTo = checksumEthereumAddress(element.to); + + bool isIncoming; + bool txFailed = false; + if (addressFrom == thisAddress) { + if (element.isError) { + txFailed = true; } + isIncoming = false; + } else if (addressTo == thisAddress) { + isIncoming = true; + } else { + continue; + } - // hack eth tx data into inputs and outputs - final List outputs = []; - final List inputs = []; + // hack eth tx data into inputs and outputs + final List outputs = []; + final List inputs = []; - final OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( - scriptPubKeyHex: "00", - valueStringSats: transactionAmount.raw.toString(), - addresses: [addressTo], - walletOwns: addressTo == thisAddress, - ); - final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( - scriptSigHex: null, - scriptSigAsm: null, - sequence: null, - outpoint: null, - addresses: [addressFrom], - valueStringSats: transactionAmount.raw.toString(), - witness: null, - innerRedeemScriptAsm: null, - coinbase: null, - walletOwns: addressFrom == thisAddress, - ); + final OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( + scriptPubKeyHex: "00", + valueStringSats: transactionAmount.raw.toString(), + addresses: [addressTo], + walletOwns: addressTo == thisAddress, + ); + final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: null, + scriptSigAsm: null, + sequence: null, + outpoint: null, + addresses: [addressFrom], + valueStringSats: transactionAmount.raw.toString(), + witness: null, + innerRedeemScriptAsm: null, + coinbase: null, + walletOwns: addressFrom == thisAddress, + ); - final TransactionType txType; - if (isIncoming) { - if (addressFrom == addressTo) { - txType = TransactionType.sentToSelf; - } else { - txType = TransactionType.incoming; - } + final TransactionType txType; + if (isIncoming) { + if (addressFrom == addressTo) { + txType = TransactionType.sentToSelf; } else { - txType = TransactionType.outgoing; + txType = TransactionType.incoming; } + } else { + txType = TransactionType.outgoing; + } - outputs.add(output); - inputs.add(input); - - final otherData = { - "nonce": tuple.item2, - "isCancelled": txFailed, - "overrideFee": txFee.toJsonString(), - }; - - final txn = TransactionV2( - walletId: walletId, - blockHash: element.blockHash, - hash: element.hash, - txid: element.hash, - timestamp: element.timestamp, - height: element.blockNumber, - inputs: List.unmodifiable(inputs), - outputs: List.unmodifiable(outputs), - version: -1, - type: txType, - subType: TransactionSubType.none, - otherData: jsonEncode(otherData), - ); + outputs.add(output); + inputs.add(input); - txns.add(txn); - } - await mainDB.updateOrPutTransactionV2s(txns); - } else { - Logging.instance.w( - "Failed to refresh transactions with nonces for ${cryptoCurrency.prettyName} " - "${info.name} $walletId: ${txsResponse.exception}", + final otherData = { + "nonce": element.nonce, + "isCancelled": txFailed, + "overrideFee": txFee.toJsonString(), + }; + + final txn = TransactionV2( + walletId: walletId, + blockHash: element.blockHash, + hash: element.hash, + txid: element.hash, + timestamp: element.timestamp, + height: element.blockNumber, + inputs: List.unmodifiable(inputs), + outputs: List.unmodifiable(outputs), + version: -1, + type: txType, + subType: TransactionSubType.none, + otherData: jsonEncode(otherData), ); + + txns.add(txn); } + await mainDB.updateOrPutTransactionV2s(txns); } @override From 9a67e1d0d24c40e7a272d202f0f52f95abe95d95 Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 5 Apr 2025 11:15:40 -0600 Subject: [PATCH 013/206] refactor eth token transaction fetch and update --- lib/dto/ethereum/eth_token_tx_dto.dart | 126 +++++++------- lib/dto/ethereum/eth_token_tx_extra_dto.dart | 131 -------------- lib/services/ethereum/ethereum_api.dart | 164 ------------------ .../impl/sub_wallets/eth_token_wallet.dart | 81 ++++----- 4 files changed, 104 insertions(+), 398 deletions(-) delete mode 100644 lib/dto/ethereum/eth_token_tx_extra_dto.dart diff --git a/lib/dto/ethereum/eth_token_tx_dto.dart b/lib/dto/ethereum/eth_token_tx_dto.dart index 51a9a7449..0a63c6106 100644 --- a/lib/dto/ethereum/eth_token_tx_dto.dart +++ b/lib/dto/ethereum/eth_token_tx_dto.dart @@ -28,23 +28,32 @@ class EthTokenTxDto { required this.articulatedLog, required this.transactionHash, required this.transactionIndex, + required this.blockHash, + required this.timestamp, + required this.nonce, + required this.gasUsed, + required this.gasPrice, }); EthTokenTxDto.fromMap(Map map) - : address = map['address'] as String, - blockNumber = map['blockNumber'] as int, - logIndex = map['logIndex'] as int, - topics = List.from(map['topics'] as List), - data = map['data'] as String, - articulatedLog = map['articulatedLog'] == null - ? null - : ArticulatedLog.fromMap( - Map.from( - map['articulatedLog'] as Map, - ), + : address = map['address'] as String, + blockNumber = map['blockNumber'] as int, + logIndex = map['logIndex'] as int, + topics = List.from(map['topics'] as List), + data = map['data'] as String, + articulatedLog = + map['articulatedLog'] == null + ? null + : ArticulatedLog.fromMap( + Map.from(map['articulatedLog'] as Map), ), - transactionHash = map['transactionHash'] as String, - transactionIndex = map['transactionIndex'] as int; + transactionHash = map['transactionHash'] as String, + transactionIndex = map['transactionIndex'] as int, + blockHash = map['blockHash'] as String?, + timestamp = map['timestamp'] as int, + nonce = map['nonce'] as int?, + gasUsed = map['gasUsed'] as int?, + gasPrice = BigInt.tryParse(map['gasPrice'].toString()); final String address; final int blockNumber; @@ -54,6 +63,11 @@ class EthTokenTxDto { final ArticulatedLog? articulatedLog; final String transactionHash; final int transactionIndex; + final String? blockHash; + final int timestamp; + final int? nonce; + final int? gasUsed; + final BigInt? gasPrice; EthTokenTxDto copyWith({ String? address, @@ -65,17 +79,26 @@ class EthTokenTxDto { String? compressedLog, String? transactionHash, int? transactionIndex, - }) => - EthTokenTxDto( - address: address ?? this.address, - blockNumber: blockNumber ?? this.blockNumber, - logIndex: logIndex ?? this.logIndex, - topics: topics ?? this.topics, - data: data ?? this.data, - articulatedLog: articulatedLog ?? this.articulatedLog, - transactionHash: transactionHash ?? this.transactionHash, - transactionIndex: transactionIndex ?? this.transactionIndex, - ); + String? blockHash, + int? timestamp, + int? nonce, + int? gasUsed, + BigInt? gasPrice, + }) => EthTokenTxDto( + address: address ?? this.address, + blockNumber: blockNumber ?? this.blockNumber, + logIndex: logIndex ?? this.logIndex, + topics: topics ?? this.topics, + data: data ?? this.data, + articulatedLog: articulatedLog ?? this.articulatedLog, + transactionHash: transactionHash ?? this.transactionHash, + transactionIndex: transactionIndex ?? this.transactionIndex, + blockHash: blockHash ?? this.blockHash, + timestamp: timestamp ?? this.timestamp, + nonce: nonce ?? this.nonce, + gasUsed: gasUsed ?? this.gasUsed, + gasPrice: gasPrice ?? this.gasPrice, + ); Map toMap() { final map = {}; @@ -87,6 +110,11 @@ class EthTokenTxDto { map['articulatedLog'] = articulatedLog?.toMap(); map['transactionHash'] = transactionHash; map['transactionIndex'] = transactionIndex; + map['blockHash'] = blockHash; + map['timestamp'] = timestamp; + map['nonce'] = nonce; + map['gasPrice'] = gasPrice; + map['gasUsed'] = gasUsed; return map; } @@ -100,30 +128,17 @@ class EthTokenTxDto { /// inputs : {"_amount":"3291036540000000000","_from":"0x3a5cc8689d1b0cef2c317bc5c0ad6ce88b27d597","_to":"0xc5e81fc2401b8104966637d5334cbce92f01dbf7"} class ArticulatedLog { - ArticulatedLog({ - required this.name, - required this.inputs, - }); + ArticulatedLog({required this.name, required this.inputs}); ArticulatedLog.fromMap(Map map) - : name = map['name'] as String, - inputs = Inputs.fromMap( - Map.from( - map['inputs'] as Map, - ), - ); + : name = map['name'] as String, + inputs = Inputs.fromMap(Map.from(map['inputs'] as Map)); final String name; final Inputs inputs; - ArticulatedLog copyWith({ - String? name, - Inputs? inputs, - }) => - ArticulatedLog( - name: name ?? this.name, - inputs: inputs ?? this.inputs, - ); + ArticulatedLog copyWith({String? name, Inputs? inputs}) => + ArticulatedLog(name: name ?? this.name, inputs: inputs ?? this.inputs); Map toMap() { final map = {}; @@ -138,31 +153,22 @@ class ArticulatedLog { /// _to : "0xc5e81fc2401b8104966637d5334cbce92f01dbf7" /// class Inputs { - Inputs({ - required this.amount, - required this.from, - required this.to, - }); + Inputs({required this.amount, required this.from, required this.to}); Inputs.fromMap(Map map) - : amount = map['_amount'] as String, - from = map['_from'] as String, - to = map['_to'] as String; + : amount = map['_amount'] as String, + from = map['_from'] as String, + to = map['_to'] as String; final String amount; final String from; final String to; - Inputs copyWith({ - String? amount, - String? from, - String? to, - }) => - Inputs( - amount: amount ?? this.amount, - from: from ?? this.from, - to: to ?? this.to, - ); + Inputs copyWith({String? amount, String? from, String? to}) => Inputs( + amount: amount ?? this.amount, + from: from ?? this.from, + to: to ?? this.to, + ); Map toMap() { final map = {}; diff --git a/lib/dto/ethereum/eth_token_tx_extra_dto.dart b/lib/dto/ethereum/eth_token_tx_extra_dto.dart deleted file mode 100644 index 401ea7122..000000000 --- a/lib/dto/ethereum/eth_token_tx_extra_dto.dart +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'dart:convert'; - -import '../../utilities/amount/amount.dart'; -import '../../wallets/crypto_currency/crypto_currency.dart'; - -class EthTokenTxExtraDTO { - EthTokenTxExtraDTO({ - required this.blockHash, - required this.blockNumber, - required this.from, - required this.gas, - required this.gasCost, - required this.gasPrice, - required this.gasUsed, - required this.hash, - required this.input, - required this.nonce, - required this.timestamp, - required this.to, - required this.transactionIndex, - required this.value, - }); - - factory EthTokenTxExtraDTO.fromMap(Map map) => - EthTokenTxExtraDTO( - hash: map['hash'] as String, - blockHash: map['blockHash'] as String, - blockNumber: map['blockNumber'] as int, - transactionIndex: map['transactionIndex'] as int, - timestamp: map['timestamp'] as int, - from: map['from'] as String, - to: map['to'] as String, - value: Amount( - rawValue: BigInt.parse(map['value'] as String), - fractionDigits: Ethereum(CryptoCurrencyNetwork.main).fractionDigits, - ), - gas: _amountFromJsonNum(map['gas']), - gasPrice: _amountFromJsonNum(map['gasPrice']), - nonce: map['nonce'] as int?, - input: map['input'] as String, - gasCost: _amountFromJsonNum(map['gasCost']), - gasUsed: _amountFromJsonNum(map['gasUsed']), - ); - - final String hash; - final String blockHash; - final int blockNumber; - final int transactionIndex; - final int timestamp; - final String from; - final String to; - final Amount value; - final Amount gas; - final Amount gasPrice; - final String input; - final int? nonce; - final Amount gasCost; - final Amount gasUsed; - - static Amount _amountFromJsonNum(dynamic json) { - return Amount( - rawValue: BigInt.from(json as num), - fractionDigits: Ethereum(CryptoCurrencyNetwork.main).fractionDigits, - ); - } - - EthTokenTxExtraDTO copyWith({ - String? hash, - String? blockHash, - int? blockNumber, - int? transactionIndex, - int? timestamp, - String? from, - String? to, - Amount? value, - Amount? gas, - Amount? gasPrice, - int? nonce, - String? input, - Amount? gasCost, - Amount? gasUsed, - }) => - EthTokenTxExtraDTO( - hash: hash ?? this.hash, - blockHash: blockHash ?? this.blockHash, - blockNumber: blockNumber ?? this.blockNumber, - transactionIndex: transactionIndex ?? this.transactionIndex, - timestamp: timestamp ?? this.timestamp, - from: from ?? this.from, - to: to ?? this.to, - value: value ?? this.value, - gas: gas ?? this.gas, - gasPrice: gasPrice ?? this.gasPrice, - nonce: nonce ?? this.nonce, - input: input ?? this.input, - gasCost: gasCost ?? this.gasCost, - gasUsed: gasUsed ?? this.gasUsed, - ); - - Map toMap() { - final map = {}; - map['hash'] = hash; - map['blockHash'] = blockHash; - map['blockNumber'] = blockNumber; - map['transactionIndex'] = transactionIndex; - map['timestamp'] = timestamp; - map['from'] = from; - map['to'] = to; - map['value'] = value.toJsonString(); - map['gas'] = gas.toJsonString(); - map['gasPrice'] = gasPrice.toJsonString(); - map['input'] = input; - map['nonce'] = nonce; - map['gasCost'] = gasCost.toJsonString(); - map['gasUsed'] = gasUsed.toJsonString(); - return map; - } - - @override - String toString() => jsonEncode(toMap()); -} diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index badb3f96d..8619e3f01 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -11,7 +11,6 @@ import 'dart:convert'; import '../../dto/ethereum/eth_token_tx_dto.dart'; -import '../../dto/ethereum/eth_token_tx_extra_dto.dart'; import '../../dto/ethereum/eth_tx_dto.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../models/paymint/fee_object_model.dart'; @@ -102,58 +101,6 @@ abstract class EthereumAPI { } } - static Future>> - getEthTokenTransactionsByTxids(List txids) async { - try { - final response = await client.get( - url: Uri.parse( - "$stackBaseServer/transactions?transactions=${txids.join(" ")}", - ), - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - if (response.code == 200) { - if (response.body.isNotEmpty) { - final json = jsonDecode(response.body) as Map; - final list = json["data"] as List?; - - final List txns = []; - for (final map in list!) { - final txn = EthTokenTxExtraDTO.fromMap( - Map.from(map as Map), - ); - - txns.add(txn); - } - return EthereumResponse(txns, null); - } else { - throw EthApiException( - "getEthTokenTransactionsByTxids($txids) response is empty but status code is " - "${response.code}", - ); - } - } else { - throw EthApiException( - "getEthTokenTransactionsByTxids($txids) failed with status code: " - "${response.code}", - ); - } - } on EthApiException catch (e) { - return EthereumResponse(null, e); - } catch (e, s) { - Logging.instance.e("getEthTokenTransactionsByTxids()", error: e); - Logging.instance.d( - "getEthTokenTransactionsByTxids($txids)", - error: e, - stackTrace: s, - ); - return EthereumResponse(null, EthApiException(e.toString())); - } - } - static Future>> getTokenTransactions({ required String address, required String tokenContractAddress, @@ -207,79 +154,6 @@ abstract class EthereumAPI { } } - // ONLY FETCHES WALLET TOKENS WITH A NON ZERO BALANCE - // static Future>> getWalletTokens({ - // required String address, - // }) async { - // try { - // final uri = Uri.parse( - // "$blockExplorer?module=account&action=tokenlist&address=$address", - // ); - // final response = await get(uri); - // - // if (response.statusCode == 200) { - // final json = jsonDecode(response.body); - // if (json["message"] == "OK") { - // final result = - // List>.from(json["result"] as List); - // final List tokens = []; - // for (final map in result) { - // if (map["type"] == "ERC-20") { - // tokens.add( - // Erc20Token( - // balance: int.parse(map["balance"] as String), - // contractAddress: map["contractAddress"] as String, - // decimals: int.parse(map["decimals"] as String), - // name: map["name"] as String, - // symbol: map["symbol"] as String, - // ), - // ); - // } else if (map["type"] == "ERC-721") { - // tokens.add( - // Erc721Token( - // balance: int.parse(map["balance"] as String), - // contractAddress: map["contractAddress"] as String, - // decimals: int.parse(map["decimals"] as String), - // name: map["name"] as String, - // symbol: map["symbol"] as String, - // ), - // ); - // } else { - // throw EthApiException( - // "Unsupported token type found: ${map["type"]}"); - // } - // } - // - // return EthereumResponse( - // tokens, - // null, - // ); - // } else { - // throw EthApiException(json["message"] as String); - // } - // } else { - // throw EthApiException( - // "getWalletTokens($address) failed with status code: " - // "${response.statusCode}", - // ); - // } - // } on EthApiException catch (e) { - // return EthereumResponse( - // null, - // e, - // ); - // } catch (e, s) { - // Logging.instance.log( - // "getWalletTokens(): $e\n$s", - // level: LogLevel.Error, - // ); - // return EthereumResponse( - // null, - // EthApiException(e.toString()), - // ); - // } - // } - static Future> getWalletTokenBalance({ required String address, required String contractAddress, @@ -325,44 +199,6 @@ abstract class EthereumAPI { } } - static Future> getAddressNonce({ - required String address, - }) async { - try { - final uri = Uri.parse("$stackBaseServer/state?addrs=$address&parts=all"); - final response = await client.get( - url: uri, - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - if (response.code == 200) { - final json = jsonDecode(response.body); - if (json["data"] is List) { - final map = json["data"].first as Map; - - final nonce = map["nonce"] as int; - - return EthereumResponse(nonce, null); - } else { - throw EthApiException(json["message"] as String); - } - } else { - throw EthApiException( - "getAddressNonce($address) failed with status code: " - "${response.code}", - ); - } - } on EthApiException catch (e) { - return EthereumResponse(null, e); - } catch (e, s) { - Logging.instance.e("getAddressNonce()", error: e, stackTrace: s); - return EthereumResponse(null, EthApiException(e.toString())); - } - } - static Future> getGasOracle() async { try { final response = await client.get( diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index 29f96438e..136efc5ca 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -5,7 +5,6 @@ import 'package:isar/isar.dart'; import 'package:web3dart/web3dart.dart' as web3dart; import '../../../../dto/ethereum/eth_token_tx_dto.dart'; -import '../../../../dto/ethereum/eth_token_tx_extra_dto.dart'; import '../../../../models/balance.dart'; import '../../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../../models/isar/models/blockchain_data/v2/input_v2.dart'; @@ -395,45 +394,38 @@ class EthTokenWallet extends Wallet { return; } - final response2 = await EthereumAPI.getEthTokenTransactionsByTxids( - response.value!.map((e) => e.transactionHash).toSet().toList(), - ); - - if (response2.value == null) { - throw response2.exception ?? - Exception("Failed to fetch token transactions"); - } - final List<({EthTokenTxDto tx, EthTokenTxExtraDTO extra})> data = []; - for (final tokenDto in response.value!) { - try { - final txExtra = response2.value!.firstWhere( - (e) => e.hash == tokenDto.transactionHash, - ); - data.add((tx: tokenDto, extra: txExtra)); - } catch (e, s) { - // Server indexing failed for some reason. Instead of hard crashing or - // showing no transactions we just skip it here. Not ideal but better - // than nothing showing up - Logging.instance.e( - "Server error: Transaction hash not found.", - error: e, - stackTrace: s, - ); - Logging.instance.d( - "Server error: Transaction ${tokenDto.transactionHash} not found.", - error: e, - stackTrace: s, - ); + web3dart.Web3Client? client; + final List allTxs = []; + for (final dto in response.value!) { + if (dto.nonce == null) { + client ??= ethWallet.getEthClient(); + final txInfo = await client.getTransactionByHash(dto.transactionHash); + if (txInfo == null) { + // Something strange is happening + Logging.instance.w( + "Could not find token transaction via RPC that was found use " + "TrueBlocks API.\nOffending tx: $dto", + ); + } else { + final updated = dto.copyWith( + nonce: txInfo.nonce, + gasPrice: txInfo.gasPrice.getInWei, + gasUsed: txInfo.gas, + ); + allTxs.add(updated); + } + } else { + allTxs.add(dto); } } final List txns = []; - for (final tuple in data) { + for (final tx in allTxs) { // ignore all non Transfer events (for now) - if (tuple.tx.topics[0] == kTransferEventSignature) { + if (tx.topics[0] == kTransferEventSignature) { final amount = Amount( - rawValue: tuple.tx.data.toBigIntFromHex, + rawValue: tx.data.toBigIntFromHex, fractionDigits: tokenContract.decimals, ); @@ -442,9 +434,12 @@ class EthTokenWallet extends Wallet { continue; } - final Amount txFee = tuple.extra.gasUsed * tuple.extra.gasPrice; - final addressFrom = _addressFromTopic(tuple.tx.topics[1]); - final addressTo = _addressFromTopic(tuple.tx.topics[2]); + final txFee = Amount( + rawValue: BigInt.from(tx.gasUsed!) * tx.gasPrice!, + fractionDigits: cryptoCurrency.fractionDigits, + ); + final addressFrom = _addressFromTopic(tx.topics[1]); + final addressTo = _addressFromTopic(tx.topics[2]); final TransactionType txType; if (addressTo == addressString) { @@ -466,10 +461,10 @@ class EthTokenWallet extends Wallet { } final otherData = { - "nonce": tuple.extra.nonce, + "nonce": tx.nonce, "isCancelled": false, "overrideFee": txFee.toJsonString(), - "contractAddress": tuple.tx.address, + "contractAddress": tx.address, }; // hack eth tx data into inputs and outputs @@ -500,11 +495,11 @@ class EthTokenWallet extends Wallet { final txn = TransactionV2( walletId: walletId, - blockHash: tuple.extra.blockHash, - hash: tuple.tx.transactionHash, - txid: tuple.tx.transactionHash, - timestamp: tuple.extra.timestamp, - height: tuple.tx.blockNumber, + blockHash: tx.blockHash, + hash: tx.transactionHash, + txid: tx.transactionHash, + timestamp: tx.timestamp, + height: tx.blockNumber, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), version: -1, From b61ba0e865c1d6bcc51f07d2805bfc96fbb38b4b Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 09:58:16 -0600 Subject: [PATCH 014/206] refactor desktop send fee info/selection to its own widget --- .../wallet_view/sub_widgets/desktop_send.dart | 253 +-------------- .../sub_widgets/desktop_send_fee_form.dart | 294 ++++++++++++++++++ 2 files changed, 302 insertions(+), 245 deletions(-) create mode 100644 lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 9dc0b0f91..29faa77d7 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -10,7 +10,6 @@ import 'dart:async'; -import 'package:cs_monero/cs_monero.dart' as lib_monero; import 'package:decimal/decimal.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; @@ -39,7 +38,6 @@ import '../../../../utilities/assets.dart'; import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/clipboard_interface.dart'; import '../../../../utilities/constants.dart'; -import '../../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../../utilities/logger.dart'; import '../../../../utilities/prefs.dart'; import '../../../../utilities/text_styles.dart'; @@ -50,20 +48,15 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/models/tx_data.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; -import '../../../../wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; -import '../../../../widgets/animated_text.dart'; -import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; -import '../../../../widgets/desktop/desktop_fee_dialog.dart'; import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/qr_code_scanner_dialog.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/dialogs/firo_exchange_address_dialog.dart'; -import '../../../../widgets/fee_slider.dart'; import '../../../../widgets/icon_widgets/addressbook_icon.dart'; import '../../../../widgets/icon_widgets/clipboard_icon.dart'; import '../../../../widgets/icon_widgets/qrcode_icon.dart'; @@ -75,6 +68,7 @@ import '../../../coin_control/desktop_coin_control_use_dialog.dart'; import '../../../desktop_home_view.dart'; import 'address_book_address_chooser/address_book_address_chooser.dart'; import 'desktop_fee_dropdown.dart'; +import 'desktop_send_fee_form.dart'; class DesktopSend extends ConsumerStatefulWidget { const DesktopSend({ @@ -134,14 +128,6 @@ class _DesktopSendState extends ConsumerState { bool isCustomFee = false; int customFeeRate = 1; - (FeeRateType, String?, String?)? feeSelectionResult; - - final stringsToLoopThrough = [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ]; Future scanWebcam() async { try { @@ -196,9 +182,7 @@ class _DesktopSendState extends ConsumerState { ref.read(prefsChangeNotifierProvider).enableCoinControl; if (!(wallet is CoinControlInterface && coinControlEnabled) || - (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isEmpty)) { + (coinControlEnabled && ref.read(desktopUseUTXOs).isEmpty)) { // confirm send all if (amount == availableBalance) { final bool? shouldSendAll = await showDialog( @@ -358,8 +342,7 @@ class _DesktopSendState extends ConsumerState { feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: - (wallet is CoinControlInterface && - coinControlEnabled && + (coinControlEnabled && ref.read(desktopUseUTXOs).isNotEmpty) ? ref.read(desktopUseUTXOs) : null, @@ -374,8 +357,7 @@ class _DesktopSendState extends ConsumerState { feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: - (wallet is CoinControlInterface && - coinControlEnabled && + (coinControlEnabled && ref.read(desktopUseUTXOs).isNotEmpty) ? ref.read(desktopUseUTXOs) : null, @@ -1641,229 +1623,10 @@ class _DesktopSendState extends ConsumerState { ), if (!isPaynymSend) const SizedBox(height: 20), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) - ConditionalParent( - condition: - ref.watch(pWallets).getWallet(walletId) is ElectrumXInterface && - !(((coin is Firo) && - (ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.lelantus || - ref - .watch(publicPrivateBalanceStateProvider.state) - .state == - FiroType.spark))), - builder: - (child) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - child, - CustomTextButton( - text: "Edit", - onTap: () async { - feeSelectionResult = - await showDialog<(FeeRateType, String?, String?)?>( - context: context, - builder: - (_) => DesktopFeeDialog(walletId: walletId), - ); - - if (feeSelectionResult != null) { - if (isCustomFee && - feeSelectionResult!.$1 != FeeRateType.custom) { - isCustomFee = false; - } else if (!isCustomFee && - feeSelectionResult!.$1 == FeeRateType.custom) { - isCustomFee = true; - } - } - - setState(() {}); - }, - ), - ], - ), - child: Text( - "Transaction fee" - "${isCustomFee ? "" : " (${coin is Ethereum ? "max" : "estimated"})"}", - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveSearchIconRight, - ), - textAlign: TextAlign.left, - ), - ), - if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) - const SizedBox(height: 10), - if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) - if (!isCustomFee) - Padding( - padding: const EdgeInsets.all(10), - child: - (feeSelectionResult?.$2 == null) - ? FutureBuilder( - future: ref.watch( - pWallets.select( - (value) => value.getWallet(walletId).fees, - ), - ), - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - return DesktopFeeItem( - feeObject: snapshot.data, - feeRateType: FeeRateType.average, - walletId: walletId, - isButton: false, - feeFor: ({ - required Amount amount, - required FeeRateType feeRateType, - required int feeRate, - required CryptoCurrency coin, - }) async { - if (ref - .read(feeSheetSessionCacheProvider) - .average[amount] == - null) { - final wallet = ref - .read(pWallets) - .getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero - .TransactionPriority - .medium - .value, - ); - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - fee; - } else if ((coin is Firo) && - ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public) { - final firoWallet = wallet as FiroWallet; - - if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.lelantus) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await firoWallet - .estimateFeeForLelantus(amount); - } else if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.spark) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await firoWallet - .estimateFeeForSpark(amount); - } - } else { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await wallet - .estimateFeeFor(amount, feeRate); - } - } - return ref - .read(feeSheetSessionCacheProvider) - .average[amount]!; - }, - isSelected: true, - ); - } else { - return Row( - children: [ - AnimatedText( - stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textFieldActiveText, - ), - ), - ], - ); - } - }, - ) - : (coin is Firo) && - ref - .watch( - publicPrivateBalanceStateProvider.state, - ) - .state == - FiroType.lelantus - ? Text( - "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveText, - ), - textAlign: TextAlign.left, - ) - : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - feeSelectionResult?.$2 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, - ), - Text( - feeSelectionResult?.$3 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ), - ), - ], - ), - ), - if (isCustomFee) - Padding( - padding: const EdgeInsets.only(bottom: 12, top: 16), - child: FeeSlider( - coin: coin, - onSatVByteChanged: (rate) { - customFeeRate = rate; - }, - ), + DesktopSendFeeForm( + walletId: walletId, + onCustomFeeSliderChanged: (value) => customFeeRate = value, + onCustomFeeOptionChanged: (value) => isCustomFee = value, ), const SizedBox(height: 36), PrimaryButton( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart new file mode 100644 index 000000000..1f5b20579 --- /dev/null +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -0,0 +1,294 @@ +import 'package:cs_monero/cs_monero.dart' as lib_monero; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; +import '../../../../providers/providers.dart'; +import '../../../../providers/wallet/public_private_balance_state_provider.dart'; +import '../../../../themes/stack_colors.dart'; +import '../../../../utilities/amount/amount.dart'; +import '../../../../utilities/amount/amount_formatter.dart'; +import '../../../../utilities/enums/fee_rate_type_enum.dart'; +import '../../../../utilities/text_styles.dart'; +import '../../../../wallets/crypto_currency/crypto_currency.dart'; +import '../../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../../wallets/wallet/impl/firo_wallet.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart'; +import '../../../../widgets/animated_text.dart'; +import '../../../../widgets/conditional_parent.dart'; +import '../../../../widgets/custom_buttons/blue_text_button.dart'; +import '../../../../widgets/desktop/desktop_fee_dialog.dart'; +import '../../../../widgets/fee_slider.dart'; + +class DesktopSendFeeForm extends ConsumerStatefulWidget { + const DesktopSendFeeForm({ + super.key, + required this.walletId, + required this.onCustomFeeSliderChanged, + required this.onCustomFeeOptionChanged, + }); + + final String walletId; + final void Function(int) onCustomFeeSliderChanged; + final void Function(bool) onCustomFeeOptionChanged; + + @override + ConsumerState createState() => _DesktopSendFeeFormState(); +} + +class _DesktopSendFeeFormState extends ConsumerState { + final stringsToLoopThrough = [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ]; + + late final CryptoCurrency cryptoCurrency; + + bool isCustomFee = false; + (FeeRateType, String?, String?)? feeSelectionResult; + + @override + void initState() { + super.initState(); + cryptoCurrency = ref.read(pWalletCoin(widget.walletId)); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + ConditionalParent( + condition: + ref.watch(pWallets).getWallet(widget.walletId) + is ElectrumXInterface && + !(((cryptoCurrency is Firo) && + (ref.watch(publicPrivateBalanceStateProvider.state).state == + FiroType.lelantus || + ref + .watch(publicPrivateBalanceStateProvider.state) + .state == + FiroType.spark))), + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + child, + CustomTextButton( + text: "Edit", + onTap: () async { + feeSelectionResult = + await showDialog<(FeeRateType, String?, String?)?>( + context: context, + builder: + (_) => + DesktopFeeDialog(walletId: widget.walletId), + ); + + if (feeSelectionResult != null) { + if (isCustomFee && + feeSelectionResult!.$1 != FeeRateType.custom) { + isCustomFee = false; + } else if (!isCustomFee && + feeSelectionResult!.$1 == FeeRateType.custom) { + isCustomFee = true; + } + } + + setState(() {}); + }, + ), + ], + ), + child: Text( + "Transaction fee" + "${isCustomFee ? "" : " (${cryptoCurrency is Ethereum ? "max" : "estimated"})"}", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, + ), + textAlign: TextAlign.left, + ), + ), + const SizedBox(height: 10), + if (!isCustomFee) + Padding( + padding: const EdgeInsets.all(10), + child: + (feeSelectionResult?.$2 == null) + ? FutureBuilder( + future: ref.watch( + pWallets.select( + (value) => value.getWallet(widget.walletId).fees, + ), + ), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + return DesktopFeeItem( + feeObject: snapshot.data, + feeRateType: FeeRateType.average, + walletId: widget.walletId, + isButton: false, + feeFor: ({ + required Amount amount, + required FeeRateType feeRateType, + required int feeRate, + required CryptoCurrency coin, + }) async { + if (ref + .read(feeSheetSessionCacheProvider) + .average[amount] == + null) { + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); + + if (coin is Monero || coin is Wownero) { + final fee = await wallet.estimateFeeFor( + amount, + lib_monero.TransactionPriority.medium.value, + ); + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = + fee; + } else if ((coin is Firo) && + ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) { + final firoWallet = wallet as FiroWallet; + + if (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state == + FiroType.lelantus) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForLelantus(amount); + } else if (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state == + FiroType.spark) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForSpark(amount); + } + } else { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await wallet + .estimateFeeFor(amount, feeRate); + } + } + return ref + .read(feeSheetSessionCacheProvider) + .average[amount]!; + }, + isSelected: true, + ); + } else { + return Row( + children: [ + AnimatedText( + stringsToLoopThrough: stringsToLoopThrough, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + ), + ), + ], + ); + } + }, + ) + : (cryptoCurrency is Firo) && + ref + .watch(publicPrivateBalanceStateProvider.state) + .state == + FiroType.lelantus + ? Builder( + builder: (context) { + final lelantusFee = ref + .watch(pAmountFormatter(cryptoCurrency)) + .format( + Amount( + rawValue: BigInt.parse("3794"), + fractionDigits: cryptoCurrency.fractionDigits, + ), + indicatePrecisionLoss: false, + ); + return Text( + "~$lelantusFee", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + ), + textAlign: TextAlign.left, + ); + }, + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + feeSelectionResult?.$2 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + ), + textAlign: TextAlign.left, + ), + Text( + feeSelectionResult?.$3 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + ], + ), + ), + if (isCustomFee) + Padding( + padding: const EdgeInsets.only(bottom: 12, top: 16), + child: FeeSlider( + coin: cryptoCurrency, + onSatVByteChanged: widget.onCustomFeeSliderChanged, + ), + ), + ], + ); + } +} From 72a1be18e985a893c16c5158c4a6a65e10aacaf8 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 09:58:58 -0600 Subject: [PATCH 015/206] remove conflicting analysis rule --- analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index ea46ed3ca..cee9f40f3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -92,7 +92,7 @@ linter: constant_identifier_names: false prefer_final_locals: true prefer_final_in_for_each: true - require_trailing_commas: true +# require_trailing_commas: true # new dart format hates this # avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule From 7a153eba70a57cda1e144966d04b8310d1885f3e Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 10:51:48 -0600 Subject: [PATCH 016/206] remove old desktop fee selection dropdown, add nonce override field to eth send, and move a couple providers to their own file --- .../sub_widgets/desktop_fee_dropdown.dart | 447 ------------------ .../wallet_view/sub_widgets/desktop_send.dart | 65 ++- .../sub_widgets/desktop_send_fee_form.dart | 5 +- .../sub_widgets/desktop_token_send.dart | 20 +- .../wallet/desktop_fee_providers.dart | 23 + lib/widgets/desktop/desktop_fee_dialog.dart | 200 ++++---- 6 files changed, 199 insertions(+), 561 deletions(-) delete mode 100644 lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart create mode 100644 lib/providers/wallet/desktop_fee_providers.dart diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart deleted file mode 100644 index 6326a6474..000000000 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart +++ /dev/null @@ -1,447 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:dropdown_button2/dropdown_button2.dart'; -import 'package:flutter/material.dart'; -import 'package:cs_monero/cs_monero.dart' as lib_monero; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; - -import '../../../../models/models.dart'; -import '../../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; -import '../../../../providers/global/wallets_provider.dart'; -import '../../../../providers/ui/fee_rate_type_state_provider.dart'; -import '../../../../providers/wallet/public_private_balance_state_provider.dart'; -import '../../../../themes/stack_colors.dart'; -import '../../../../utilities/amount/amount.dart'; -import '../../../../utilities/amount/amount_formatter.dart'; -import '../../../../utilities/assets.dart'; -import '../../../../utilities/constants.dart'; -import '../../../../utilities/enums/fee_rate_type_enum.dart'; -import '../../../../utilities/text_styles.dart'; -import '../../../../wallets/crypto_currency/crypto_currency.dart'; -import '../../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; -import '../../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../../wallets/wallet/impl/firo_wallet.dart'; -import '../../../../widgets/animated_text.dart'; - -final tokenFeeSessionCacheProvider = - ChangeNotifierProvider((ref) { - return FeeSheetSessionCache(); -}); - -class DesktopFeeDropDown extends ConsumerStatefulWidget { - const DesktopFeeDropDown({ - super.key, - required this.walletId, - this.isToken = false, - }); - - final String walletId; - final bool isToken; - - @override - ConsumerState createState() => _DesktopFeeDropDownState(); -} - -class _DesktopFeeDropDownState extends ConsumerState { - late final String walletId; - - FeeObject? feeObject; - FeeRateType feeRateType = FeeRateType.average; - - final stringsToLoopThrough = [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ]; - - Future feeFor({ - required Amount amount, - required FeeRateType feeRateType, - required int feeRate, - required CryptoCurrency coin, - }) async { - switch (feeRateType) { - case FeeRateType.fast: - if (ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .fast[amount] == - null) { - if (widget.isToken == false) { - final wallet = ref.read(pWallets).getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero.TransactionPriority.high.value, - ); - ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; - } else if (coin is Firo) { - final Amount fee; - switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); - case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); - case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); - } - ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; - } else { - ref.read(feeSheetSessionCacheProvider).fast[amount] = - await wallet.estimateFeeFor(amount, feeRate); - } - } else { - final tokenWallet = ref.read(pCurrentTokenWallet)!; - final fee = await tokenWallet.estimateFeeFor(amount, feeRate); - ref.read(tokenFeeSessionCacheProvider).fast[amount] = fee; - } - } - return ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .fast[amount]!; - - case FeeRateType.average: - if (ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .average[amount] == - null) { - if (widget.isToken == false) { - final wallet = ref.read(pWallets).getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero.TransactionPriority.medium.value, - ); - ref.read(feeSheetSessionCacheProvider).average[amount] = fee; - } else if (coin is Firo) { - final Amount fee; - switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); - case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); - case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); - } - ref.read(feeSheetSessionCacheProvider).average[amount] = fee; - } else { - ref.read(feeSheetSessionCacheProvider).average[amount] = - await wallet.estimateFeeFor(amount, feeRate); - } - } else { - final tokenWallet = ref.read(pCurrentTokenWallet)!; - final fee = await tokenWallet.estimateFeeFor(amount, feeRate); - ref.read(tokenFeeSessionCacheProvider).average[amount] = fee; - } - } - return ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .average[amount]!; - - case FeeRateType.slow: - if (ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .slow[amount] == - null) { - if (widget.isToken == false) { - final wallet = ref.read(pWallets).getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero.TransactionPriority.normal.value, - ); - ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; - } else if (coin is Firo) { - final Amount fee; - switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); - case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); - case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); - } - ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; - } else { - ref.read(feeSheetSessionCacheProvider).slow[amount] = - await wallet.estimateFeeFor(amount, feeRate); - } - } else { - final tokenWallet = ref.read(pCurrentTokenWallet)!; - final fee = await tokenWallet.estimateFeeFor(amount, feeRate); - ref.read(tokenFeeSessionCacheProvider).slow[amount] = fee; - } - } - return ref - .read( - widget.isToken - ? tokenFeeSessionCacheProvider - : feeSheetSessionCacheProvider, - ) - .slow[amount]!; - default: - return Amount.zero; - } - } - - @override - void initState() { - walletId = widget.walletId; - super.initState(); - } - - String? labelSlow; - String? labelAverage; - String? labelFast; - - @override - Widget build(BuildContext context) { - debugPrint("BUILD: $runtimeType"); - - final wallet = - ref.watch(pWallets.select((value) => value.getWallet(walletId))); - - return FutureBuilder( - future: wallet.fees, - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - feeObject = snapshot.data!; - } - return DropdownButtonHideUnderline( - child: DropdownButton2( - isExpanded: true, - value: ref.watch(feeRateTypeStateProvider.state).state, - items: [ - ...FeeRateType.values.map( - (e) => DropdownMenuItem( - value: e, - child: FeeDropDownChild( - feeObject: feeObject, - feeRateType: e, - walletId: walletId, - feeFor: feeFor, - isSelected: false, - ), - ), - ), - ], - onChanged: (newRateType) { - if (newRateType is FeeRateType) { - ref.read(feeRateTypeStateProvider.state).state = newRateType; - } - }, - iconStyleData: IconStyleData( - icon: SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - height: 6, - color: Theme.of(context).extension()!.textDark3, - ), - ), - dropdownStyleData: DropdownStyleData( - offset: const Offset(0, -10), - elevation: 0, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - ), - menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - ), - ), - ); - }, - ); - } -} - -final sendAmountProvider = - StateProvider.autoDispose((_) => Amount.zero); - -class FeeDropDownChild extends ConsumerWidget { - const FeeDropDownChild({ - super.key, - required this.feeObject, - required this.feeRateType, - required this.walletId, - required this.feeFor, - required this.isSelected, - }); - - final FeeObject? feeObject; - final FeeRateType feeRateType; - final String walletId; - final Future Function({ - required Amount amount, - required FeeRateType feeRateType, - required int feeRate, - required CryptoCurrency coin, - }) feeFor; - final bool isSelected; - - static const stringsToLoopThrough = [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ]; - - String estimatedTimeToBeIncludedInNextBlock( - int targetBlockTime, - int estimatedNumberOfBlocks, - ) { - final int time = targetBlockTime * estimatedNumberOfBlocks; - - final int hours = (time / 3600).floor(); - if (hours > 1) { - return "~$hours hours"; - } else if (hours == 1) { - return "~$hours hour"; - } - - // less than an hour - - final string = (time / 60).toStringAsFixed(1); - - if (string == "1.0") { - return "~1 minute"; - } else { - if (string.endsWith(".0")) { - return "~${(time / 60).floor()} minutes"; - } - return "~$string minutes"; - } - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - debugPrint("BUILD: $runtimeType : $feeRateType"); - - final coin = ref.watch(pWalletCoin(walletId)); - - if (feeObject == null) { - return AnimatedText( - stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textFieldActiveText, - ), - ); - } else { - return FutureBuilder( - future: feeFor( - coin: coin, - feeRateType: feeRateType, - feeRate: feeRateType == FeeRateType.fast - ? feeObject!.fast - : feeRateType == FeeRateType.slow - ? feeObject!.slow - : feeObject!.medium, - amount: ref.watch(sendAmountProvider.state).state, - ), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "${feeRateType.prettyName} " - "(~${ref.watch(pAmountFormatter(coin)).format( - snapshot.data!, - indicatePrecisionLoss: false, - )})", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, - ), - if (feeObject != null) - Text( - coin is Ethereum - ? "" - : estimatedTimeToBeIncludedInNextBlock( - coin.targetBlockTimeSeconds, - feeRateType == FeeRateType.fast - ? feeObject!.numberOfBlocksFast - : feeRateType == FeeRateType.slow - ? feeObject!.numberOfBlocksSlow - : feeObject!.numberOfBlocksAverage, - ), - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ), - ), - ], - ); - } else { - return AnimatedText( - stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - ); - } - }, - ); - } - } -} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 29faa77d7..3aed8ba95 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -27,6 +27,7 @@ import '../../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet. import '../../../../providers/providers.dart'; import '../../../../providers/ui/fee_rate_type_state_provider.dart'; import '../../../../providers/ui/preview_tx_button_state_provider.dart'; +import '../../../../providers/wallet/desktop_fee_providers.dart'; import '../../../../providers/wallet/public_private_balance_state_provider.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/address_utils.dart'; @@ -67,7 +68,6 @@ import '../../../../widgets/textfield_icon_button.dart'; import '../../../coin_control/desktop_coin_control_use_dialog.dart'; import '../../../desktop_home_view.dart'; import 'address_book_address_chooser/address_book_address_chooser.dart'; -import 'desktop_fee_dropdown.dart'; import 'desktop_send_fee_form.dart'; class DesktopSend extends ConsumerStatefulWidget { @@ -99,8 +99,8 @@ class _DesktopSendState extends ConsumerState { late TextEditingController sendToController; late TextEditingController cryptoAmountController; late TextEditingController baseAmountController; - // late TextEditingController feeController; late TextEditingController memoController; + late TextEditingController nonceController; late final SendViewAutoFillData? _data; @@ -108,6 +108,7 @@ class _DesktopSendState extends ConsumerState { final _cryptoFocus = FocusNode(); final _baseFocus = FocusNode(); final _memoFocus = FocusNode(); + final _nonceFocusNode = FocusNode(); late final bool isStellar; @@ -408,6 +409,10 @@ class _DesktopSendState extends ConsumerState { memo: memo, feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, + nonce: + wallet.cryptoCurrency is Ethereum + ? int.tryParse(nonceController.text) + : null, utxos: (wallet is CoinControlInterface && coinControlEnabled && @@ -528,6 +533,7 @@ class _DesktopSendState extends ConsumerState { cryptoAmountController.text = ""; baseAmountController.text = ""; memoController.text = ""; + nonceController.text = ""; _address = ""; _addressToggleFlag = false; if (mounted) { @@ -864,7 +870,7 @@ class _DesktopSendState extends ConsumerState { cryptoAmountController = TextEditingController(); baseAmountController = TextEditingController(); memoController = TextEditingController(); - // feeController = TextEditingController(); + nonceController = TextEditingController(); onCryptoAmountChanged = _cryptoAmountChanged; cryptoAmountController.addListener(onCryptoAmountChanged); @@ -918,12 +924,13 @@ class _DesktopSendState extends ConsumerState { cryptoAmountController.dispose(); baseAmountController.dispose(); memoController.dispose(); - // feeController.dispose(); + nonceController.dispose(); _addressFocusNode.dispose(); _cryptoFocus.dispose(); _baseFocus.dispose(); _memoFocus.dispose(); + _nonceFocusNode.dispose(); super.dispose(); } @@ -1628,6 +1635,56 @@ class _DesktopSendState extends ConsumerState { onCustomFeeSliderChanged: (value) => customFeeRate = value, onCustomFeeOptionChanged: (value) => isCustomFee = value, ), + if (coin is Ethereum) const SizedBox(height: 20), + if (coin is Ethereum) + Text( + "Nonce", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, + ), + textAlign: TextAlign.left, + ), + if (coin is Ethereum) const SizedBox(height: 10), + if (coin is Ethereum) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 1, + key: const Key("sendViewNonceFieldKey"), + controller: nonceController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + keyboardType: const TextInputType.numberWithOptions(), + focusNode: _nonceFocusNode, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Leave empty to auto select nonce", + _nonceFocusNode, + context, + desktopMed: true, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ), + ), + ), + ), const SizedBox(height: 36), PrimaryButton( buttonHeight: ButtonHeight.l, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 1f5b20579..93bac0e90 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -46,6 +46,8 @@ class _DesktopSendFeeFormState extends ConsumerState { late final CryptoCurrency cryptoCurrency; + bool get isEth => cryptoCurrency is Ethereum; + bool isCustomFee = false; (FeeRateType, String?, String?)? feeSelectionResult; @@ -58,6 +60,7 @@ class _DesktopSendFeeFormState extends ConsumerState { @override Widget build(BuildContext context) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ ConditionalParent( condition: @@ -103,7 +106,7 @@ class _DesktopSendFeeFormState extends ConsumerState { ), child: Text( "Transaction fee" - "${isCustomFee ? "" : " (${cryptoCurrency is Ethereum ? "max" : "estimated"})"}", + "${isCustomFee ? "" : " (${isEth ? "max" : "estimated"})"}", style: STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index a69c6ef05..1f346dd1a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -23,6 +23,7 @@ import '../../../../pages/send_view/sub_widgets/building_transaction_dialog.dart import '../../../../providers/providers.dart'; import '../../../../providers/ui/fee_rate_type_state_provider.dart'; import '../../../../providers/ui/preview_tx_button_state_provider.dart'; +import '../../../../providers/wallet/desktop_fee_providers.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/address_utils.dart'; import '../../../../utilities/amount/amount.dart'; @@ -51,9 +52,7 @@ import '../../../../widgets/stack_text_field.dart'; import '../../../../widgets/textfield_icon_button.dart'; import '../../../desktop_home_view.dart'; import 'address_book_address_chooser/address_book_address_chooser.dart'; -import 'desktop_fee_dropdown.dart'; - -// const _kCryptoAmountRegex = r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$'; +import 'desktop_send_fee_form.dart'; class DesktopTokenSend extends ConsumerStatefulWidget { const DesktopTokenSend({ @@ -1025,18 +1024,11 @@ class _DesktopTokenSendState extends ConsumerState { }, ), const SizedBox(height: 20), - Text( - "Transaction fee (max)", - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveSearchIconRight, - ), - textAlign: TextAlign.left, + DesktopSendFeeForm( + walletId: walletId, + onCustomFeeSliderChanged: (value) => {}, + onCustomFeeOptionChanged: (value) {}, ), - const SizedBox(height: 10), - DesktopFeeDropDown(walletId: walletId, isToken: true), const SizedBox(height: 20), Text( "Nonce", diff --git a/lib/providers/wallet/desktop_fee_providers.dart b/lib/providers/wallet/desktop_fee_providers.dart new file mode 100644 index 000000000..d1723c78c --- /dev/null +++ b/lib/providers/wallet/desktop_fee_providers.dart @@ -0,0 +1,23 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; +import '../../utilities/amount/amount.dart'; + +final tokenFeeSessionCacheProvider = + ChangeNotifierProvider((ref) { + return FeeSheetSessionCache(); + }); + +final sendAmountProvider = StateProvider.autoDispose( + (_) => Amount.zero, +); diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart index 713aaa109..1840e04d9 100644 --- a/lib/widgets/desktop/desktop_fee_dialog.dart +++ b/lib/widgets/desktop/desktop_fee_dialog.dart @@ -4,8 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/models.dart'; import '../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; -import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart'; import '../../providers/global/wallets_provider.dart'; +import '../../providers/wallet/desktop_fee_providers.dart'; import '../../providers/wallet/public_private_balance_state_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount.dart'; @@ -69,19 +69,23 @@ class _DesktopFeeDialogState extends ConsumerState { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; } else { - ref.read(feeSheetSessionCacheProvider).fast[amount] = - await wallet.estimateFeeFor(amount, feeRate); + ref.read(feeSheetSessionCacheProvider).fast[amount] = await wallet + .estimateFeeFor(amount, feeRate); } } else { final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -119,14 +123,18 @@ class _DesktopFeeDialogState extends ConsumerState { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).average[amount] = fee; } else { @@ -169,19 +177,23 @@ class _DesktopFeeDialogState extends ConsumerState { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; } else { - ref.read(feeSheetSessionCacheProvider).slow[amount] = - await wallet.estimateFeeFor(amount, feeRate); + ref.read(feeSheetSessionCacheProvider).slow[amount] = await wallet + .estimateFeeFor(amount, feeRate); } } else { final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -214,9 +226,7 @@ class _DesktopFeeDialogState extends ConsumerState { maxHeight: double.infinity, child: FutureBuilder( future: ref.watch( - pWallets.select( - (value) => value.getWallet(walletId).fees, - ), + pWallets.select((value) => value.getWallet(walletId).fees), ), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && @@ -255,9 +265,7 @@ class _DesktopFeeDialogState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ); }, @@ -285,7 +293,8 @@ class DesktopFeeItem extends ConsumerStatefulWidget { required FeeRateType feeRateType, required int feeRate, required CryptoCurrency coin, - }) feeFor; + }) + feeFor; final bool isSelected; final bool isButton; @@ -337,19 +346,16 @@ class _DesktopFeeItemState extends ConsumerState { return ConditionalParent( condition: widget.isButton, - builder: (child) => MaterialButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pop( - ( - widget.feeRateType, - feeString, - timeString, - ), - ); - }, - child: child, - ), + builder: + (child) => MaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of( + context, + ).pop((widget.feeRateType, feeString, timeString)); + }, + child: child, + ), child: Builder( builder: (_) { if (!widget.isButton) { @@ -362,17 +368,12 @@ class _DesktopFeeItemState extends ConsumerState { ref.watch(publicPrivateBalanceStateProvider.state).state == "Private") { return Text( - "~${ref.watch(pAmountFormatter(coin)).format( - Amount( - rawValue: BigInt.parse("3794"), - fractionDigits: coin.fractionDigits, - ), - indicatePrecisionLoss: false, - )}", + "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, ), textAlign: TextAlign.left, ); @@ -385,11 +386,13 @@ class _DesktopFeeItemState extends ConsumerState { children: [ Text( widget.feeRateType.prettyName, - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, ), textAlign: TextAlign.left, ), @@ -405,9 +408,10 @@ class _DesktopFeeItemState extends ConsumerState { return AnimatedText( stringsToLoopThrough: stringsToLoopThrough, style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, ), ); } else { @@ -415,9 +419,10 @@ class _DesktopFeeItemState extends ConsumerState { future: widget.feeFor( coin: wallet.info.coin, feeRateType: widget.feeRateType, - feeRate: widget.feeRateType == FeeRateType.fast - ? widget.feeObject!.fast - : widget.feeRateType == FeeRateType.slow + feeRate: + widget.feeRateType == FeeRateType.fast + ? widget.feeObject!.fast + : widget.feeRateType == FeeRateType.slow ? widget.feeObject!.slow : widget.feeObject!.medium, amount: ref.watch(sendAmountProvider.state).state, @@ -425,44 +430,47 @@ class _DesktopFeeItemState extends ConsumerState { builder: (_, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { - feeString = "${widget.feeRateType.prettyName} " - "(~${ref.watch(pAmountFormatter(wallet.info.coin)).format( - snapshot.data!, - indicatePrecisionLoss: false, - )})"; - - timeString = wallet.info.coin is Ethereum - ? "" - : estimatedTimeToBeIncludedInNextBlock( - wallet.info.coin.targetBlockTimeSeconds, - widget.feeRateType == FeeRateType.fast - ? widget.feeObject!.numberOfBlocksFast - : widget.feeRateType == FeeRateType.slow - ? widget.feeObject!.numberOfBlocksSlow - : widget.feeObject!.numberOfBlocksAverage, - ); + feeString = + "${widget.feeRateType.prettyName} " + "(~${ref.watch(pAmountFormatter(wallet.info.coin)).format(snapshot.data!, indicatePrecisionLoss: false)})"; + + timeString = + wallet.info.coin is Ethereum + ? "" + : estimatedTimeToBeIncludedInNextBlock( + wallet.info.coin.targetBlockTimeSeconds, + widget.feeRateType == FeeRateType.fast + ? widget.feeObject!.numberOfBlocksFast + : widget.feeRateType == FeeRateType.slow + ? widget.feeObject!.numberOfBlocksSlow + : widget.feeObject!.numberOfBlocksAverage, + ); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( feeString!, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, ), textAlign: TextAlign.left, ), if (widget.feeObject != null) Text( timeString!, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), ], @@ -470,11 +478,13 @@ class _DesktopFeeItemState extends ConsumerState { } else { return AnimatedText( stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, ), ); } From 3316b69d647b27e369589403ee1a350a7446aebd Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 12:38:25 -0600 Subject: [PATCH 017/206] wip desktop custom eip-1559 fee ui --- .../sub_widgets/desktop_send_fee_form.dart | 31 ++- lib/widgets/eth_fee_form.dart | 227 ++++++++++++++++++ 2 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 lib/widgets/eth_fee_form.dart diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 93bac0e90..54590f722 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -11,13 +11,14 @@ import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; +import '../../../../wallets/crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; -import '../../../../wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart'; import '../../../../widgets/animated_text.dart'; import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../../widgets/desktop/desktop_fee_dialog.dart'; +import '../../../../widgets/eth_fee_form.dart'; import '../../../../widgets/fee_slider.dart'; class DesktopSendFeeForm extends ConsumerStatefulWidget { @@ -59,20 +60,20 @@ class _DesktopSendFeeFormState extends ConsumerState { @override Widget build(BuildContext context) { + final canEditFees = + isEth || + (cryptoCurrency is ElectrumXCurrencyInterface && + !(((cryptoCurrency is Firo) && + (ref.watch(publicPrivateBalanceStateProvider.state).state == + FiroType.lelantus || + ref.watch(publicPrivateBalanceStateProvider.state).state == + FiroType.spark)))); + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ConditionalParent( - condition: - ref.watch(pWallets).getWallet(widget.walletId) - is ElectrumXInterface && - !(((cryptoCurrency is Firo) && - (ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.lelantus || - ref - .watch(publicPrivateBalanceStateProvider.state) - .state == - FiroType.spark))), + condition: canEditFees, builder: (child) => Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -283,7 +284,13 @@ class _DesktopSendFeeFormState extends ConsumerState { ], ), ), - if (isCustomFee) + if (isCustomFee && isEth) + EthFeeForm( + stateChanged: (updatedFeeModel) { + print(updatedFeeModel); + }, + ), + if (isCustomFee && !isEth) Padding( padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( diff --git a/lib/widgets/eth_fee_form.dart b/lib/widgets/eth_fee_form.dart new file mode 100644 index 000000000..df5851acf --- /dev/null +++ b/lib/widgets/eth_fee_form.dart @@ -0,0 +1,227 @@ +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; + +import '../themes/stack_colors.dart'; +import '../utilities/constants.dart'; +import '../utilities/text_styles.dart'; +import 'stack_text_field.dart'; + +@immutable +class EthEIP1559Fee { + final Decimal maxBaseFeeGwei; + final Decimal priorityFeeGwei; + final int gasLimit; + + const EthEIP1559Fee({ + required this.maxBaseFeeGwei, + required this.priorityFeeGwei, + required this.gasLimit, + }); + + @override + String toString() => + "EthEIP1559Fee(" + "maxBaseFeeGwei: $maxBaseFeeGwei, " + "priorityFeeGwei: $priorityFeeGwei, " + "gasLimit: $gasLimit)"; +} + +class EthFeeForm extends StatefulWidget { + EthFeeForm({ + super.key, + this.minGasLimit = 21000, + this.maxGasLimit = 30000000, + this.initialState, + required this.stateChanged, + }) : assert( + initialState == null || + (initialState.gasLimit >= minGasLimit && + initialState.gasLimit <= maxGasLimit), + ); + + final int minGasLimit; + final int maxGasLimit; + + final EthEIP1559Fee? initialState; + + final void Function(EthEIP1559Fee) stateChanged; + + @override + State createState() => _EthFeeFormState(); +} + +class _EthFeeFormState extends State { + final maxBaseController = TextEditingController(); + final priorityFeeController = TextEditingController(); + final maxBaseFocus = FocusNode(); + final priorityFeeFocus = FocusNode(); + + late int gasLimit; + double _sliderValue = 0; + + @override + void initState() { + super.initState(); + + maxBaseController.text = + widget.initialState?.maxBaseFeeGwei.toString() ?? ""; + priorityFeeController.text = + widget.initialState?.priorityFeeGwei.toString() ?? ""; + + gasLimit = widget.initialState?.gasLimit ?? widget.minGasLimit; + print("asgLimit: $gasLimit"); + } + + @override + void dispose() { + maxBaseController.dispose(); + priorityFeeController.dispose(); + maxBaseFocus.dispose(); + priorityFeeFocus.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Max base fee (GWEI)", + style: STextStyles.smallMed12(context) + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 1, + controller: maxBaseController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + focusNode: maxBaseFocus, + onChanged: (value) { + widget.stateChanged( + EthEIP1559Fee( + maxBaseFeeGwei: Decimal.tryParse(value) ?? Decimal.zero, + priorityFeeGwei: + Decimal.tryParse(priorityFeeController.text) ?? + Decimal.zero, + gasLimit: gasLimit, + ), + ); + }, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Leave empty to auto select nonce", + maxBaseFocus, + context, + desktopMed: true, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ), + ), + ), + ), + const SizedBox(height: 20), + Text( + "Max base fee (GWEI)", + style: STextStyles.smallMed12(context) + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 1, + controller: priorityFeeController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + focusNode: priorityFeeFocus, + onChanged: (value) { + widget.stateChanged( + EthEIP1559Fee( + maxBaseFeeGwei: + Decimal.tryParse(maxBaseController.text) ?? Decimal.zero, + priorityFeeGwei: Decimal.tryParse(value) ?? Decimal.zero, + gasLimit: gasLimit, + ), + ); + }, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Leave empty to auto select nonce", + priorityFeeFocus, + context, + desktopMed: true, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ), + ), + ), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Gas limit", style: STextStyles.smallMed12(context)), + Text("$gasLimit", style: STextStyles.smallMed12(context)), + ], + ), + Slider( + value: _sliderValue, + onChanged: (value) { + setState(() { + _sliderValue = value; + final number = + (_sliderValue * (widget.maxGasLimit - widget.minGasLimit) + + widget.minGasLimit) + .toDouble(); + + gasLimit = number.toInt(); + }); + widget.stateChanged( + EthEIP1559Fee( + maxBaseFeeGwei: + Decimal.tryParse(maxBaseController.text) ?? Decimal.zero, + priorityFeeGwei: + Decimal.tryParse(priorityFeeController.text) ?? + Decimal.zero, + gasLimit: gasLimit, + ), + ); + }, + ), + ], + ); + } +} From 568c7c6b07c4bc57d7d4713a5fdd6a44b568531a Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 14:04:44 -0600 Subject: [PATCH 018/206] refactor eth gas tracker response data --- lib/services/ethereum/ethereum_api.dart | 4 +-- lib/utilities/eth_commons.dart | 42 +++++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 8619e3f01..ef3d64998 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -247,9 +247,9 @@ abstract class EthereumAPI { static Future getFees() async { final fees = (await getGasOracle()).value!; - final feesFast = fees.fast.shift(9).toBigInt(); + final feesFast = fees.high.shift(9).toBigInt(); final feesStandard = fees.average.shift(9).toBigInt(); - final feesSlow = fees.slow.shift(9).toBigInt(); + final feesSlow = fees.low.shift(9).toBigInt(); return FeeObject( numberOfBlocksFast: fees.numberOfBlocksFast, diff --git a/lib/utilities/eth_commons.dart b/lib/utilities/eth_commons.dart index c105412db..280f8ee8b 100644 --- a/lib/utilities/eth_commons.dart +++ b/lib/utilities/eth_commons.dart @@ -12,36 +12,45 @@ import 'package:bip32/bip32.dart' as bip32; import 'package:bip39/bip39.dart' as bip39; import 'package:decimal/decimal.dart'; import "package:hex/hex.dart"; + import '../wallets/crypto_currency/crypto_currency.dart'; class GasTracker { + final Decimal low; final Decimal average; - final Decimal fast; - final Decimal slow; + final Decimal high; final int numberOfBlocksFast; final int numberOfBlocksAverage; final int numberOfBlocksSlow; + final Decimal suggestBaseFee; + final String lastBlock; const GasTracker({ + required this.low, required this.average, - required this.fast, - required this.slow, + required this.high, required this.numberOfBlocksFast, required this.numberOfBlocksAverage, required this.numberOfBlocksSlow, + required this.suggestBaseFee, required this.lastBlock, }); + Decimal get lowPriority => (low - suggestBaseFee).zeroIfNegative; + Decimal get averagePriority => (average - suggestBaseFee).zeroIfNegative; + Decimal get highPriority => (high - suggestBaseFee).zeroIfNegative; + factory GasTracker.fromJson(Map json) { final targetTime = Ethereum(CryptoCurrencyNetwork.main).targetBlockTimeSeconds; return GasTracker( - fast: Decimal.parse(json["FastGasPrice"].toString()), + high: Decimal.parse(json["FastGasPrice"].toString()), average: Decimal.parse(json["ProposeGasPrice"].toString()), - slow: Decimal.parse(json["SafeGasPrice"].toString()), + low: Decimal.parse(json["SafeGasPrice"].toString()), + suggestBaseFee: Decimal.parse(json["suggestBaseFee"].toString()), // TODO fix hardcoded numberOfBlocksFast: 30 ~/ targetTime, numberOfBlocksAverage: 180 ~/ targetTime, @@ -49,6 +58,27 @@ class GasTracker { lastBlock: json["LastBlock"] as String, ); } + + @override + String toString() { + return 'GasTracker(' + 'slow: $low, ' + 'average: $average, ' + 'fast: $high, ' + 'suggestBaseFee: $suggestBaseFee, ' + 'numberOfBlocksFast: $numberOfBlocksFast, ' + 'numberOfBlocksAverage: $numberOfBlocksAverage, ' + 'numberOfBlocksSlow: $numberOfBlocksSlow, ' + 'lastBlock: $lastBlock' + ')'; + } +} + +extension DecimalExt on Decimal { + Decimal get zeroIfNegative { + if (this < Decimal.zero) return Decimal.zero; + return this; + } } const hdPathEthereum = "m/44'/60'/0'/0"; From fb6d35d1176ead245eeba54a5e36eedf3429b097 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 14:19:51 -0600 Subject: [PATCH 019/206] add eip-1559 fees fetch functionality --- lib/services/ethereum/ethereum_api.dart | 44 +++++++++++++++++++ lib/utilities/eth_commons.dart | 3 ++ .../crypto_currency/coins/ethereum.dart | 3 +- .../impl/sub_wallets/eth_token_wallet.dart | 6 +-- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index ef3d64998..bee88d37b 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -20,6 +20,7 @@ import '../../utilities/eth_commons.dart'; import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; +import '../../widgets/eth_fee_form.dart'; import '../tor_service.dart'; class EthApiException implements Exception { @@ -261,6 +262,49 @@ abstract class EthereumAPI { ); } + static Future< + ({EthEIP1559Fee low, EthEIP1559Fee average, EthEIP1559Fee high}) + > + getEip1559Fees(EthContractType? contractType) async { + final response = await getGasOracle(); + if (response.exception != null) { + throw response.exception!; + } + + final int gasLimit; + switch (contractType) { + case null: + case EthContractType.unknown: + // actually unknown or just normal eth + gasLimit = kEthereumMinGasLimit; + break; + + case EthContractType.erc20: + case EthContractType.erc721: + // can vary + gasLimit = kEthereumTokenMinGasLimit; + break; + } + + return ( + low: EthEIP1559Fee( + maxBaseFeeGwei: response.value!.suggestBaseFee, + priorityFeeGwei: response.value!.lowPriority, + gasLimit: gasLimit, + ), + average: EthEIP1559Fee( + maxBaseFeeGwei: response.value!.suggestBaseFee, + priorityFeeGwei: response.value!.averagePriority, + gasLimit: gasLimit, + ), + high: EthEIP1559Fee( + maxBaseFeeGwei: response.value!.suggestBaseFee, + priorityFeeGwei: response.value!.highPriority, + gasLimit: gasLimit, + ), + ); + } + static Future _addContractInfoToServer(String contractAddress) async { await client.get( url: Uri.parse( diff --git a/lib/utilities/eth_commons.dart b/lib/utilities/eth_commons.dart index 280f8ee8b..3bb8557de 100644 --- a/lib/utilities/eth_commons.dart +++ b/lib/utilities/eth_commons.dart @@ -83,6 +83,9 @@ extension DecimalExt on Decimal { const hdPathEthereum = "m/44'/60'/0'/0"; +const kEthereumMinGasLimit = 21000; +const kEthereumTokenMinGasLimit = 65000; + // equal to "0x${keccak256("Transfer(address,address,uint256)".toUint8ListFromUtf8).toHex}"; const kTransferEventSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; diff --git a/lib/wallets/crypto_currency/coins/ethereum.dart b/lib/wallets/crypto_currency/coins/ethereum.dart index bb12d0bb4..0c727de28 100644 --- a/lib/wallets/crypto_currency/coins/ethereum.dart +++ b/lib/wallets/crypto_currency/coins/ethereum.dart @@ -4,6 +4,7 @@ import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/node_model.dart'; import '../../../utilities/default_nodes.dart'; import '../../../utilities/enums/derive_path_type_enum.dart'; +import '../../../utilities/eth_commons.dart'; import '../crypto_currency.dart'; import '../intermediate/bip39_currency.dart'; @@ -41,7 +42,7 @@ class Ethereum extends Bip39Currency { @override String get ticker => _ticker; - int get gasLimit => 21000; + int get gasLimit => kEthereumMinGasLimit; @override bool get hasTokenSupport => true; diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index 136efc5ca..7f3d7735b 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -38,8 +38,6 @@ class EthTokenWallet extends Wallet { late web3dart.DeployedContract _deployedContract; late web3dart.ContractFunction _sendFunction; - static const gasLimit = 65000; - // =========================================================================== // =========================================================================== @@ -259,7 +257,7 @@ class EthTokenWallet extends Wallet { contract: _deployedContract, function: _sendFunction, parameters: [web3dart.EthereumAddress.fromHex(address), amount.raw], - maxGas: gasLimit, + maxGas: kEthereumTokenMinGasLimit, gasPrice: web3dart.EtherAmount.fromInt(web3dart.EtherUnit.wei, fee), nonce: nonce, ); @@ -290,7 +288,7 @@ class EthTokenWallet extends Wallet { Future estimateFeeFor(Amount amount, int feeRate) async { return ethWallet.estimateEthFee( feeRate, - gasLimit, + kEthereumTokenMinGasLimit, cryptoCurrency.fractionDigits, ); } From c23edb0d4b5c5695a0df2b36a9caab3edaeeb6ac Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 15:16:51 -0600 Subject: [PATCH 020/206] refactor FeeObject to use BigInt, add EthFeeObject, and of course a pile of autoformat changes... --- lib/models/paymint/fee_object_model.dart | 31 +- .../subwidgets/desktop_paynym_details.dart | 211 +++++---- lib/pages/send_view/send_view.dart | 9 +- .../transaction_fee_selection_sheet.dart | 303 ++++++------- lib/pages/send_view/token_send_view.dart | 4 +- .../sub_widgets/desktop_send_fee_form.dart | 9 +- lib/services/ethereum/ethereum_api.dart | 65 +-- lib/wallets/models/tx_data.dart | 33 +- .../wallet/impl/bitcoin_frost_wallet.dart | 14 +- lib/wallets/wallet/impl/bitcoin_wallet.dart | 8 +- .../wallet/impl/bitcoincash_wallet.dart | 139 +++--- lib/wallets/wallet/impl/cardano_wallet.dart | 184 +++++--- lib/wallets/wallet/impl/dash_wallet.dart | 77 ++-- lib/wallets/wallet/impl/dogecoin_wallet.dart | 80 ++-- lib/wallets/wallet/impl/ecash_wallet.dart | 122 +++--- lib/wallets/wallet/impl/epiccash_wallet.dart | 171 ++++---- lib/wallets/wallet/impl/ethereum_wallet.dart | 13 +- lib/wallets/wallet/impl/firo_wallet.dart | 214 ++++----- lib/wallets/wallet/impl/litecoin_wallet.dart | 211 ++++----- lib/wallets/wallet/impl/monero_wallet.dart | 41 +- lib/wallets/wallet/impl/namecoin_wallet.dart | 22 +- lib/wallets/wallet/impl/particl_wallet.dart | 175 ++++---- lib/wallets/wallet/impl/peercoin_wallet.dart | 8 +- lib/wallets/wallet/impl/solana_wallet.dart | 118 +++-- lib/wallets/wallet/impl/stellar_wallet.dart | 229 +++++----- .../impl/sub_wallets/eth_token_wallet.dart | 8 +- lib/wallets/wallet/impl/tezos_wallet.dart | 90 ++-- lib/wallets/wallet/impl/wownero_wallet.dart | 41 +- lib/wallets/wallet/impl/xelis_wallet.dart | 10 +- .../intermediate/lib_monero_wallet.dart | 377 ++++++++-------- lib/wallets/wallet/wallet.dart | 113 ++--- .../electrumx_interface.dart | 29 +- .../lelantus_interface.dart | 409 +++++++++--------- .../nano_interface.dart | 161 ++++--- .../paynym_interface.dart | 2 +- lib/widgets/desktop/desktop_fee_dialog.dart | 10 +- test/models/fee_object_model_test.dart | 25 +- 37 files changed, 1841 insertions(+), 1925 deletions(-) diff --git a/lib/models/paymint/fee_object_model.dart b/lib/models/paymint/fee_object_model.dart index 3745f997d..0c00f807f 100644 --- a/lib/models/paymint/fee_object_model.dart +++ b/lib/models/paymint/fee_object_model.dart @@ -9,9 +9,9 @@ */ class FeeObject { - final int fast; - final int medium; - final int slow; + final BigInt fast; + final BigInt medium; + final BigInt slow; final int numberOfBlocksFast; final int numberOfBlocksAverage; @@ -26,19 +26,22 @@ class FeeObject { required this.slow, }); - factory FeeObject.fromJson(Map json) { - return FeeObject( - fast: json['fast'] as int, - medium: json['average'] as int, - slow: json['slow'] as int, - numberOfBlocksFast: json['numberOfBlocksFast'] as int, - numberOfBlocksAverage: json['numberOfBlocksAverage'] as int, - numberOfBlocksSlow: json['numberOfBlocksSlow'] as int, - ); - } - @override String toString() { return "{fast: $fast, medium: $medium, slow: $slow, numberOfBlocksFast: $numberOfBlocksFast, numberOfBlocksAverage: $numberOfBlocksAverage, numberOfBlocksSlow: $numberOfBlocksSlow}"; } } + +class EthFeeObject extends FeeObject { + final BigInt suggestBaseFee; + + EthFeeObject({ + required this.suggestBaseFee, + required super.numberOfBlocksFast, + required super.numberOfBlocksAverage, + required super.numberOfBlocksSlow, + required super.fast, + required super.medium, + required super.slow, + }); +} diff --git a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart index 6b08b84db..3185144f2 100644 --- a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart +++ b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart @@ -62,12 +62,11 @@ class _PaynymDetailsPopupState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => WillPopScope( - onWillPop: () async => canPop, - child: const LoadingIndicator( - width: 200, - ), - ), + builder: + (context) => WillPopScope( + onWillPop: () async => canPop, + child: const LoadingIndicator(width: 200), + ), ), ); @@ -111,45 +110,47 @@ class _PaynymDetailsPopupState extends ConsumerState { // show info pop up await showDialog( context: context, - builder: (context) => ConfirmPaynymConnectDialog( - nymName: widget.accountLite.nymName, - locale: ref.read(localeServiceChangeNotifierProvider).locale, - onConfirmPressed: () { - Navigator.of(context, rootNavigator: true).pop(); - unawaited( - showDialog( - context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: ConfirmTransactionView( - walletId: widget.walletId, - isPaynymNotificationTransaction: true, - txData: preparedTx, - onSuccess: () { - // do nothing extra - }, - onSuccessInsteadOfRouteOnSuccess: () { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of(context, rootNavigator: true).pop(); - unawaited( - showFloatingFlushBar( - type: FlushBarType.success, - message: - "Connection initiated to ${widget.accountLite.nymName}", - iconAsset: Assets.svg.copy, - context: context, + builder: + (context) => ConfirmPaynymConnectDialog( + nymName: widget.accountLite.nymName, + locale: ref.read(localeServiceChangeNotifierProvider).locale, + onConfirmPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + unawaited( + showDialog( + context: context, + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: ConfirmTransactionView( + walletId: widget.walletId, + isPaynymNotificationTransaction: true, + txData: preparedTx, + onSuccess: () { + // do nothing extra + }, + onSuccessInsteadOfRouteOnSuccess: () { + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context, rootNavigator: true).pop(); + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: + "Connection initiated to ${widget.accountLite.nymName}", + iconAsset: Assets.svg.copy, + context: context, + ), + ); + }, + ), ), - ); - }, ), - ), - ), - ); - }, - amount: preparedTx.amount! + preparedTx.fee!, - coin: ref.read(pWalletCoin(widget.walletId)), - ), + ); + }, + amount: preparedTx.amount! + preparedTx.fee!, + coin: ref.read(pWalletCoin(widget.walletId)), + ), ); } } @@ -157,10 +158,11 @@ class _PaynymDetailsPopupState extends ConsumerState { Future _onSend() async { await showDialog( context: context, - builder: (context) => DesktopPaynymSendDialog( - walletId: widget.walletId, - accountLite: widget.accountLite, - ), + builder: + (context) => DesktopPaynymSendDialog( + walletId: widget.walletId, + accountLite: widget.accountLite, + ), ); } @@ -185,9 +187,7 @@ class _PaynymDetailsPopupState extends ConsumerState { paymentCodeString: widget.accountLite.code, size: 36, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -196,8 +196,9 @@ class _PaynymDetailsPopupState extends ConsumerState { style: STextStyles.desktopTextSmall(context), ), FutureBuilder( - future: paynymWallet - .hasConnected(widget.accountLite.code), + future: paynymWallet.hasConnected( + widget.accountLite.code, + ), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done && @@ -205,16 +206,16 @@ class _PaynymDetailsPopupState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( "Connected", - style: STextStyles.desktopTextSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorGreen, + style: STextStyles.desktopTextSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorGreen, ), ), ], @@ -228,15 +229,14 @@ class _PaynymDetailsPopupState extends ConsumerState { ), ], ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Row( children: [ Expanded( child: FutureBuilder( - future: - paynymWallet.hasConnected(widget.accountLite.code), + future: paynymWallet.hasConnected( + widget.accountLite.code, + ), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done && @@ -249,9 +249,10 @@ class _PaynymDetailsPopupState extends ConsumerState { Assets.svg.circleArrowUpRight, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + color: + Theme.of(context) + .extension()! + .buttonTextPrimary, ), iconSpacing: 6, onPressed: _onSend, @@ -264,9 +265,10 @@ class _PaynymDetailsPopupState extends ConsumerState { Assets.svg.circlePlusFilled, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + color: + Theme.of(context) + .extension()! + .buttonTextPrimary, ), iconSpacing: 6, onPressed: _onConnectPressed, @@ -281,44 +283,41 @@ class _PaynymDetailsPopupState extends ConsumerState { }, ), ), - const SizedBox( - width: 20, - ), + const SizedBox(width: 20), kDisableFollowing ? const Spacer() : Expanded( - child: PaynymFollowToggleButton( - walletId: widget.walletId, - paymentCodeStringToFollow: - widget.accountLite.code, - style: - PaynymFollowToggleButtonStyle.detailsDesktop, - ), + child: PaynymFollowToggleButton( + walletId: widget.walletId, + paymentCodeStringToFollow: widget.accountLite.code, + style: PaynymFollowToggleButtonStyle.detailsDesktop, ), + ), ], ), if (_showInsufficientFundsInfo) Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, + color: + Theme.of( + context, + ).extension()!.warningBackground, child: Text( "Adding a PayNym to your contacts requires a one-time " "transaction fee for creating the record on the " "blockchain. Please deposit more " "${ref.watch(pWalletCoin(widget.walletId)).ticker} " "into your wallet and try again.", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.warningForeground, ), ), ), @@ -341,9 +340,7 @@ class _PaynymDetailsPopupState extends ConsumerState { "PayNym address", style: STextStyles.desktopTextExtraExtraSmall(context), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Row( children: [ Expanded( @@ -351,18 +348,18 @@ class _PaynymDetailsPopupState extends ConsumerState { constraints: const BoxConstraints(minHeight: 100), child: Text( widget.accountLite.code, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), ), - const SizedBox( - width: 20, - ), + const SizedBox(width: 20), QR( padding: const EdgeInsets.all(0), size: 100, @@ -370,16 +367,12 @@ class _PaynymDetailsPopupState extends ConsumerState { ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), CustomTextButton( text: "Copy", onTap: () async { await Clipboard.setData( - ClipboardData( - text: widget.accountLite.code, - ), + ClipboardData(text: widget.accountLite.code), ); unawaited( showFloatingFlushBar( diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 5a624a916..780231f3c 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -450,7 +450,7 @@ class _SendViewState extends ConsumerState { final wallet = ref.read(pWallets).getWallet(walletId); final feeObject = await wallet.fees; - late final int feeRate; + late final BigInt feeRate; switch (ref.read(feeRateTypeStateProvider.state).state) { case FeeRateType.fast: @@ -463,7 +463,7 @@ class _SendViewState extends ConsumerState { feeRate = feeObject.slow; break; default: - feeRate = -1; + feeRate = BigInt.from(-1); } Amount fee; @@ -483,7 +483,10 @@ class _SendViewState extends ConsumerState { throw ArgumentError("custom fee not available for monero"); } - fee = await wallet.estimateFeeFor(amount, specialMoneroId.value); + fee = await wallet.estimateFeeFor( + amount, + BigInt.from(specialMoneroId.value), + ); cachedFees[amount] = ref .read(pAmountFormatter(coin)) .format(fee, withUnitName: true, indicatePrecisionLoss: false); diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index 2586d88ee..8f2f79b68 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -8,8 +8,8 @@ * */ -import 'package:flutter/material.dart'; import 'package:cs_monero/cs_monero.dart' as lib_monero; +import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../models/paymint/fee_object_model.dart'; @@ -32,8 +32,8 @@ import '../../../widgets/animated_text.dart'; final feeSheetSessionCacheProvider = ChangeNotifierProvider((ref) { - return FeeSheetSessionCache(); -}); + return FeeSheetSessionCache(); + }); class FeeSheetSessionCache extends ChangeNotifier { final Map fast = {}; @@ -79,7 +79,7 @@ class _TransactionFeeSelectionSheetState Future feeFor({ required Amount amount, required FeeRateType feeRateType, - required int feeRate, + required BigInt feeRate, required CryptoCurrency coin, }) async { switch (feeRateType) { @@ -91,27 +91,31 @@ class _TransactionFeeSelectionSheetState if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.high.value, + BigInt.from(lib_monero.TransactionPriority.high.value), ); ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; } else { - ref.read(feeSheetSessionCacheProvider).fast[amount] = - await wallet.estimateFeeFor(amount, feeRate); + ref.read(feeSheetSessionCacheProvider).fast[amount] = await wallet + .estimateFeeFor(amount, feeRate); } } else { final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -128,21 +132,25 @@ class _TransactionFeeSelectionSheetState if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.medium.value, + BigInt.from(lib_monero.TransactionPriority.medium.value), ); ref.read(feeSheetSessionCacheProvider).average[amount] = fee; } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).average[amount] = fee; } else { @@ -164,26 +172,30 @@ class _TransactionFeeSelectionSheetState if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.normal.value, + BigInt.from(lib_monero.TransactionPriority.normal.value), ); ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.spark: - fee = - await (wallet as FiroWallet).estimateFeeForSpark(amount); + fee = await (wallet as FiroWallet).estimateFeeForSpark( + amount, + ); case FiroType.lelantus: - fee = await (wallet as FiroWallet) - .estimateFeeForLelantus(amount); + fee = await (wallet as FiroWallet).estimateFeeForLelantus( + amount, + ); case FiroType.public: - fee = await (wallet as FiroWallet) - .estimateFeeFor(amount, feeRate); + fee = await (wallet as FiroWallet).estimateFeeFor( + amount, + feeRate, + ); } ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; } else { - ref.read(feeSheetSessionCacheProvider).slow[amount] = - await wallet.estimateFeeFor(amount, feeRate); + ref.read(feeSheetSessionCacheProvider).slow[amount] = await wallet + .estimateFeeFor(amount, feeRate); } } else { final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -243,17 +255,10 @@ class _TransactionFeeSelectionSheetState return Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Padding( - padding: const EdgeInsets.only( - left: 24, - right: 24, - top: 10, - bottom: 0, - ), + padding: const EdgeInsets.only(left: 24, right: 24, top: 10, bottom: 0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -261,9 +266,10 @@ class _TransactionFeeSelectionSheetState Center( child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -272,13 +278,12 @@ class _TransactionFeeSelectionSheetState height: 4, ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), FutureBuilder( - future: widget.isToken - ? ref.read(pCurrentTokenWallet)!.fees - : wallet.fees, + future: + widget.isToken + ? ref.read(pCurrentTokenWallet)!.fees + : wallet.fees, builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { @@ -293,9 +298,7 @@ class _TransactionFeeSelectionSheetState style: STextStyles.pageTitleH2(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), GestureDetector( onTap: () { final state = @@ -304,8 +307,10 @@ class _TransactionFeeSelectionSheetState ref.read(feeRateTypeStateProvider.state).state = FeeRateType.fast; } - final String? fee = - getAmount(FeeRateType.fast, wallet.info.coin); + final String? fee = getAmount( + FeeRateType.fast, + wallet.info.coin, + ); if (fee != null) { widget.updateChosen(fee); } @@ -323,13 +328,17 @@ class _TransactionFeeSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FeeRateType.fast, - groupValue: ref - .watch(feeRateTypeStateProvider.state) - .state, + groupValue: + ref + .watch( + feeRateTypeStateProvider.state, + ) + .state, onChanged: (x) { ref .read(feeRateTypeStateProvider.state) @@ -341,9 +350,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -355,15 +362,14 @@ class _TransactionFeeSelectionSheetState style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), - const SizedBox( - width: 2, - ), + const SizedBox(width: 2), if (feeObject == null) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), if (feeObject != null) FutureBuilder( @@ -381,15 +387,7 @@ class _TransactionFeeSelectionSheetState ConnectionState.done && snapshot.hasData) { return Text( - "(~${ref.watch( - pAmountFormatter( - coin, - ), - ).format( - snapshot.data!, - indicatePrecisionLoss: - false, - )})", + "(~${ref.watch(pAmountFormatter(coin)).format(snapshot.data!, indicatePrecisionLoss: false)})", style: STextStyles.itemSubtitle( context, ), @@ -408,9 +406,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (feeObject == null && coin is! Ethereum) AnimatedText( stringsToLoopThrough: @@ -433,9 +429,7 @@ class _TransactionFeeSelectionSheetState ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), GestureDetector( onTap: () { final state = @@ -444,8 +438,10 @@ class _TransactionFeeSelectionSheetState ref.read(feeRateTypeStateProvider.state).state = FeeRateType.average; } - final String? fee = - getAmount(FeeRateType.average, coin); + final String? fee = getAmount( + FeeRateType.average, + coin, + ); if (fee != null) { widget.updateChosen(fee); } @@ -462,13 +458,17 @@ class _TransactionFeeSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FeeRateType.average, - groupValue: ref - .watch(feeRateTypeStateProvider.state) - .state, + groupValue: + ref + .watch( + feeRateTypeStateProvider.state, + ) + .state, onChanged: (x) { ref .read(feeRateTypeStateProvider.state) @@ -479,9 +479,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -493,15 +491,14 @@ class _TransactionFeeSelectionSheetState style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), - const SizedBox( - width: 2, - ), + const SizedBox(width: 2), if (feeObject == null) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), if (feeObject != null) FutureBuilder( @@ -519,15 +516,7 @@ class _TransactionFeeSelectionSheetState ConnectionState.done && snapshot.hasData) { return Text( - "(~${ref.watch( - pAmountFormatter( - coin, - ), - ).format( - snapshot.data!, - indicatePrecisionLoss: - false, - )})", + "(~${ref.watch(pAmountFormatter(coin)).format(snapshot.data!, indicatePrecisionLoss: false)})", style: STextStyles.itemSubtitle( context, ), @@ -546,9 +535,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (feeObject == null && coin is! Ethereum) AnimatedText( stringsToLoopThrough: @@ -571,9 +558,7 @@ class _TransactionFeeSelectionSheetState ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), GestureDetector( onTap: () { final state = @@ -599,13 +584,17 @@ class _TransactionFeeSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FeeRateType.slow, - groupValue: ref - .watch(feeRateTypeStateProvider.state) - .state, + groupValue: + ref + .watch( + feeRateTypeStateProvider.state, + ) + .state, onChanged: (x) { ref .read(feeRateTypeStateProvider.state) @@ -616,9 +605,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -630,15 +617,14 @@ class _TransactionFeeSelectionSheetState style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), - const SizedBox( - width: 2, - ), + const SizedBox(width: 2), if (feeObject == null) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), if (feeObject != null) FutureBuilder( @@ -656,15 +642,7 @@ class _TransactionFeeSelectionSheetState ConnectionState.done && snapshot.hasData) { return Text( - "(~${ref.watch( - pAmountFormatter( - coin, - ), - ).format( - snapshot.data!, - indicatePrecisionLoss: - false, - )})", + "(~${ref.watch(pAmountFormatter(coin)).format(snapshot.data!, indicatePrecisionLoss: false)})", style: STextStyles.itemSubtitle( context, ), @@ -683,9 +661,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), if (feeObject == null && coin is! Ethereum) AnimatedText( stringsToLoopThrough: @@ -708,9 +684,7 @@ class _TransactionFeeSelectionSheetState ), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), if (wallet is ElectrumXInterface) GestureDetector( onTap: () { @@ -735,13 +709,17 @@ class _TransactionFeeSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FeeRateType.custom, - groupValue: ref - .watch(feeRateTypeStateProvider.state) - .state, + groupValue: + ref + .watch( + feeRateTypeStateProvider.state, + ) + .state, onChanged: (x) { ref .read( @@ -754,9 +732,7 @@ class _TransactionFeeSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -765,15 +741,14 @@ class _TransactionFeeSelectionSheetState children: [ Text( FeeRateType.custom.prettyName, - style: - STextStyles.titleBold12(context), + style: STextStyles.titleBold12( + context, + ), textAlign: TextAlign.left, ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), ], ), ), @@ -782,9 +757,7 @@ class _TransactionFeeSelectionSheetState ), ), if (wallet is ElectrumXInterface) - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), ], ); }, @@ -800,7 +773,9 @@ class _TransactionFeeSelectionSheetState switch (feeRateType) { case FeeRateType.fast: if (ref.read(feeSheetSessionCacheProvider).fast[amount] != null) { - return ref.read(pAmountFormatter(coin)).format( + return ref + .read(pAmountFormatter(coin)) + .format( ref.read(feeSheetSessionCacheProvider).fast[amount]!, indicatePrecisionLoss: false, withUnitName: false, @@ -810,7 +785,9 @@ class _TransactionFeeSelectionSheetState case FeeRateType.average: if (ref.read(feeSheetSessionCacheProvider).average[amount] != null) { - return ref.read(pAmountFormatter(coin)).format( + return ref + .read(pAmountFormatter(coin)) + .format( ref.read(feeSheetSessionCacheProvider).average[amount]!, indicatePrecisionLoss: false, withUnitName: false, @@ -820,7 +797,9 @@ class _TransactionFeeSelectionSheetState case FeeRateType.slow: if (ref.read(feeSheetSessionCacheProvider).slow[amount] != null) { - return ref.read(pAmountFormatter(coin)).format( + return ref + .read(pAmountFormatter(coin)) + .format( ref.read(feeSheetSessionCacheProvider).slow[amount]!, indicatePrecisionLoss: false, withUnitName: false, @@ -831,7 +810,7 @@ class _TransactionFeeSelectionSheetState return null; } } catch (e, s) { - Logging.instance.w("$e $s", error: e, stackTrace: s,); + Logging.instance.w("$e $s", error: e, stackTrace: s); return null; } } diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 281045361..b22a9e9d0 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -360,7 +360,7 @@ class _TokenSendViewState extends ConsumerState { final wallet = ref.read(pCurrentTokenWallet)!; final feeObject = await wallet.fees; - late final int feeRate; + late final BigInt feeRate; switch (ref.read(feeRateTypeStateProvider.state).state) { case FeeRateType.fast: @@ -373,7 +373,7 @@ class _TokenSendViewState extends ConsumerState { feeRate = feeObject.slow; break; default: - feeRate = -1; + feeRate = BigInt.from(-1); } final Amount fee = await wallet.estimateFeeFor(Amount.zero, feeRate); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 54590f722..62989f1dc 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -140,7 +140,7 @@ class _DesktopSendFeeFormState extends ConsumerState { feeFor: ({ required Amount amount, required FeeRateType feeRateType, - required int feeRate, + required BigInt feeRate, required CryptoCurrency coin, }) async { if (ref @@ -154,7 +154,12 @@ class _DesktopSendFeeFormState extends ConsumerState { if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.medium.value, + BigInt.from( + lib_monero + .TransactionPriority + .medium + .value, + ), ); ref .read(feeSheetSessionCacheProvider) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index bee88d37b..c9e405cba 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -20,7 +20,6 @@ import '../../utilities/eth_commons.dart'; import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; -import '../../widgets/eth_fee_form.dart'; import '../tor_service.dart'; class EthApiException implements Exception { @@ -200,7 +199,7 @@ abstract class EthereumAPI { } } - static Future> getGasOracle() async { + static Future> _getGasOracle() async { try { final response = await client.get( url: Uri.parse("$stackBaseServer/gas-prices"), @@ -246,62 +245,20 @@ abstract class EthereumAPI { } } - static Future getFees() async { - final fees = (await getGasOracle()).value!; - final feesFast = fees.high.shift(9).toBigInt(); - final feesStandard = fees.average.shift(9).toBigInt(); - final feesSlow = fees.low.shift(9).toBigInt(); - - return FeeObject( - numberOfBlocksFast: fees.numberOfBlocksFast, - numberOfBlocksAverage: fees.numberOfBlocksAverage, - numberOfBlocksSlow: fees.numberOfBlocksSlow, - fast: feesFast.toInt(), - medium: feesStandard.toInt(), - slow: feesSlow.toInt(), - ); - } - - static Future< - ({EthEIP1559Fee low, EthEIP1559Fee average, EthEIP1559Fee high}) - > - getEip1559Fees(EthContractType? contractType) async { - final response = await getGasOracle(); + static Future getFees() async { + final response = await _getGasOracle(); if (response.exception != null) { throw response.exception!; } - final int gasLimit; - switch (contractType) { - case null: - case EthContractType.unknown: - // actually unknown or just normal eth - gasLimit = kEthereumMinGasLimit; - break; - - case EthContractType.erc20: - case EthContractType.erc721: - // can vary - gasLimit = kEthereumTokenMinGasLimit; - break; - } - - return ( - low: EthEIP1559Fee( - maxBaseFeeGwei: response.value!.suggestBaseFee, - priorityFeeGwei: response.value!.lowPriority, - gasLimit: gasLimit, - ), - average: EthEIP1559Fee( - maxBaseFeeGwei: response.value!.suggestBaseFee, - priorityFeeGwei: response.value!.averagePriority, - gasLimit: gasLimit, - ), - high: EthEIP1559Fee( - maxBaseFeeGwei: response.value!.suggestBaseFee, - priorityFeeGwei: response.value!.highPriority, - gasLimit: gasLimit, - ), + return EthFeeObject( + suggestBaseFee: response.value!.suggestBaseFee.shift(9).toBigInt(), + numberOfBlocksFast: response.value!.numberOfBlocksFast, + numberOfBlocksAverage: response.value!.numberOfBlocksAverage, + numberOfBlocksSlow: response.value!.numberOfBlocksSlow, + fast: response.value!.high.shift(9).toBigInt(), + medium: response.value!.average.shift(9).toBigInt(), + slow: response.value!.low.shift(9).toBigInt(), ); } diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 94474e390..1fbe077e2 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -14,7 +14,7 @@ typedef TxRecipient = ({String address, Amount amount, bool isChange}); class TxData { final FeeRateType? feeRateType; - final int? feeRateAmount; + final BigInt? feeRateAmount; final int? satsPerVByte; final Amount? fee; @@ -64,13 +64,8 @@ class TxData { final tezart.OperationsList? tezosOperationsList; // firo spark specific - final List< - ({ - String address, - Amount amount, - String memo, - bool isChange, - })>? sparkRecipients; + final List<({String address, Amount amount, String memo, bool isChange})>? + sparkRecipients; final List? sparkMints; final List? usedSparkCoins; @@ -201,13 +196,14 @@ class TxData { } } - int? get estimatedSatsPerVByte => fee != null && vSize != null - ? (fee!.raw ~/ BigInt.from(vSize!)).toInt() - : null; + int? get estimatedSatsPerVByte => + fee != null && vSize != null + ? (fee!.raw ~/ BigInt.from(vSize!)).toInt() + : null; TxData copyWith({ FeeRateType? feeRateType, - int? feeRateAmount, + BigInt? feeRateAmount, int? satsPerVByte, Amount? fee, int? vSize, @@ -237,14 +233,8 @@ class TxData { TransactionSubType? txSubType, List>? mintsMapLelantus, tezart.OperationsList? tezosOperationsList, - List< - ({ - String address, - Amount amount, - String memo, - bool isChange, - })>? - sparkRecipients, + List<({String address, Amount amount, String memo, bool isChange})>? + sparkRecipients, List? sparkMints, List? usedSparkCoins, TransactionV2? tempTx, @@ -294,7 +284,8 @@ class TxData { } @override - String toString() => 'TxData{' + String toString() => + 'TxData{' 'feeRateType: $feeRateType, ' 'feeRateAmount: $feeRateAmount, ' 'satsPerVByte: $satsPerVByte, ' diff --git a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart index 3beaa0e8d..2b5173b6b 100644 --- a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart @@ -337,7 +337,7 @@ class BitcoinFrostWallet extends Wallet } } - Future sweepAllEstimate(int feeRate) async { + Future sweepAllEstimate(BigInt feeRate) async { int available = 0; int inputCount = 0; final height = await chainHeight; @@ -367,11 +367,11 @@ class BitcoinFrostWallet extends Wallet // return vSize * (feeRatePerKB / 1000).ceil(); // } - Amount _roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount _roughFeeEstimate(int inputCount, int outputCount, BigInt feeRatePerKB) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); @@ -724,7 +724,7 @@ class BitcoinFrostWallet extends Wallet } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { final available = info.cachedBalance.spendable; if (available == amount) { @@ -790,15 +790,15 @@ class BitcoinFrostWallet extends Wallet fast: Amount.fromDecimal( fast, fractionDigits: cryptoCurrency.fractionDigits, - ).raw.toInt(), + ).raw, medium: Amount.fromDecimal( medium, fractionDigits: cryptoCurrency.fractionDigits, - ).raw.toInt(), + ).raw, slow: Amount.fromDecimal( slow, fractionDigits: cryptoCurrency.fractionDigits, - ).raw.toInt(), + ).raw, ); Logging.instance.i("fetched fees: $feeObject"); diff --git a/lib/wallets/wallet/impl/bitcoin_wallet.dart b/lib/wallets/wallet/impl/bitcoin_wallet.dart index 5c7f3ed75..2ce942673 100644 --- a/lib/wallets/wallet/impl/bitcoin_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoin_wallet.dart @@ -54,19 +54,19 @@ class BitcoinWallet extends Bip39HDWallet // =========================================================================== @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate(int inputCount, int outputCount, BigInt feeRatePerKB) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } // // @override diff --git a/lib/wallets/wallet/impl/bitcoincash_wallet.dart b/lib/wallets/wallet/impl/bitcoincash_wallet.dart index 666d5fd6b..cee690219 100644 --- a/lib/wallets/wallet/impl/bitcoincash_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoincash_wallet.dart @@ -33,57 +33,54 @@ class BitcoincashWallet int get isarTransactionVersion => 2; BitcoincashWallet(CryptoCurrencyNetwork network) - : super(Bitcoincash(network) as T); + : super(Bitcoincash(network) as T); @override - FilterOperation? get changeAddressFilterOperation => FilterGroup.and( - [ - ...standardChangeAddressFilters, - FilterGroup.not( - const ObjectFilter( - property: "derivationPath", - filter: FilterCondition.startsWith( - property: "value", - value: "m/44'/0'", - ), - ), - ), - ], - ); + FilterOperation? get changeAddressFilterOperation => FilterGroup.and([ + ...standardChangeAddressFilters, + FilterGroup.not( + const ObjectFilter( + property: "derivationPath", + filter: FilterCondition.startsWith( + property: "value", + value: "m/44'/0'", + ), + ), + ), + ]); @override - FilterOperation? get receivingAddressFilterOperation => FilterGroup.and( - [ - ...standardReceivingAddressFilters, - FilterGroup.not( - const ObjectFilter( - property: "derivationPath", - filter: FilterCondition.startsWith( - property: "value", - value: "m/44'/0'", - ), - ), - ), - ], - ); + FilterOperation? get receivingAddressFilterOperation => FilterGroup.and([ + ...standardReceivingAddressFilters, + FilterGroup.not( + const ObjectFilter( + property: "derivationPath", + filter: FilterCondition.startsWith( + property: "value", + value: "m/44'/0'", + ), + ), + ), + ]); // =========================================================================== @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .typeEqualTo(AddressType.nonWallet) - .and() - .group( - (q) => q - .subTypeEqualTo(AddressSubType.receiving) - .or() - .subTypeEqualTo(AddressSubType.change), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .typeEqualTo(AddressType.nonWallet) + .and() + .group( + (q) => q + .subTypeEqualTo(AddressSubType.receiving) + .or() + .subTypeEqualTo(AddressSubType.change), + ) + .findAll(); return allAddresses; } @@ -106,20 +103,23 @@ class BitcoincashWallet final List
allAddressesOld = await fetchAddressesForElectrumXScan(); - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => convertAddressString(e.value)) + .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => convertAddressString(e.value)) + .toSet(); final allAddressesSet = {...receivingAddresses, ...changeAddresses}; - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); final List> allTransactions = []; @@ -139,8 +139,9 @@ class BitcoincashWallet ); // check for duplicates before adding to list - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -294,12 +295,8 @@ class BitcoincashWallet // only found outputs owned by this wallet type = TransactionType.incoming; } else { - Logging.instance.e( - "Unexpected tx found (ignoring it)", - ); - Logging.instance.d( - "Unexpected tx found (ignoring it): $txData", - ); + Logging.instance.e("Unexpected tx found (ignoring it)"); + Logging.instance.d("Unexpected tx found (ignoring it): $txData"); continue; } @@ -310,7 +307,8 @@ class BitcoincashWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -327,7 +325,7 @@ class BitcoincashWallet @override Future<({String? blockedReason, bool blocked, String? utxoLabel})> - checkBlockUTXO( + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map jsonTX, @@ -339,8 +337,9 @@ class BitcoincashWallet if (scriptPubKeyHex != null) { // check for cash tokens try { - final ctOutput = - cash_tokens.unwrap_spk(scriptPubKeyHex.toUint8ListFromHex); + final ctOutput = cash_tokens.unwrap_spk( + scriptPubKeyHex.toUint8ListFromHex, + ); if (ctOutput.token_data != null) { // found a token! blocked = true; @@ -374,19 +373,23 @@ class BitcoincashWallet // TODO: correct formula for bch? @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((181 * inputCount) + (34 * outputCount) + 10) * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: info.coin.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } @override diff --git a/lib/wallets/wallet/impl/cardano_wallet.dart b/lib/wallets/wallet/impl/cardano_wallet.dart index 3beafe5f5..2cad7c514 100644 --- a/lib/wallets/wallet/impl/cardano_wallet.dart +++ b/lib/wallets/wallet/impl/cardano_wallet.dart @@ -45,15 +45,16 @@ class CardanoWallet extends Bip39Wallet { final seed = CardanoIcarusSeedGenerator(mnemonic).generate(); final cip1852 = Cip1852.fromSeed(seed, Cip1852Coins.cardanoIcarus); final derivationAccount = cip1852.purpose.coin.account(0); - final shelley = CardanoShelley.fromCip1852Object(derivationAccount) - .change(Bip44Changes.chainExt) - .addressIndex(0); + final shelley = CardanoShelley.fromCip1852Object( + derivationAccount, + ).change(Bip44Changes.chainExt).addressIndex(0); final paymentPublicKey = shelley.bip44.publicKey.compressed; final stakePublicKey = shelley.bip44Sk.publicKey.compressed; - final addressStr = ADABaseAddress.fromPublicKey( - basePubkeyBytes: paymentPublicKey, - stakePubkeyBytes: stakePublicKey, - ).address; + final addressStr = + ADABaseAddress.fromPublicKey( + basePubkeyBytes: paymentPublicKey, + stakePubkeyBytes: stakePublicKey, + ).address; return Address( walletId: walletId, value: addressStr, @@ -76,7 +77,11 @@ class CardanoWallet extends Bip39Wallet { await mainDB.updateOrPutAddresses([address]); } } catch (e, s) { - Logging.instance.e("$runtimeType checkSaveInitialReceivingAddress() failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType checkSaveInitialReceivingAddress() failed: ", + error: e, + stackTrace: s, + ); } } @@ -91,13 +96,17 @@ class CardanoWallet extends Bip39Wallet { return Future.value(health); } catch (e, s) { - Logging.instance.e("Error ping checking in cardano_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error ping checking in cardano_wallet.dart: ", + error: e, + stackTrace: s, + ); return Future.value(false); } } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { await updateProvider(); if (info.cachedBalance.spendable.raw == BigInt.zero) { @@ -113,10 +122,7 @@ class CardanoWallet extends Bip39Wallet { final fee = params.calculateFee(284); - return Amount( - rawValue: fee, - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount(rawValue: fee, fractionDigits: cryptoCurrency.fractionDigits); } @override @@ -129,7 +135,7 @@ class CardanoWallet extends Bip39Wallet { ); // 284 is the size of a basic transaction with one input and two outputs (change and recipient) - final fee = params.calculateFee(284).toInt(); + final fee = params.calculateFee(284); return FeeObject( numberOfBlocksFast: 2, @@ -140,7 +146,11 @@ class CardanoWallet extends Bip39Wallet { slow: fee, ); } catch (e, s) { - Logging.instance.e("Error getting fees in cardano_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error getting fees in cardano_wallet.dart: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -181,39 +191,45 @@ class CardanoWallet extends Bip39Wallet { } final bip32 = CardanoIcarusBip32.fromSeed( - CardanoIcarusSeedGenerator(await getMnemonic()).generate()); + CardanoIcarusSeedGenerator(await getMnemonic()).generate(), + ); final spend = bip32.derivePath("1852'/1815'/0'/0/0"); final privateKey = AdaPrivateKey.fromBytes(spend.privateKey.raw); // Calculate fees with example tx final exampleFee = ADAHelper.toLovelaces("0.10"); final change = TransactionOutput( - address: ADABaseAddress((await getCurrentReceivingAddress())!.value), - amount: Value(coin: totalBalance - (txData.amount!.raw))); + address: ADABaseAddress((await getCurrentReceivingAddress())!.value), + amount: Value(coin: totalBalance - (txData.amount!.raw)), + ); final body = TransactionBody( - inputs: listOfUtxosToBeUsed - .map((e) => TransactionInput( - transactionId: TransactionHash.fromHex(e.txHash), - index: e.outputIndex)) - .toList(), + inputs: + listOfUtxosToBeUsed + .map( + (e) => TransactionInput( + transactionId: TransactionHash.fromHex(e.txHash), + index: e.outputIndex, + ), + ) + .toList(), outputs: [ change, TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), - amount: Value(coin: txData.amount!.raw - exampleFee)) + address: ADABaseAddress(txData.recipients!.first.address), + amount: Value(coin: txData.amount!.raw - exampleFee), + ), ], fee: exampleFee, ); final exampleTx = ADATransaction( body: body, witnessSet: TransactionWitnessSet( - vKeys: [ - privateKey.createSignatureWitness(body.toHash().data), - ], + vKeys: [privateKey.createSignatureWitness(body.toHash().data)], ), ); - final params = await blockfrostProvider! - .request(BlockfrostRequestLatestEpochProtocolParameters()); + final params = await blockfrostProvider!.request( + BlockfrostRequestLatestEpochProtocolParameters(), + ); final fee = params.calculateFee(exampleTx.size); // Check if we are sending all balance, which means no change and only one output for recipient. @@ -244,7 +260,8 @@ class CardanoWallet extends Bip39Wallet { if (totalBalance - (txData.amount!.raw + fee) < ADAHelper.toLovelaces("1")) { throw Exception( - "Not enough balance for change. By network rules, please either send all balance or leave at least 1 ADA change."); + "Not enough balance for change. By network rules, please either send all balance or leave at least 1 ADA change.", + ); } return txData.copyWith( @@ -255,7 +272,11 @@ class CardanoWallet extends Bip39Wallet { ); } } catch (e, s) { - Logging.instance.e("$runtimeType Cardano prepareSend failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType Cardano prepareSend failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -293,44 +314,51 @@ class CardanoWallet extends Bip39Wallet { } final bip32 = CardanoIcarusBip32.fromSeed( - CardanoIcarusSeedGenerator(await getMnemonic()).generate()); + CardanoIcarusSeedGenerator(await getMnemonic()).generate(), + ); final spend = bip32.derivePath("1852'/1815'/0'/0/0"); final privateKey = AdaPrivateKey.fromBytes(spend.privateKey.raw); final change = TransactionOutput( - address: ADABaseAddress((await getCurrentReceivingAddress())!.value), - amount: Value( - coin: totalUtxoAmount - (txData.amount!.raw + txData.fee!.raw))); + address: ADABaseAddress((await getCurrentReceivingAddress())!.value), + amount: Value( + coin: totalUtxoAmount - (txData.amount!.raw + txData.fee!.raw), + ), + ); List outputs = []; if (totalBalance == (txData.amount!.raw + txData.fee!.raw)) { outputs = [ TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), - amount: Value(coin: txData.amount!.raw)) + address: ADABaseAddress(txData.recipients!.first.address), + amount: Value(coin: txData.amount!.raw), + ), ]; } else { outputs = [ change, TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), - amount: Value(coin: txData.amount!.raw)) + address: ADABaseAddress(txData.recipients!.first.address), + amount: Value(coin: txData.amount!.raw), + ), ]; } final body = TransactionBody( - inputs: listOfUtxosToBeUsed - .map((e) => TransactionInput( - transactionId: TransactionHash.fromHex(e.txHash), - index: e.outputIndex)) - .toList(), + inputs: + listOfUtxosToBeUsed + .map( + (e) => TransactionInput( + transactionId: TransactionHash.fromHex(e.txHash), + index: e.outputIndex, + ), + ) + .toList(), outputs: outputs, fee: txData.fee!.raw, ); final tx = ADATransaction( body: body, witnessSet: TransactionWitnessSet( - vKeys: [ - privateKey.createSignatureWitness(body.toHash().data), - ], + vKeys: [privateKey.createSignatureWitness(body.toHash().data)], ), ); @@ -339,11 +367,13 @@ class CardanoWallet extends Bip39Wallet { transactionCborBytes: tx.serialize(), ), ); - return txData.copyWith( - txid: sentTx, - ); + return txData.copyWith(txid: sentTx); } catch (e, s) { - Logging.instance.e("$runtimeType Cardano confirmSend failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType Cardano confirmSend failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -410,7 +440,11 @@ class CardanoWallet extends Bip39Wallet { await info.updateBalance(newBalance: balance, isar: mainDB.isar); } catch (e, s) { - Logging.instance.e("Error getting balance in cardano_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error getting balance in cardano_wallet.dart: ", + error: e, + stackTrace: s, + ); } } @@ -428,7 +462,11 @@ class CardanoWallet extends Bip39Wallet { isar: mainDB.isar, ); } catch (e, s) { - Logging.instance.e("Error updating transactions in cardano_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error updating transactions in cardano_wallet.dart: ", + error: e, + stackTrace: s, + ); } } @@ -446,14 +484,13 @@ class CardanoWallet extends Bip39Wallet { final txsList = await blockfrostProvider!.request( BlockfrostRequestAddressTransactions( - ADAAddress.fromAddress( - currentAddr, - ), + ADAAddress.fromAddress(currentAddr), ), ); - final parsedTxsList = - List>.empty(growable: true); + final parsedTxsList = List>.empty( + growable: true, + ); for (final tx in txsList) { final txInfo = await blockfrostProvider!.request( @@ -525,10 +562,11 @@ class CardanoWallet extends Bip39Wallet { type: txType, subType: isar.TransactionSubType.none, amount: amount, - amountString: Amount( - rawValue: BigInt.from(amount), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + amountString: + Amount( + rawValue: BigInt.from(amount), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), fee: int.parse(txInfo.fees), height: txInfo.blockHeight, isCancelled: false, @@ -548,9 +586,10 @@ class CardanoWallet extends Bip39Wallet { derivationIndex: 0, derivationPath: DerivationPath()..value = _addressDerivationPath, type: AddressType.cardanoShelley, - subType: txType == isar.TransactionType.outgoing - ? AddressSubType.unknown - : AddressSubType.receiving, + subType: + txType == isar.TransactionType.outgoing + ? AddressSubType.unknown + : AddressSubType.receiving, ); parsedTxsList.add(Tuple2(transaction, txAddress)); @@ -560,7 +599,11 @@ class CardanoWallet extends Bip39Wallet { } on NodeTorMismatchConfigException { rethrow; } catch (e, s) { - Logging.instance.e("Error updating transactions in cardano_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error updating transactions in cardano_wallet.dart: ", + error: e, + stackTrace: s, + ); } } @@ -576,10 +619,7 @@ class CardanoWallet extends Bip39Wallet { final client = HttpClient(); if (prefs.useTor) { final proxyInfo = TorService.sharedInstance.getProxyInfo(); - final proxySettings = ProxySettings( - proxyInfo.host, - proxyInfo.port, - ); + final proxySettings = ProxySettings(proxyInfo.host, proxyInfo.port); SocksTCPClient.assignToHttpClient(client, [proxySettings]); } blockfrostProvider = CustomBlockForestProvider( diff --git a/lib/wallets/wallet/impl/dash_wallet.dart b/lib/wallets/wallet/impl/dash_wallet.dart index 59fdaa037..f9a90d5b8 100644 --- a/lib/wallets/wallet/impl/dash_wallet.dart +++ b/lib/wallets/wallet/impl/dash_wallet.dart @@ -36,17 +36,18 @@ class DashWallet extends Bip39HDWallet @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } @@ -59,30 +60,34 @@ class DashWallet extends Bip39HDWallet await fetchAddressesForElectrumXScan(); // Separate receiving and change addresses. - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); // Remove duplicates. final allAddressesSet = {...receivingAddresses, ...changeAddresses}; // Fetch history from ElectrumX. - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); // Only parse new txs (not in db yet). final List> allTransactions = []; for (final txHash in allTxHashes) { // Check for duplicates by searching for tx by tx_hash in db. - final storedTx = await mainDB.isar.transactionV2s - .where() - .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); if (storedTx == null || storedTx.height == null || @@ -95,8 +100,9 @@ class DashWallet extends Bip39HDWallet ); // Only tx to list once. - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -246,7 +252,8 @@ class DashWallet extends Bip39HDWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -263,7 +270,7 @@ class DashWallet extends Bip39HDWallet @override Future<({String? blockedReason, bool blocked, String? utxoLabel})> - checkBlockUTXO( + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map jsonTX, @@ -296,18 +303,22 @@ class DashWallet extends Bip39HDWallet } @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((181 * inputCount) + (34 * outputCount) + 10) * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } } diff --git a/lib/wallets/wallet/impl/dogecoin_wallet.dart b/lib/wallets/wallet/impl/dogecoin_wallet.dart index e9046f959..da24c5a9d 100644 --- a/lib/wallets/wallet/impl/dogecoin_wallet.dart +++ b/lib/wallets/wallet/impl/dogecoin_wallet.dart @@ -38,17 +38,18 @@ class DogecoinWallet @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } @@ -61,30 +62,34 @@ class DogecoinWallet await fetchAddressesForElectrumXScan(); // Separate receiving and change addresses. - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); // Remove duplicates. final allAddressesSet = {...receivingAddresses, ...changeAddresses}; // Fetch history from ElectrumX. - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); // Only parse new txs (not in db yet). final List> allTransactions = []; for (final txHash in allTxHashes) { // Check for duplicates by searching for tx by tx_hash in db. - final storedTx = await mainDB.isar.transactionV2s - .where() - .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); if (storedTx == null || storedTx.height == null || @@ -97,8 +102,9 @@ class DogecoinWallet ); // Only tx to list once. - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -249,7 +255,8 @@ class DogecoinWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -266,7 +273,7 @@ class DogecoinWallet @override Future<({String? blockedReason, bool blocked, String? utxoLabel})> - checkBlockUTXO( + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map jsonTX, @@ -287,7 +294,8 @@ class DogecoinWallet // https://en.bitcoin.it/wiki/BIP_0047#Sending if (bytes.length == 80 && bytes.first == 1) { blocked = true; - blockedReason = "Paynym notification output. Incautious " + blockedReason = + "Paynym notification output. Incautious " "handling of outputs from notification transactions " "may cause unintended loss of privacy."; break; @@ -299,18 +307,22 @@ class DogecoinWallet } @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((181 * inputCount) + (34 * outputCount) + 10) * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } } diff --git a/lib/wallets/wallet/impl/ecash_wallet.dart b/lib/wallets/wallet/impl/ecash_wallet.dart index a8741ba21..aacdc4f31 100644 --- a/lib/wallets/wallet/impl/ecash_wallet.dart +++ b/lib/wallets/wallet/impl/ecash_wallet.dart @@ -34,46 +34,37 @@ class EcashWallet extends Bip39HDWallet EcashWallet(CryptoCurrencyNetwork network) : super(Ecash(network) as T); @override - FilterOperation? get changeAddressFilterOperation => FilterGroup.and( - [ - ...standardChangeAddressFilters, - const ObjectFilter( - property: "derivationPath", - filter: FilterCondition.startsWith( - property: "value", - value: "m/44'/899", - ), - ), - ], - ); + FilterOperation? get changeAddressFilterOperation => FilterGroup.and([ + ...standardChangeAddressFilters, + const ObjectFilter( + property: "derivationPath", + filter: FilterCondition.startsWith(property: "value", value: "m/44'/899"), + ), + ]); @override - FilterOperation? get receivingAddressFilterOperation => FilterGroup.and( - [ - ...standardReceivingAddressFilters, - const ObjectFilter( - property: "derivationPath", - filter: FilterCondition.startsWith( - property: "value", - value: "m/44'/899", - ), - ), - ], - ); + FilterOperation? get receivingAddressFilterOperation => FilterGroup.and([ + ...standardReceivingAddressFilters, + const ObjectFilter( + property: "derivationPath", + filter: FilterCondition.startsWith(property: "value", value: "m/44'/899"), + ), + ]); // =========================================================================== @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .typeEqualTo(AddressType.nonWallet) - .and() - .not() - .subTypeEqualTo(AddressSubType.nonWallet) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .typeEqualTo(AddressType.nonWallet) + .and() + .not() + .subTypeEqualTo(AddressSubType.nonWallet) + .findAll(); return allAddresses; } @@ -96,28 +87,32 @@ class EcashWallet extends Bip39HDWallet final List
allAddressesOld = await fetchAddressesForElectrumXScan(); - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => convertAddressString(e.value)) + .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => convertAddressString(e.value)) + .toSet(); final allAddressesSet = {...receivingAddresses, ...changeAddresses}; - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); final List> allTransactions = []; for (final txHash in allTxHashes) { - final storedTx = await mainDB.isar.transactionV2s - .where() - .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); if (storedTx == null || storedTx.height == null || @@ -129,8 +124,9 @@ class EcashWallet extends Bip39HDWallet ); // check for duplicates before adding to list - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -288,7 +284,8 @@ class EcashWallet extends Bip39HDWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -304,12 +301,8 @@ class EcashWallet extends Bip39HDWallet } @override - Future< - ({ - String? blockedReason, - bool blocked, - String? utxoLabel, - })> checkBlockUTXO( + Future<({String? blockedReason, bool blocked, String? utxoLabel})> + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map jsonTX, @@ -321,8 +314,9 @@ class EcashWallet extends Bip39HDWallet if (scriptPubKeyHex != null) { // check for cash tokens try { - final ctOutput = - cash_tokens.unwrap_spk(scriptPubKeyHex.toUint8ListFromHex); + final ctOutput = cash_tokens.unwrap_spk( + scriptPubKeyHex.toUint8ListFromHex, + ); if (ctOutput.token_data != null) { // found a token! blocked = true; @@ -350,19 +344,23 @@ class EcashWallet extends Bip39HDWallet // TODO: correct formula for ecash? @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((181 * inputCount) + (34 * outputCount) + 10) * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: info.coin.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } @override diff --git a/lib/wallets/wallet/impl/epiccash_wallet.dart b/lib/wallets/wallet/impl/epiccash_wallet.dart index 10238cef6..215f41917 100644 --- a/lib/wallets/wallet/impl/epiccash_wallet.dart +++ b/lib/wallets/wallet/impl/epiccash_wallet.dart @@ -53,15 +53,17 @@ class EpiccashWallet extends Bip39Wallet { final int lastScannedBlock = info.epicData?.lastScannedBlock ?? 0; final _chainHeight = await chainHeight; final double restorePercent = lastScannedBlock / _chainHeight; - GlobalEventBus.instance - .fire(RefreshPercentChangedEvent(highestPercent, walletId)); + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercent, walletId), + ); if (restorePercent > highestPercent) { highestPercent = restorePercent; } final int blocksRemaining = _chainHeight - lastScannedBlock; - GlobalEventBus.instance - .fire(BlocksRemainingEvent(blocksRemaining, walletId)); + GlobalEventBus.instance.fire( + BlocksRemainingEvent(blocksRemaining, walletId), + ); return restorePercent < 0 ? 0.0 : restorePercent; } @@ -84,17 +86,14 @@ class EpiccashWallet extends Bip39Wallet { Future cancelPendingTransactionAndPost(String txSlateId) async { try { _hackedCheckTorNodePrefs(); - final String wallet = (await secureStorageInterface.read( - key: '${walletId}_wallet', - ))!; + final String wallet = + (await secureStorageInterface.read(key: '${walletId}_wallet'))!; final result = await epiccash.LibEpiccash.cancelTransaction( wallet: wallet, transactionId: txSlateId, ); - Logging.instance.d( - "cancel $txSlateId result: $result", - ); + Logging.instance.d("cancel $txSlateId result: $result"); return result; } catch (e, s) { Logging.instance.e("", error: e, stackTrace: s); @@ -154,8 +153,10 @@ class EpiccashWallet extends Bip39Wallet { config["chain"] = "mainnet"; config["account"] = "default"; config["api_listen_port"] = port; - config["api_listen_interface"] = - nodeApiAddress.replaceFirst(uri.scheme, ""); + config["api_listen_interface"] = nodeApiAddress.replaceFirst( + uri.scheme, + "", + ); final String stringConfig = jsonEncode(config); return stringConfig; } @@ -219,12 +220,14 @@ class EpiccashWallet extends Bip39Wallet { } Future< - ({ - double awaitingFinalization, - double pending, - double spendable, - double total - })> _allWalletBalances() async { + ({ + double awaitingFinalization, + double pending, + double spendable, + double total, + }) + > + _allWalletBalances() async { _hackedCheckTorNodePrefs(); final wallet = await secureStorageInterface.read(key: '${walletId}_wallet'); const refreshFromNode = 0; @@ -243,9 +246,7 @@ class EpiccashWallet extends Bip39Wallet { try { final uri = Uri.parse('wss://$host:$port'); - channel = WebSocketChannel.connect( - uri, - ); + channel = WebSocketChannel.connect(uri); await channel.ready; @@ -280,9 +281,7 @@ class EpiccashWallet extends Bip39Wallet { "to": to, }; await info.updateExtraEpiccashWalletInfo( - epicData: info.epicData!.copyWith( - slatesToCommits: slatesToCommits, - ), + epicData: info.epicData!.copyWith(slatesToCommits: slatesToCommits), isar: mainDB.isar, ); return true; @@ -305,9 +304,7 @@ class EpiccashWallet extends Bip39Wallet { } /// Only index 0 is currently used in stack wallet. - Future
_generateAndStoreReceivingAddressForIndex( - int index, - ) async { + Future
_generateAndStoreReceivingAddressForIndex(int index) async { // Since only 0 is a valid index in stack wallet at this time, lets just // throw is not zero if (index != 0) { @@ -338,9 +335,7 @@ class EpiccashWallet extends Bip39Wallet { epicboxConfig: epicboxConfig.toString(), ); - Logging.instance.d( - "WALLET_ADDRESS_IS $walletAddress", - ); + Logging.instance.d("WALLET_ADDRESS_IS $walletAddress"); final address = Address( walletId: walletId, @@ -359,8 +354,9 @@ class EpiccashWallet extends Bip39Wallet { try { //First stop the current listener epiccash.LibEpiccash.stopEpicboxListener(); - final wallet = - await secureStorageInterface.read(key: '${walletId}_wallet'); + final wallet = await secureStorageInterface.read( + key: '${walletId}_wallet', + ); // max number of blocks to scan per loop iteration const scanChunkSize = 10000; @@ -387,9 +383,7 @@ class EpiccashWallet extends Bip39Wallet { // update local cache await info.updateExtraEpiccashWalletInfo( - epicData: info.epicData!.copyWith( - lastScannedBlock: nextScannedBlock, - ), + epicData: info.epicData!.copyWith(lastScannedBlock: nextScannedBlock), isar: mainDB.isar, ); @@ -470,8 +464,9 @@ class EpiccashWallet extends Bip39Wallet { @override Future init({bool? isRestore}) async { if (isRestore != true) { - String? encodedWallet = - await secureStorageInterface.read(key: "${walletId}_wallet"); + String? encodedWallet = await secureStorageInterface.read( + key: "${walletId}_wallet", + ); // check if should create a new wallet if (encodedWallet == null) { @@ -543,8 +538,9 @@ class EpiccashWallet extends Bip39Wallet { ); final config = await _getRealConfig(); - final password = - await secureStorageInterface.read(key: '${walletId}_password'); + final password = await secureStorageInterface.read( + key: '${walletId}_password', + ); final walletOpen = await epiccash.LibEpiccash.openWallet( config: config, @@ -558,8 +554,11 @@ class EpiccashWallet extends Bip39Wallet { await updateNode(); } catch (e, s) { // do nothing, still allow user into wallet - Logging.instance - .w("$runtimeType init() failed: ", error: e, stackTrace: s); + Logging.instance.w( + "$runtimeType init() failed: ", + error: e, + stackTrace: s, + ); } } } @@ -571,8 +570,9 @@ class EpiccashWallet extends Bip39Wallet { Future confirmSend({required TxData txData}) async { try { _hackedCheckTorNodePrefs(); - final wallet = - await secureStorageInterface.read(key: '${walletId}_wallet'); + final wallet = await secureStorageInterface.read( + key: '${walletId}_wallet', + ); final EpicBoxConfigModel epicboxConfig = await getEpicBoxConfig(); // TODO determine whether it is worth sending change to a change address. @@ -581,9 +581,7 @@ class EpiccashWallet extends Bip39Wallet { if (!receiverAddress.startsWith("http://") || !receiverAddress.startsWith("https://")) { - final bool isEpicboxConnected = await _testEpicboxServer( - epicboxConfig, - ); + final bool isEpicboxConnected = await _testEpicboxServer(epicboxConfig); if (!isEpicboxConnected) { throw Exception("Failed to send TX : Unable to reach epicbox server"); } @@ -618,9 +616,7 @@ class EpiccashWallet extends Bip39Wallet { txAddressInfo['to'] = txData.recipients!.first.address; await _putSendToAddresses(transaction, txAddressInfo); - return txData.copyWith( - txid: transaction.slateId, - ); + return txData.copyWith(txid: transaction.slateId); } catch (e, s) { Logging.instance.e("Epic cash confirmSend: ", error: e, stackTrace: s); rethrow; @@ -658,10 +654,7 @@ class EpiccashWallet extends Bip39Wallet { ); } - return txData.copyWith( - recipients: [recipient], - fee: feeAmount, - ); + return txData.copyWith(recipients: [recipient], fee: feeAmount); } catch (e, s) { Logging.instance.e("Epic cash prepareSend", error: e, stackTrace: s); rethrow; @@ -898,10 +891,7 @@ class EpiccashWallet extends Bip39Wallet { ), ); - await info.updateBalance( - newBalance: balance, - isar: mainDB.isar, - ); + await info.updateBalance(newBalance: balance, isar: mainDB.isar); } catch (e, s) { Logging.instance.w( "Epic cash wallet failed to update balance: ", @@ -915,20 +905,22 @@ class EpiccashWallet extends Bip39Wallet { Future updateTransactions() async { try { _hackedCheckTorNodePrefs(); - final wallet = - await secureStorageInterface.read(key: '${walletId}_wallet'); + final wallet = await secureStorageInterface.read( + key: '${walletId}_wallet', + ); const refreshFromNode = 1; - final myAddresses = await mainDB - .getAddresses(walletId) - .filter() - .typeEqualTo(AddressType.mimbleWimble) - .and() - .subTypeEqualTo(AddressSubType.receiving) - .and() - .valueIsNotEmpty() - .valueProperty() - .findAll(); + final myAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .typeEqualTo(AddressType.mimbleWimble) + .and() + .subTypeEqualTo(AddressSubType.receiving) + .and() + .valueIsNotEmpty() + .valueProperty() + .findAll(); final myAddressesSet = myAddresses.toSet(); final transactions = await epiccash.LibEpiccash.getTransactions( @@ -943,7 +935,7 @@ class EpiccashWallet extends Bip39Wallet { for (final tx in transactions) { final isIncoming = tx.txType == epic_models.TransactionType.TxReceived || - tx.txType == epic_models.TransactionType.TxReceivedCancelled; + tx.txType == epic_models.TransactionType.TxReceivedCancelled; final slateId = tx.txSlateId; final commitId = slatesToCommits[slateId]?['commitId'] as String?; final numberOfMessages = tx.messages?.messages.length; @@ -964,9 +956,7 @@ class EpiccashWallet extends Bip39Wallet { OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: credit.toString(), - addresses: [ - if (addressFrom != null) addressFrom, - ], + addresses: [if (addressFrom != null) addressFrom], walletOwns: true, ); final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( @@ -1010,11 +1000,12 @@ class EpiccashWallet extends Bip39Wallet { "onChainNote": onChainNote, "isCancelled": tx.txType == epic_models.TransactionType.TxSentCancelled || - tx.txType == epic_models.TransactionType.TxReceivedCancelled, - "overrideFee": Amount( - rawValue: BigInt.from(fee), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + tx.txType == epic_models.TransactionType.TxReceivedCancelled, + "overrideFee": + Amount( + rawValue: BigInt.from(fee), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), }; final txn = TransactionV2( @@ -1092,11 +1083,7 @@ class EpiccashWallet extends Bip39Wallet { ) != null; } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); return false; } } @@ -1105,8 +1092,9 @@ class EpiccashWallet extends Bip39Wallet { Future updateChainHeight() async { _hackedCheckTorNodePrefs(); final config = await _getRealConfig(); - final latestHeight = - await epiccash.LibEpiccash.getChainHeight(config: config); + final latestHeight = await epiccash.LibEpiccash.getChainHeight( + config: config, + ); await info.updateCachedChainHeight( newHeight: latestHeight, isar: mainDB.isar, @@ -1114,7 +1102,7 @@ class EpiccashWallet extends Bip39Wallet { } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { _hackedCheckTorNodePrefs(); // setting ifErrorEstimateFee doesn't do anything as its not used in the nativeFee function????? final int currentFee = await _nativeFee( @@ -1135,9 +1123,9 @@ class EpiccashWallet extends Bip39Wallet { numberOfBlocksFast: 10, numberOfBlocksAverage: 10, numberOfBlocksSlow: 10, - fast: 1, - medium: 1, - slow: 1, + fast: BigInt.one, + medium: BigInt.one, + slow: BigInt.one, ); } @@ -1202,10 +1190,7 @@ Future deleteEpicWallet({ return "Tried to delete non existent epic wallet file with walletId=$walletId"; } else { try { - return epiccash.LibEpiccash.deleteWallet( - wallet: wallet, - config: config!, - ); + return epiccash.LibEpiccash.deleteWallet(wallet: wallet, config: config!); } catch (e, s) { Logging.instance.e("$e\n$s", error: e, stackTrace: s); return "deleteEpicWallet($walletId) failed..."; diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index f10109ff9..db4c2fa50 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -58,7 +58,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { return web3.Web3Client(node.host, client); } - Amount estimateEthFee(int feeRate, int gasLimit, int decimals) { + Amount estimateEthFee(BigInt feeRate, int gasLimit, int decimals) { final gweiAmount = feeRate.toDecimal() / (Decimal.ten.pow(9).toDecimal()); final fee = gasLimit.toDecimal() * @@ -188,7 +188,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { return estimateEthFee( feeRate, (cryptoCurrency as Ethereum).gasLimit, @@ -197,7 +197,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { } @override - Future get fees => EthereumAPI.getFees(); + Future get fees => EthereumAPI.getFees(); @override Future pingCheck() async { @@ -423,8 +423,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { @override Future prepareSend({required TxData txData}) async { - final int - rate; // TODO: use BigInt for feeObject whenever FeeObject gets redone + final BigInt rate; final feeObject = await fees; switch (txData.feeRateType!) { case FeeRateType.fast: @@ -489,7 +488,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final tx = web3.Transaction( to: web3.EthereumAddress.fromHex(address), - gasPrice: web3.EtherAmount.fromInt(web3.EtherUnit.wei, rate), + gasPrice: web3.EtherAmount.fromBigInt(web3.EtherUnit.wei, rate), maxGas: (cryptoCurrency as Ethereum).gasLimit, value: web3.EtherAmount.inWei(amount.raw), nonce: nonce, @@ -499,7 +498,7 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { nonce: tx.nonce, web3dartTransaction: tx, fee: feeEstimate, - feeInWei: BigInt.from(rate), + feeInWei: rate, chainId: (await client.getChainId()), ); } diff --git a/lib/wallets/wallet/impl/firo_wallet.dart b/lib/wallets/wallet/impl/firo_wallet.dart index aed72a33a..75d7290a9 100644 --- a/lib/wallets/wallet/impl/firo_wallet.dart +++ b/lib/wallets/wallet/impl/firo_wallet.dart @@ -60,9 +60,7 @@ class FiroWallet extends Bip39HDWallet if (txData.tempTx != null) { await mainDB.updateOrPutTransactionV2s([txData.tempTx!]); _unconfirmedTxids.add(txData.tempTx!.txid); - Logging.instance.d( - "Added firo unconfirmed: ${txData.tempTx!.txid}", - ); + Logging.instance.d("Added firo unconfirmed: ${txData.tempTx!.txid}"); } return txData; } @@ -72,36 +70,41 @@ class FiroWallet extends Bip39HDWallet final List
allAddressesOld = await fetchAddressesForElectrumXScan(); - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => convertAddressString(e.value)) + .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => convertAddressString(e.value)) - .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => convertAddressString(e.value)) + .toSet(); final allAddressesSet = {...receivingAddresses, ...changeAddresses}; - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); - final sparkCoins = await mainDB.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .findAll(); + final sparkCoins = + await mainDB.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .findAll(); final List> allTransactions = []; // some lelantus transactions aren't fetched via wallet addresses so they // will never show as confirmed in the gui. - final unconfirmedTransactions = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .heightIsNull() - .findAll(); + final unconfirmedTransactions = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .heightIsNull() + .findAll(); for (final tx in unconfirmedTransactions) { final txn = await electrumXCachedClient.getTransaction( txHash: tx.txid, @@ -113,10 +116,7 @@ class FiroWallet extends Bip39HDWallet if (height != null) { // tx was mined // add to allTxHashes - final info = { - "tx_hash": tx.txid, - "height": height, - }; + final info = {"tx_hash": tx.txid, "height": height}; allTxHashes.add(info); } } @@ -126,10 +126,7 @@ class FiroWallet extends Bip39HDWallet sparkTxids.add(coin.txHash); // check for duplicates before adding to list if (allTxHashes.indexWhere((e) => e["tx_hash"] == coin.txHash) == -1) { - final info = { - "tx_hash": coin.txHash, - "height": coin.height, - }; + final info = {"tx_hash": coin.txHash, "height": coin.height}; allTxHashes.add(info); } } @@ -138,9 +135,7 @@ class FiroWallet extends Bip39HDWallet for (final txid in missing.map((e) => e.txid).toSet()) { // check for duplicates before adding to list if (allTxHashes.indexWhere((e) => e["tx_hash"] == txid) == -1) { - final info = { - "tx_hash": txid, - }; + final info = {"tx_hash": txid}; allTxHashes.add(info); } } @@ -148,12 +143,13 @@ class FiroWallet extends Bip39HDWallet final currentHeight = await chainHeight; for (final txHash in allTxHashes) { - final storedTx = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .txidEqualTo(txHash["tx_hash"] as String) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(txHash["tx_hash"] as String) + .findFirst(); if (storedTx?.isConfirmed( currentHeight, @@ -180,8 +176,9 @@ class FiroWallet extends Bip39HDWallet } // check for duplicates before adding to list - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] ??= txHash["height"]; allTransactions.add(tx); @@ -290,17 +287,19 @@ class FiroWallet extends Bip39HDWallet if (output.addresses.isEmpty && output.scriptPubKeyHex.length >= 488) { // likely spark related - final opByte = output.scriptPubKeyHex - .substring(0, 2) - .toUint8ListFromHex - .first; + final opByte = + output.scriptPubKeyHex + .substring(0, 2) + .toUint8ListFromHex + .first; if (opByte == OP_SPARKMINT || opByte == OP_SPARKSMINT) { final serCoin = base64Encode( output.scriptPubKeyHex.substring(2, 488).toUint8ListFromHex, ); - final coin = sparkCoinsInvolvedReceived - .where((e) => e.serializedCoinB64!.startsWith(serCoin)) - .firstOrNull; + final coin = + sparkCoinsInvolvedReceived + .where((e) => e.serializedCoinB64!.startsWith(serCoin)) + .firstOrNull; if (coin == null) { // not ours @@ -308,9 +307,7 @@ class FiroWallet extends Bip39HDWallet output = output.copyWith( walletOwns: true, valueStringSats: coin.value.toString(), - addresses: [ - coin.address, - ], + addresses: [coin.address], ); } } @@ -395,11 +392,10 @@ class FiroWallet extends Bip39HDWallet txid: txData["txid"] as String, network: cryptoCurrency.network, ); - spentSparkCoins = sparkCoinsInvolvedSpent - .where( - (e) => tags.contains(e.lTagHash), - ) - .toList(); + spentSparkCoins = + sparkCoinsInvolvedSpent + .where((e) => tags.contains(e.lTagHash)) + .toList(); } else if (isSparkSpend) { parseAnonFees(); } else if (isSparkMint) { @@ -483,10 +479,11 @@ class FiroWallet extends Bip39HDWallet if (usedCoins.isNotEmpty) { input = input.copyWith( addresses: usedCoins.map((e) => e.address).toList(), - valueStringSats: usedCoins - .map((e) => e.value) - .reduce((value, element) => value += element) - .toString(), + valueStringSats: + usedCoins + .map((e) => e.value) + .reduce((value, element) => value += element) + .toString(), walletOwns: true, ); wasSentFromThisWallet = true; @@ -497,10 +494,11 @@ class FiroWallet extends Bip39HDWallet spentSparkCoins.isNotEmpty) { input = input.copyWith( addresses: spentSparkCoins.map((e) => e.address).toList(), - valueStringSats: spentSparkCoins - .map((e) => e.value) - .fold(BigInt.zero, (p, e) => p + e) - .toString(), + valueStringSats: + spentSparkCoins + .map((e) => e.value) + .fold(BigInt.zero, (p, e) => p + e) + .toString(), walletOwns: true, ); wasSentFromThisWallet = true; @@ -570,11 +568,7 @@ class FiroWallet extends Bip39HDWallet String? otherData; if (anonFees != null) { - otherData = jsonEncode( - { - "overrideFee": anonFees!.toJsonString(), - }, - ); + otherData = jsonEncode({"overrideFee": anonFees!.toJsonString()}); } final tx = TransactionV2( @@ -584,7 +578,8 @@ class FiroWallet extends Bip39HDWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -613,12 +608,8 @@ class FiroWallet extends Bip39HDWallet } @override - Future< - ({ - String? blockedReason, - bool blocked, - String? utxoLabel, - })> checkBlockUTXO( + Future<({String? blockedReason, bool blocked, String? utxoLabel})> + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map? jsonTX, @@ -631,7 +622,8 @@ class FiroWallet extends Bip39HDWallet if (jsonUTXO["value"] is int) { // TODO: [prio=high] use special electrumx call to verify the 1000 Firo output is masternode // electrumx call should exist now. Unsure if it works though - blocked = Amount.fromDecimal( + blocked = + Amount.fromDecimal( Decimal.fromInt( 1000, // 1000 firo output is a possible master node ), @@ -654,7 +646,8 @@ class FiroWallet extends Bip39HDWallet } if (blocked) { - blockedReason = "Possible masternode collateral. " + blockedReason = + "Possible masternode collateral. " "Unlock and spend at your own risk."; label = "Possible masternode collateral"; } @@ -707,13 +700,11 @@ class FiroWallet extends Bip39HDWallet final List> lelantusFutures = []; final enableLelantusScanning = info.otherData[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false; + false; if (enableLelantusScanning) { latestSetId = await electrumXClient.getLelantusLatestCoinId(); lelantusFutures.add( - electrumXCachedClient.getUsedCoinSerials( - cryptoCurrency: info.coin, - ), + electrumXCachedClient.getUsedCoinSerials(cryptoCurrency: info.coin), ); lelantusFutures.add(getSetDataMap(latestSetId)); } @@ -733,9 +724,9 @@ class FiroWallet extends Bip39HDWallet } final sparkUsedCoinTagsFuture = FiroCacheCoordinator.runFetchAndUpdateSparkUsedCoinTags( - electrumXClient, - cryptoCurrency.network, - ); + electrumXClient, + cryptoCurrency.network, + ); // receiving addresses Logging.instance.i("checking receiving addresses..."); @@ -745,17 +736,8 @@ class FiroWallet extends Bip39HDWallet for (final type in cryptoCurrency.supportedDerivationPathTypes) { receiveFutures.add( canBatch - ? checkGapsBatched( - txCountBatchSize, - root, - type, - receiveChain, - ) - : checkGapsLinearly( - root, - type, - receiveChain, - ), + ? checkGapsBatched(txCountBatchSize, root, type, receiveChain) + : checkGapsLinearly(root, type, receiveChain), ); } @@ -764,17 +746,8 @@ class FiroWallet extends Bip39HDWallet for (final type in cryptoCurrency.supportedDerivationPathTypes) { changeFutures.add( canBatch - ? checkGapsBatched( - txCountBatchSize, - root, - type, - changeChain, - ) - : checkGapsLinearly( - root, - type, - changeChain, - ), + ? checkGapsBatched(txCountBatchSize, root, type, changeChain) + : checkGapsLinearly(root, type, changeChain), ); } @@ -834,10 +807,7 @@ class FiroWallet extends Bip39HDWallet await mainDB.updateOrPutAddresses(addressesToStore); - await Future.wait([ - updateTransactions(), - updateUTXOs(), - ]); + await Future.wait([updateTransactions(), updateUTXOs()]); final List> futures = []; if (enableLelantusScanning) { @@ -865,9 +835,7 @@ class FiroWallet extends Bip39HDWallet usedSerialNumbers: usedSerialsSet!, setDataMap: setDataMap!, ), - recoverSparkWallet( - latestSparkCoinId: latestSparkCoinId, - ), + recoverSparkWallet(latestSparkCoinId: latestSparkCoinId), ]); } else { if (enableLelantusScanning) { @@ -877,9 +845,7 @@ class FiroWallet extends Bip39HDWallet setDataMap: setDataMap!, ); } - await recoverSparkWallet( - latestSparkCoinId: latestSparkCoinId, - ); + await recoverSparkWallet(latestSparkCoinId: latestSparkCoinId); } }); @@ -900,19 +866,23 @@ class FiroWallet extends Bip39HDWallet } @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((181 * inputCount) + (34 * outputCount) + 10) * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } // =========================================================================== diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index 034056817..e72b8e633 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -44,17 +44,18 @@ class LitecoinWallet @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } @@ -67,14 +68,16 @@ class LitecoinWallet await fetchAddressesForElectrumXScan(); // Separate receiving and change addresses. - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); // Remove duplicates. final allAddressesSet = {...receivingAddresses, ...changeAddresses}; @@ -84,17 +87,19 @@ class LitecoinWallet ); // Fetch history from ElectrumX. - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); // Only parse new txs (not in db yet). final List> allTransactions = []; for (final txHash in allTxHashes) { // Check for duplicates by searching for tx by tx_hash in db. - final storedTx = await mainDB.isar.transactionV2s - .where() - .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); if (storedTx == null || storedTx.height == null || @@ -107,8 +112,9 @@ class LitecoinWallet ); // Only tx to list once. - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -248,12 +254,13 @@ class LitecoinWallet // Check for special Litecoin outputs like ordinals. if (outputs.isNotEmpty) { // may not catch every case but it is much quicker - final hasOrdinal = await mainDB.isar.ordinals - .where() - .filter() - .walletIdEqualTo(walletId) - .utxoTXIDEqualTo(txData["txid"] as String) - .isNotEmpty(); + final hasOrdinal = + await mainDB.isar.ordinals + .where() + .filter() + .walletIdEqualTo(walletId) + .utxoTXIDEqualTo(txData["txid"] as String) + .isNotEmpty(); if (hasOrdinal) { subType = TransactionSubType.ordinal; } @@ -307,7 +314,8 @@ class LitecoinWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -323,79 +331,84 @@ class LitecoinWallet } @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } -// -// @override -// Future coinSelection({required TxData txData}) async { -// final isCoinControl = txData.utxos != null; -// final isSendAll = txData.amount == info.cachedBalance.spendable; -// -// final utxos = -// txData.utxos?.toList() ?? await mainDB.getUTXOs(walletId).findAll(); -// -// final currentChainHeight = await chainHeight; -// final List spendableOutputs = []; -// int spendableSatoshiValue = 0; -// -// // Build list of spendable outputs and totaling their satoshi amount -// for (final utxo in utxos) { -// if (utxo.isBlocked == false && -// utxo.isConfirmed(currentChainHeight, cryptoCurrency.minConfirms) && -// utxo.used != true) { -// spendableOutputs.add(utxo); -// spendableSatoshiValue += utxo.value; -// } -// } -// -// if (isCoinControl && spendableOutputs.length < utxos.length) { -// throw ArgumentError("Attempted to use an unavailable utxo"); -// } -// -// if (spendableSatoshiValue < txData.amount!.raw.toInt()) { -// throw Exception("Insufficient balance"); -// } else if (spendableSatoshiValue == txData.amount!.raw.toInt() && -// !isSendAll) { -// throw Exception("Insufficient balance to pay transaction fee"); -// } -// -// if (isCoinControl) { -// } else { -// final selection = cs.coinSelection( -// spendableOutputs -// .map((e) => cs.InputModel( -// i: e.vout, -// txid: e.txid, -// value: e.value, -// address: e.address, -// )) -// .toList(), -// txData.recipients! -// .map((e) => cs.OutputModel( -// address: e.address, -// value: e.amount.raw.toInt(), -// )) -// .toList(), -// txData.feeRateAmount!, -// 10, // TODO: ??????????????????????????????? -// ); -// -// // .inputs and .outputs will be null if no solution was found -// if (selection.inputs!.isEmpty || selection.outputs!.isEmpty) { -// throw Exception("coin selection failed"); -// } -// } -// } + + // + // @override + // Future coinSelection({required TxData txData}) async { + // final isCoinControl = txData.utxos != null; + // final isSendAll = txData.amount == info.cachedBalance.spendable; + // + // final utxos = + // txData.utxos?.toList() ?? await mainDB.getUTXOs(walletId).findAll(); + // + // final currentChainHeight = await chainHeight; + // final List spendableOutputs = []; + // int spendableSatoshiValue = 0; + // + // // Build list of spendable outputs and totaling their satoshi amount + // for (final utxo in utxos) { + // if (utxo.isBlocked == false && + // utxo.isConfirmed(currentChainHeight, cryptoCurrency.minConfirms) && + // utxo.used != true) { + // spendableOutputs.add(utxo); + // spendableSatoshiValue += utxo.value; + // } + // } + // + // if (isCoinControl && spendableOutputs.length < utxos.length) { + // throw ArgumentError("Attempted to use an unavailable utxo"); + // } + // + // if (spendableSatoshiValue < txData.amount!.raw.toInt()) { + // throw Exception("Insufficient balance"); + // } else if (spendableSatoshiValue == txData.amount!.raw.toInt() && + // !isSendAll) { + // throw Exception("Insufficient balance to pay transaction fee"); + // } + // + // if (isCoinControl) { + // } else { + // final selection = cs.coinSelection( + // spendableOutputs + // .map((e) => cs.InputModel( + // i: e.vout, + // txid: e.txid, + // value: e.value, + // address: e.address, + // )) + // .toList(), + // txData.recipients! + // .map((e) => cs.OutputModel( + // address: e.address, + // value: e.amount.raw.toInt(), + // )) + // .toList(), + // txData.feeRateAmount!, + // 10, // TODO: ??????????????????????????????? + // ); + // + // // .inputs and .outputs will be null if no solution was found + // if (selection.inputs!.isEmpty || selection.outputs!.isEmpty) { + // throw Exception("coin selection failed"); + // } + // } + // } } diff --git a/lib/wallets/wallet/impl/monero_wallet.dart b/lib/wallets/wallet/impl/monero_wallet.dart index f1de036aa..933bc64ee 100644 --- a/lib/wallets/wallet/impl/monero_wallet.dart +++ b/lib/wallets/wallet/impl/monero_wallet.dart @@ -9,22 +9,17 @@ import '../intermediate/lib_monero_wallet.dart'; class MoneroWallet extends LibMoneroWallet { MoneroWallet(CryptoCurrencyNetwork network) - : super( - Monero(network), - lib_monero_compat.WalletType.monero, - ); + : super(Monero(network), lib_monero_compat.WalletType.monero); @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { if (libMoneroWallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) { - return Amount.zeroWith( - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } lib_monero.TransactionPriority priority; - switch (feeRate) { + switch (feeRate.toInt()) { case 1: priority = lib_monero.TransactionPriority.low; break; @@ -104,13 +99,12 @@ class MoneroWallet extends LibMoneroWallet { required String password, required String mnemonic, int height = 0, - }) async => - await lib_monero.MoneroWallet.restoreWalletFromSeed( - path: path, - password: password, - seed: mnemonic, - restoreHeight: height, - ); + }) async => await lib_monero.MoneroWallet.restoreWalletFromSeed( + path: path, + password: password, + seed: mnemonic, + restoreHeight: height, + ); @override Future getRestoredFromViewKeyWallet({ @@ -119,14 +113,13 @@ class MoneroWallet extends LibMoneroWallet { required String address, required String privateViewKey, int height = 0, - }) async => - lib_monero.MoneroWallet.createViewOnlyWallet( - path: path, - password: password, - address: address, - viewKey: privateViewKey, - restoreHeight: height, - ); + }) async => lib_monero.MoneroWallet.createViewOnlyWallet( + path: path, + password: password, + address: address, + viewKey: privateViewKey, + restoreHeight: height, + ); @override void invalidSeedLengthCheck(int length) { diff --git a/lib/wallets/wallet/impl/namecoin_wallet.dart b/lib/wallets/wallet/impl/namecoin_wallet.dart index bf6f43e41..bb3f020f3 100644 --- a/lib/wallets/wallet/impl/namecoin_wallet.dart +++ b/lib/wallets/wallet/impl/namecoin_wallet.dart @@ -200,17 +200,21 @@ class NamecoinWallet } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } // TODO: Check if this is the correct formula for namecoin. @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); @@ -897,7 +901,7 @@ class NamecoinWallet if (customSatsPerVByte != null) { final result = await coinSelectionName( - txData: txData.copyWith(feeRateAmount: -1), + txData: txData.copyWith(feeRateAmount: BigInt.from(-1)), utxos: utxos?.toList(), coinControl: coinControl, ); @@ -911,10 +915,10 @@ class NamecoinWallet } return result; - } else if (feeRateType is FeeRateType || feeRateAmount is int) { - late final int rate; + } else if (feeRateType is FeeRateType || feeRateAmount is BigInt) { + late final BigInt rate; if (feeRateType is FeeRateType) { - int fee = 0; + BigInt fee = BigInt.zero; final feeObject = await fees; switch (feeRateType) { case FeeRateType.fast: @@ -931,7 +935,7 @@ class NamecoinWallet } rate = fee; } else { - rate = feeRateAmount as int; + rate = feeRateAmount!; } final result = await coinSelectionName( diff --git a/lib/wallets/wallet/impl/particl_wallet.dart b/lib/wallets/wallet/impl/particl_wallet.dart index 80db6e2ef..1188625cb 100644 --- a/lib/wallets/wallet/impl/particl_wallet.dart +++ b/lib/wallets/wallet/impl/particl_wallet.dart @@ -45,29 +45,26 @@ class ParticlWallet @override Future> fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } -// =========================================================================== + // =========================================================================== @override - Future< - ({ - bool blocked, - String? blockedReason, - String? utxoLabel, - })> checkBlockUTXO( + Future<({bool blocked, String? blockedReason, String? utxoLabel})> + checkBlockUTXO( Map jsonUTXO, String? scriptPubKeyHex, Map jsonTX, @@ -98,8 +95,9 @@ class ParticlWallet utxoLabel = "Unsupported output type."; } else if (output['scriptPubKey'] != null) { if (output['scriptPubKey']?['asm'] is String && - (output['scriptPubKey']['asm'] as String) - .contains("OP_ISCOINSTAKE")) { + (output['scriptPubKey']['asm'] as String).contains( + "OP_ISCOINSTAKE", + )) { blocked = true; blockedReason = "Spending staking"; utxoLabel = "Unsupported output type."; @@ -111,21 +109,25 @@ class ParticlWallet return ( blocked: blocked, blockedReason: blockedReason, - utxoLabel: utxoLabel + utxoLabel: utxoLabel, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); @@ -138,30 +140,34 @@ class ParticlWallet await fetchAddressesForElectrumXScan(); // Separate receiving and change addresses. - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); // Remove duplicates. final allAddressesSet = {...receivingAddresses, ...changeAddresses}; // Fetch history from ElectrumX. - final List> allTxHashes = - await fetchHistory(allAddressesSet); + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); // Only parse new txs (not in db yet). final List> allTransactions = []; for (final txHash in allTxHashes) { // Check for duplicates by searching for tx by tx_hash in db. - final storedTx = await mainDB.isar.transactionV2s - .where() - .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); if (storedTx == null || storedTx.height == null || @@ -174,8 +180,9 @@ class ParticlWallet ); // Only tx to list once. - if (allTransactions - .indexWhere((e) => e["txid"] == tx["txid"] as String) == + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == -1) { tx["height"] = txHash["height"]; allTransactions.add(tx); @@ -325,7 +332,8 @@ class ParticlWallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -372,32 +380,31 @@ class ParticlWallet switch (sd.derivePathType) { case DerivePathType.bip44: - data = bitcoindart - .P2PKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; + data = + bitcoindart + .P2PKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip49: - final p2wpkh = bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; + final p2wpkh = + bitcoindart + .P2WPKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; redeem = p2wpkh.output; - data = bitcoindart - .P2SH( - data: bitcoindart.PaymentData(redeem: p2wpkh), - network: convertedNetwork, - ) - .data; + data = + bitcoindart + .P2SH( + data: bitcoindart.PaymentData(redeem: p2wpkh), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip84: @@ -405,14 +412,13 @@ class ParticlWallet // prevOut: coinlib.OutPoint.fromHex(sd.utxo.txid, sd.utxo.vout), // publicKey: keys.publicKey, // ); - data = bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; + data = + bitcoindart + .P2WPKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip86: @@ -432,9 +438,7 @@ class ParticlWallet extraData.add((output: output, redeem: redeem)); } - final txb = bitcoindart.TransactionBuilder( - network: convertedNetwork, - ); + final txb = bitcoindart.TransactionBuilder(network: convertedNetwork); const version = 160; // buildTransaction overridden for Particl to set this. // TODO: [prio=low] refactor overridden buildTransaction to use eg. cryptocurrency.networkParams.txVersion. txb.setVersion(version); @@ -463,9 +467,10 @@ class ParticlWallet txid: utxoSigningData[i].utxo.txid, vout: utxoSigningData[i].utxo.vout, ), - addresses: utxoSigningData[i].utxo.address == null - ? [] - : [utxoSigningData[i].utxo.address!], + addresses: + utxoSigningData[i].utxo.address == null + ? [] + : [utxoSigningData[i].utxo.address!], valueStringSats: utxoSigningData[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, @@ -487,10 +492,9 @@ class ParticlWallet OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "000000", valueStringSats: txData.recipients![i].amount.raw.toString(), - addresses: [ - txData.recipients![i].address.toString(), - ], - walletOwns: (await mainDB.isar.addresses + addresses: [txData.recipients![i].address.toString()], + walletOwns: + (await mainDB.isar.addresses .where() .walletIdEqualTo(walletId) .filter() @@ -518,8 +522,11 @@ class ParticlWallet ); } } catch (e, s) { - Logging.instance.e("Caught exception while signing transaction: ", - error: e, stackTrace: s); + Logging.instance.e( + "Caught exception while signing transaction: ", + error: e, + stackTrace: s, + ); rethrow; } diff --git a/lib/wallets/wallet/impl/peercoin_wallet.dart b/lib/wallets/wallet/impl/peercoin_wallet.dart index 153131415..09c69e2cc 100644 --- a/lib/wallets/wallet/impl/peercoin_wallet.dart +++ b/lib/wallets/wallet/impl/peercoin_wallet.dart @@ -54,13 +54,13 @@ class PeercoinWallet // =========================================================================== @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate(int inputCount, int outputCount, BigInt feeRatePerKB) { // TODO: actually do this properly for peercoin // this is probably wrong for peercoin return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); @@ -68,8 +68,8 @@ class PeercoinWallet /// we can just pretend vSize is size for peercoin @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } // =========================================================================== diff --git a/lib/wallets/wallet/impl/solana_wallet.dart b/lib/wallets/wallet/impl/solana_wallet.dart index 8ae0db348..0b7c2911d 100644 --- a/lib/wallets/wallet/impl/solana_wallet.dart +++ b/lib/wallets/wallet/impl/solana_wallet.dart @@ -55,13 +55,13 @@ class SolanaWallet extends Bip39Wallet { return addressStruct; } - Future _getCurrentBalanceInLamports() async { + Future _getCurrentBalanceInLamports() async { _checkClient(); final balance = await _rpcClient?.getBalance((await _getKeyPair()).address); - return balance!.value; + return BigInt.from(balance!.value); } - Future _getEstimatedNetworkFee(Amount transferAmount) async { + Future _getEstimatedNetworkFee(Amount transferAmount) async { _checkClient(); final latestBlockhash = await _rpcClient?.getLatestBlockhash(); final pubKey = (await _getKeyPair()).publicKey; @@ -79,9 +79,13 @@ class SolanaWallet extends Bip39Wallet { feePayer: pubKey, ); - return await _rpcClient?.getFeeForMessage( + final estimate = await _rpcClient?.getFeeForMessage( base64Encode(compiledMessage.toByteArray().toList()), ); + + if (estimate == null) return null; + + return BigInt.from(estimate); } @override @@ -99,7 +103,11 @@ class SolanaWallet extends Bip39Wallet { await mainDB.updateOrPutAddresses([address]); } } catch (e, s) { - Logging.instance.e("$runtimeType checkSaveInitialReceivingAddress() failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType checkSaveInitialReceivingAddress() failed: ", + error: e, + stackTrace: s, + ); } } @@ -133,28 +141,33 @@ class SolanaWallet extends Bip39Wallet { throw Exception("Account does not appear to exist"); } - final int minimumRent = - await _rpcClient!.getMinimumBalanceForRentExemption( - accInfo.value!.data.toString().length, + final BigInt minimumRent = BigInt.from( + await _rpcClient!.getMinimumBalanceForRentExemption( + accInfo.value!.data.toString().length, + ), ); if (minimumRent > ((await _getCurrentBalanceInLamports()) - - txData.amount!.raw.toInt() - + txData.amount!.raw - feeAmount)) { throw Exception( "Insufficient remaining balance for rent exemption, minimum rent: " - "${minimumRent / pow(10, cryptoCurrency.fractionDigits)}", + "${minimumRent.toInt() / pow(10, cryptoCurrency.fractionDigits)}", ); } return txData.copyWith( fee: Amount( - rawValue: BigInt.from(feeAmount), + rawValue: feeAmount, fractionDigits: cryptoCurrency.fractionDigits, ), ); } catch (e, s) { - Logging.instance.e("$runtimeType Solana prepareSend failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType Solana prepareSend failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -166,8 +179,9 @@ class SolanaWallet extends Bip39Wallet { final keyPair = await _getKeyPair(); final recipientAccount = txData.recipients!.first; - final recipientPubKey = - Ed25519HDPublicKey.fromBase58(recipientAccount.address); + final recipientPubKey = Ed25519HDPublicKey.fromBase58( + recipientAccount.address, + ); final message = Message( instructions: [ SystemInstruction.transfer( @@ -187,17 +201,19 @@ class SolanaWallet extends Bip39Wallet { ); final txid = await _rpcClient?.signAndSendTransaction(message, [keyPair]); - return txData.copyWith( - txid: txid, - ); + return txData.copyWith(txid: txid); } catch (e, s) { - Logging.instance.e("$runtimeType Solana confirmSend failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType Solana confirmSend failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { _checkClient(); if (info.cachedBalance.spendable.raw == BigInt.zero) { @@ -212,10 +228,7 @@ class SolanaWallet extends Bip39Wallet { throw Exception("Failed to get fees, please check your node connection."); } - return Amount( - rawValue: BigInt.from(fee), - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount(rawValue: fee, fractionDigits: cryptoCurrency.fractionDigits); } @override @@ -250,7 +263,9 @@ class SolanaWallet extends Bip39Wallet { health = await _rpcClient?.getHealth(); return health != null; } catch (e, s) { - Logging.instance.e("$runtimeType Solana pingCheck failed \"health response=$health\": $e\n$s"); + Logging.instance.e( + "$runtimeType Solana pingCheck failed \"health response=$health\": $e\n$s", + ); return Future.value(false); } } @@ -295,10 +310,10 @@ class SolanaWallet extends Bip39Wallet { throw Exception("Account does not appear to exist"); } - final int minimumRent = - await _rpcClient!.getMinimumBalanceForRentExemption( - accInfo.value!.data.toString().length, - ); + final int minimumRent = await _rpcClient! + .getMinimumBalanceForRentExemption( + accInfo.value!.data.toString().length, + ); final spendableBalance = balance!.value - minimumRent; final newBalance = Balance( @@ -322,7 +337,11 @@ class SolanaWallet extends Bip39Wallet { await info.updateBalance(newBalance: newBalance, isar: mainDB.isar); } catch (e, s) { - Logging.instance.e("Error getting balance in solana_wallet.dart: ", error: e, stackTrace: s); + Logging.instance.e( + "Error getting balance in solana_wallet.dart: ", + error: e, + stackTrace: s, + ); } } @@ -339,23 +358,29 @@ class SolanaWallet extends Bip39Wallet { isar: mainDB.isar, ); } catch (e, s) { - Logging.instance.e("Error occurred in solana_wallet.dart while getting" - " chain height for solana: $e\n$s"); + Logging.instance.e( + "Error occurred in solana_wallet.dart while getting" + " chain height for solana: $e\n$s", + ); } } @override Future updateNode() async { - _solNode = NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? + _solNode = + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? info.coin.defaultNode; await refresh(); } @override NodeModel getCurrentNode() { - _solNode ??= NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? + _solNode ??= + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? info.coin.defaultNode; return _solNode!; @@ -370,8 +395,9 @@ class SolanaWallet extends Bip39Wallet { (await _getKeyPair()).publicKey, encoding: Encoding.jsonParsed, ); - final txsList = - List>.empty(growable: true); + final txsList = List>.empty( + growable: true, + ); final myAddress = (await getCurrentReceivingAddress())!; @@ -384,8 +410,9 @@ class SolanaWallet extends Bip39Wallet { (tx.transaction as ParsedTransaction).message.accountKeys[1].pubkey; var txType = isar.TransactionType.unknown; final txAmount = Amount( - rawValue: - BigInt.from(tx.meta!.postBalances[1] - tx.meta!.preBalances[1]), + rawValue: BigInt.from( + tx.meta!.postBalances[1] - tx.meta!.preBalances[1], + ), fractionDigits: cryptoCurrency.fractionDigits, ); @@ -429,9 +456,10 @@ class SolanaWallet extends Bip39Wallet { derivationIndex: 0, derivationPath: DerivationPath()..value = _addressDerivationPath, type: AddressType.solana, - subType: txType == isar.TransactionType.outgoing - ? AddressSubType.unknown - : AddressSubType.receiving, + subType: + txType == isar.TransactionType.outgoing + ? AddressSubType.unknown + : AddressSubType.receiving, ); txsList.add(Tuple2(transaction, txAddress)); @@ -440,8 +468,10 @@ class SolanaWallet extends Bip39Wallet { } on NodeTorMismatchConfigException { rethrow; } catch (e, s) { - Logging.instance.e("Error occurred in solana_wallet.dart while getting" - " transactions for solana: $e\n$s"); + Logging.instance.e( + "Error occurred in solana_wallet.dart while getting" + " transactions for solana: $e\n$s", + ); } } diff --git a/lib/wallets/wallet/impl/stellar_wallet.dart b/lib/wallets/wallet/impl/stellar_wallet.dart index 811858546..91af9758f 100644 --- a/lib/wallets/wallet/impl/stellar_wallet.dart +++ b/lib/wallets/wallet/impl/stellar_wallet.dart @@ -33,34 +33,34 @@ class StellarWallet extends Bip39Wallet { final bus = GlobalEventBus.instance; // Listen for tor status changes. - _torStatusListener = bus.on().listen( - (event) async { - switch (event.newStatus) { - case TorConnectionStatus.connecting: - if (!_torConnectingLock.isLocked) { - await _torConnectingLock.acquire(); - } - _requireMutex = true; - break; + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + if (!_torConnectingLock.isLocked) { + await _torConnectingLock.acquire(); + } + _requireMutex = true; + break; - case TorConnectionStatus.connected: - case TorConnectionStatus.disconnected: - if (_torConnectingLock.isLocked) { - _torConnectingLock.release(); - } - _requireMutex = false; - break; - } - }, - ); + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + _requireMutex = false; + break; + } + }); // Listen for tor preference changes. - _torPreferenceListener = bus.on().listen( - (event) async { - _stellarSdk?.httpClient.close(); - _stellarSdk = null; - }, - ); + _torPreferenceListener = bus.on().listen(( + event, + ) async { + _stellarSdk?.httpClient.close(); + _stellarSdk = null; + }); } void _hackedCheck() { @@ -116,12 +116,10 @@ class StellarWallet extends Bip39Wallet { // ============== Private ==================================================== // add finalizer to cancel stream subscription when all references to an // instance of this becomes inaccessible - final _ = Finalizer( - (p0) { - p0._torPreferenceListener?.cancel(); - p0._torStatusListener?.cancel(); - }, - ); + final _ = Finalizer((p0) { + p0._torPreferenceListener?.cancel(); + p0._torStatusListener?.cancel(); + }); StreamSubscription? _torStatusListener; StreamSubscription? _torPreferenceListener; @@ -131,9 +129,9 @@ class StellarWallet extends Bip39Wallet { stellar.StellarSDK? _stellarSdk; - Future _getBaseFee() async { + Future _getBaseFee() async { final fees = await (await stellarSdk).feeStats.execute(); - return int.parse(fees.lastLedgerBaseFee); + return BigInt.parse(fees.lastLedgerBaseFee); } stellar.StellarSDK _getFreshSdk() { @@ -145,15 +143,9 @@ class StellarWallet extends Bip39Wallet { TorService.sharedInstance.getProxyInfo(); _httpClient = HttpClient(); - SocksTCPClient.assignToHttpClient( - _httpClient, - [ - ProxySettings( - proxyInfo.host, - proxyInfo.port, - ), - ], - ); + SocksTCPClient.assignToHttpClient(_httpClient, [ + ProxySettings(proxyInfo.host, proxyInfo.port), + ]); } return stellar.StellarSDK( @@ -166,16 +158,18 @@ class StellarWallet extends Bip39Wallet { bool exists = false; try { - final receiverAccount = - await (await stellarSdk).accounts.account(accountId); + final receiverAccount = await (await stellarSdk).accounts.account( + accountId, + ); if (receiverAccount.accountId != "") { exists = true; } } catch (e, s) { Logging.instance.e( - "Error getting account ${e.toString()} - ${s.toString()}", - error: e, - stackTrace: s); + "Error getting account ${e.toString()} - ${s.toString()}", + error: e, + stackTrace: s, + ); } return exists; } @@ -225,15 +219,17 @@ class StellarWallet extends Bip39Wallet { try { final address = await getCurrentReceivingAddress(); if (address == null) { - await mainDB - .updateOrPutAddresses([await _fetchStellarAddress(index: 0)]); + await mainDB.updateOrPutAddresses([ + await _fetchStellarAddress(index: 0), + ]); } } catch (e, s) { // do nothing, still allow user into wallet Logging.instance.e( - "$runtimeType checkSaveInitialReceivingAddress() failed: ", - error: e, - stackTrace: s); + "$runtimeType checkSaveInitialReceivingAddress() failed: ", + error: e, + stackTrace: s, + ); } } @@ -245,7 +241,7 @@ class StellarWallet extends Bip39Wallet { } final feeRate = txData.feeRateType; - var fee = 1000; + BigInt fee = BigInt.from(1000); if (feeRate is FeeRateType) { final theFees = await fees; switch (feeRate) { @@ -261,13 +257,16 @@ class StellarWallet extends Bip39Wallet { return txData.copyWith( fee: Amount( - rawValue: BigInt.from(fee), + rawValue: fee, fractionDigits: cryptoCurrency.fractionDigits, ), ); } catch (e, s) { - Logging.instance - .e("$runtimeType prepareSend() failed: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType prepareSend() failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -275,8 +274,9 @@ class StellarWallet extends Bip39Wallet { @override Future confirmSend({required TxData txData}) async { final senderKeyPair = await _getSenderKeyPair(index: 0); - final sender = - await (await stellarSdk).accounts.account(senderKeyPair.accountId); + final sender = await (await stellarSdk).accounts.account( + senderKeyPair.accountId, + ); final address = txData.recipients!.first.address; final amountToSend = txData.recipients!.first.amount; @@ -293,9 +293,9 @@ class StellarWallet extends Bip39Wallet { address, amountToSend.decimal.toString(), ); - transactionBuilder = stellar.TransactionBuilder(sender).addOperation( - createAccBuilder.build(), - ); + transactionBuilder = stellar.TransactionBuilder( + sender, + ).addOperation(createAccBuilder.build()); } else { transactionBuilder = stellar.TransactionBuilder(sender).addOperation( stellar.PaymentOperationBuilder( @@ -316,14 +316,13 @@ class StellarWallet extends Bip39Wallet { try { final response = await (await stellarSdk).submitTransaction(transaction); if (!response.success) { - throw Exception("${response.extras?.resultCodes?.transactionResultCode}" - " ::: ${response.extras?.resultCodes?.operationsResultCodes}"); + throw Exception( + "${response.extras?.resultCodes?.transactionResultCode}" + " ::: ${response.extras?.resultCodes?.operationsResultCodes}", + ); } - return txData.copyWith( - txHash: response.hash!, - txid: response.hash!, - ); + return txData.copyWith(txHash: response.hash!, txid: response.hash!); } catch (e, s) { Logging.instance.e("Error sending TX $e - $s", error: e, stackTrace: s); rethrow; @@ -331,17 +330,17 @@ class StellarWallet extends Bip39Wallet { } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { final baseFee = await _getBaseFee(); return Amount( - rawValue: BigInt.from(baseFee), + rawValue: baseFee, fractionDigits: cryptoCurrency.fractionDigits, ); } @override Future get fees async { - final int fee = await _getBaseFee(); + final fee = await _getBaseFee(); return FeeObject( numberOfBlocksFast: 1, numberOfBlocksAverage: 1, @@ -379,16 +378,17 @@ class StellarWallet extends Bip39Wallet { stellar.AccountResponse accountResponse; try { - accountResponse = await (await stellarSdk) - .accounts + accountResponse = await (await stellarSdk).accounts .account((await getCurrentReceivingAddress())!.value) .onError((error, stackTrace) => throw error!); } catch (e) { if (e is stellar.ErrorResponse && - e.body.contains("The resource at the url requested was not found. " - "This usually occurs for one of two reasons: " - "The url requested is not valid, or no data in our database " - "could be found with the parameters provided.")) { + e.body.contains( + "The resource at the url requested was not found. " + "This usually occurs for one of two reasons: " + "The url requested is not valid, or no data in our database " + "could be found with the parameters provided.", + )) { // probably just doesn't have any history yet or whatever stellar needs return; } else { @@ -438,16 +438,18 @@ class StellarWallet extends Bip39Wallet { @override Future updateChainHeight() async { try { - final height = await (await stellarSdk) - .ledgers + final height = await (await stellarSdk).ledgers .order(stellar.RequestBuilderOrder.DESC) .limit(1) .execute() .then((value) => value.records!.first.sequence); await info.updateCachedChainHeight(newHeight: height, isar: mainDB.isar); } catch (e, s) { - Logging.instance.e("$runtimeType updateChainHeight() failed: ", - error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType updateChainHeight() failed: ", + error: e, + stackTrace: s, + ); rethrow; } @@ -467,17 +469,19 @@ class StellarWallet extends Bip39Wallet { final List transactionList = []; stellar.Page payments; try { - payments = await (await stellarSdk) - .payments - .forAccount(myAddress.value) - .order(stellar.RequestBuilderOrder.DESC) - .execute(); + payments = + await (await stellarSdk).payments + .forAccount(myAddress.value) + .order(stellar.RequestBuilderOrder.DESC) + .execute(); } catch (e) { if (e is stellar.ErrorResponse && - e.body.contains("The resource at the url requested was not found. " - "This usually occurs for one of two reasons: " - "The url requested is not valid, or no data in our database " - "could be found with the parameters provided.")) { + e.body.contains( + "The resource at the url requested was not found. " + "This usually occurs for one of two reasons: " + "The url requested is not valid, or no data in our database " + "could be found with the parameters provided.", + )) { // probably just doesn't have any history yet or whatever stellar needs return; } else { @@ -521,13 +525,11 @@ class StellarWallet extends Bip39Wallet { final OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( - scriptPubKeyHex: "00", - valueStringSats: amount.raw.toString(), - addresses: [ - addressTo, - ], - walletOwns: addressTo == myAddress.value, - ); + scriptPubKeyHex: "00", + valueStringSats: amount.raw.toString(), + addresses: [addressTo], + walletOwns: addressTo == myAddress.value, + ); final InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( scriptSigHex: null, scriptSigAsm: null, @@ -558,10 +560,11 @@ class StellarWallet extends Bip39Wallet { } final otherData = { - "overrideFee": Amount( - rawValue: BigInt.from(fee), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + "overrideFee": + Amount( + rawValue: BigInt.from(fee), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), }; final theTransaction = TransactionV2( @@ -603,8 +606,8 @@ class StellarWallet extends Bip39Wallet { final List outputs = []; final List inputs = []; - final OutputV2 output = - OutputV2.isarCantDoRequiredInDefaultConstructor( + final OutputV2 + output = OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "00", valueStringSats: amount.raw.toString(), addresses: [ @@ -634,19 +637,20 @@ class StellarWallet extends Bip39Wallet { int fee = 0; int height = 0; - final tx = await (await stellarSdk) - .transactions - .transaction(caor.transactionHash!); + final tx = await (await stellarSdk).transactions.transaction( + caor.transactionHash!, + ); if (tx.hash.isNotEmpty) { fee = tx.feeCharged!; height = tx.ledger; } final otherData = { - "overrideFee": Amount( - rawValue: BigInt.from(fee), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + "overrideFee": + Amount( + rawValue: BigInt.from(fee), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), }; final theTransaction = TransactionV2( @@ -671,8 +675,11 @@ class StellarWallet extends Bip39Wallet { await mainDB.updateOrPutTransactionV2s(transactionList); } catch (e, s) { - Logging.instance.e("Exception rethrown from updateTransactions(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from updateTransactions(): ", + error: e, + stackTrace: s, + ); rethrow; } } diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index 7f3d7735b..b2379f28e 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -207,7 +207,7 @@ class EthTokenWallet extends Wallet { @override Future prepareSend({required TxData txData}) async { final feeRateType = txData.feeRateType!; - int fee = 0; + BigInt fee = BigInt.zero; final feeObject = await fees; switch (feeRateType) { case FeeRateType.fast: @@ -258,13 +258,13 @@ class EthTokenWallet extends Wallet { function: _sendFunction, parameters: [web3dart.EthereumAddress.fromHex(address), amount.raw], maxGas: kEthereumTokenMinGasLimit, - gasPrice: web3dart.EtherAmount.fromInt(web3dart.EtherUnit.wei, fee), + gasPrice: web3dart.EtherAmount.fromBigInt(web3dart.EtherUnit.wei, fee), nonce: nonce, ); return txData.copyWith( fee: feeEstimate, - feeInWei: BigInt.from(fee), + feeInWei: fee, web3dartTransaction: tx, chainId: await client.getChainId(), nonce: tx.nonce, @@ -285,7 +285,7 @@ class EthTokenWallet extends Wallet { } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { return ethWallet.estimateEthFee( feeRate, kEthereumTokenMinGasLimit, diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index 992a900ae..ae2183be0 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -115,9 +115,10 @@ class TezosWallet extends Bip39Wallet { prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null; final tezartClient = tezart.TezartClient( server, - proxy: proxyInfo != null - ? "socks5://${proxyInfo.host}:${proxyInfo.port};" - : null, + proxy: + proxyInfo != null + ? "socks5://${proxyInfo.host}:${proxyInfo.port};" + : null, ); final opList = await tezartClient.transferOperation( @@ -197,9 +198,7 @@ class TezosWallet extends Bip39Wallet { } final myAddress = (await getCurrentReceivingAddress())!; - final account = await TezosAPI.getAccount( - myAddress.value, - ); + final account = await TezosAPI.getAccount(myAddress.value); // final bool isSendAll = sendAmount == info.cachedBalance.spendable; // @@ -262,13 +261,8 @@ class TezosWallet extends Bip39Wallet { // fee: fee, fee: Amount( rawValue: opList.operations - .map( - (e) => BigInt.from(e.fee), - ) - .fold( - BigInt.zero, - (p, e) => p + e, - ), + .map((e) => BigInt.from(e.fee)) + .fold(BigInt.zero, (p, e) => p + e), fractionDigits: cryptoCurrency.fractionDigits, ), tezosOperationsList: opList, @@ -280,14 +274,14 @@ class TezosWallet extends Bip39Wallet { stackTrace: s, ); - if (e - .toString() - .contains("(_operationResult['errors']): Must not be null")) { + if (e.toString().contains( + "(_operationResult['errors']): Must not be null", + )) { throw Exception("Probably insufficient balance"); } else if (e.toString().contains( - "The simulation of the operation: \"transaction\" failed with error(s) :" - " contract.balance_too_low, tez.subtraction_underflow.", - )) { + "The simulation of the operation: \"transaction\" failed with error(s) :" + " contract.balance_too_low, tez.subtraction_underflow.", + )) { throw Exception("Insufficient balance to pay fees"); } @@ -300,9 +294,7 @@ class TezosWallet extends Bip39Wallet { _hackedCheckTorNodePrefs(); await txData.tezosOperationsList!.inject(); await txData.tezosOperationsList!.monitor(); - return txData.copyWith( - txid: txData.tezosOperationsList!.result.id, - ); + return txData.copyWith(txid: txData.tezosOperationsList!.result.id); } int _estCount = 0; @@ -350,13 +342,8 @@ class TezosWallet extends Bip39Wallet { rethrow; } else { _estCount++; - Logging.instance.e( - "_estimate() retry _estCount=$_estCount", - ); - return await _estimate( - account, - recipientAddress, - ); + Logging.instance.e("_estimate() retry _estCount=$_estCount"); + return await _estimate(account, recipientAddress); } } } @@ -364,7 +351,7 @@ class TezosWallet extends Bip39Wallet { @override Future estimateFeeFor( Amount amount, - int feeRate, { + BigInt feeRate, { String recipientAddress = "tz1MXvDCyXSqBqXPNDcsdmVZKfoxL9FTHmp2", }) async { _hackedCheckTorNodePrefs(); @@ -376,9 +363,7 @@ class TezosWallet extends Bip39Wallet { } final myAddress = (await getCurrentReceivingAddress())!; - final account = await TezosAPI.getAccount( - myAddress.value, - ); + final account = await TezosAPI.getAccount(myAddress.value); try { final fees = await _estimate(account, recipientAddress); @@ -402,7 +387,7 @@ class TezosWallet extends Bip39Wallet { /// Not really used (yet) @override Future get fees async { - const feePerTx = 1; + final feePerTx = BigInt.one; return FeeObject( numberOfBlocksFast: 10, numberOfBlocksAverage: 10, @@ -418,10 +403,7 @@ class TezosWallet extends Bip39Wallet { _hackedCheckTorNodePrefs(); final currentNode = getCurrentNode(); return await TezosRpcAPI.testNetworkConnection( - nodeInfo: ( - host: currentNode.host, - port: currentNode.port, - ), + nodeInfo: (host: currentNode.host, port: currentNode.port), ); } @@ -518,16 +500,10 @@ class TezosWallet extends Bip39Wallet { _hackedCheckTorNodePrefs(); final currentNode = _xtzNode ?? getCurrentNode(); final height = await TezosRpcAPI.getChainHeight( - nodeInfo: ( - host: currentNode.host, - port: currentNode.port, - ), + nodeInfo: (host: currentNode.host, port: currentNode.port), ); - await info.updateCachedChainHeight( - newHeight: height!, - isar: mainDB.isar, - ); + await info.updateCachedChainHeight(newHeight: height!, isar: mainDB.isar); } catch (e, s) { Logging.instance.e( "Error occurred in tezos_wallet.dart while getting" @@ -540,8 +516,10 @@ class TezosWallet extends Bip39Wallet { @override Future updateNode() async { - _xtzNode = NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? + _xtzNode = + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? info.coin.defaultNode; await refresh(); @@ -550,9 +528,10 @@ class TezosWallet extends Bip39Wallet { @override NodeModel getCurrentNode() { return _xtzNode ??= - NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? + info.coin.defaultNode; } @override @@ -590,10 +569,11 @@ class TezosWallet extends Bip39Wallet { type: txType, subType: TransactionSubType.none, amount: theTx.amountInMicroTez, - amountString: Amount( - rawValue: BigInt.from(theTx.amountInMicroTez), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + amountString: + Amount( + rawValue: BigInt.from(theTx.amountInMicroTez), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), fee: theTx.feeInMicroTez, height: theTx.height, isCancelled: false, diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart index 81407f837..028b447de 100644 --- a/lib/wallets/wallet/impl/wownero_wallet.dart +++ b/lib/wallets/wallet/impl/wownero_wallet.dart @@ -11,23 +11,18 @@ import '../intermediate/lib_monero_wallet.dart'; class WowneroWallet extends LibMoneroWallet { WowneroWallet(CryptoCurrencyNetwork network) - : super( - Wownero(network), - lib_monero_compat.WalletType.wownero, - ); + : super(Wownero(network), lib_monero_compat.WalletType.wownero); @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { if (libMoneroWallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) { - return Amount.zeroWith( - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } lib_monero.TransactionPriority priority; FeeRateType feeRateType = FeeRateType.slow; - switch (feeRate) { + switch (feeRate.toInt()) { case 1: priority = lib_monero.TransactionPriority.low; feeRateType = FeeRateType.average; @@ -141,13 +136,12 @@ class WowneroWallet extends LibMoneroWallet { required String password, required String mnemonic, int height = 0, - }) async => - await lib_monero.WowneroWallet.restoreWalletFromSeed( - path: path, - password: password, - seed: mnemonic, - restoreHeight: height, - ); + }) async => await lib_monero.WowneroWallet.restoreWalletFromSeed( + path: path, + password: password, + seed: mnemonic, + restoreHeight: height, + ); @override Future getRestoredFromViewKeyWallet({ @@ -156,14 +150,13 @@ class WowneroWallet extends LibMoneroWallet { required String address, required String privateViewKey, int height = 0, - }) async => - lib_monero.WowneroWallet.createViewOnlyWallet( - path: path, - password: password, - address: address, - viewKey: privateViewKey, - restoreHeight: height, - ); + }) async => lib_monero.WowneroWallet.createViewOnlyWallet( + path: path, + password: password, + address: address, + viewKey: privateViewKey, + restoreHeight: height, + ); @override void invalidSeedLengthCheck(int length) { diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart index bcbf09f4c..df5282c4a 100644 --- a/lib/wallets/wallet/impl/xelis_wallet.dart +++ b/lib/wallets/wallet/impl/xelis_wallet.dart @@ -611,9 +611,9 @@ class XelisWallet extends LibXelisWallet { numberOfBlocksFast: 10, numberOfBlocksAverage: 10, numberOfBlocksSlow: 10, - fast: 1, - medium: 1, - slow: 1, + fast: BigInt.one, + medium: BigInt.one, + slow: BigInt.one, ); } @@ -650,7 +650,7 @@ class XelisWallet extends LibXelisWallet { // Estimate fee using the shared method final boostedFee = await estimateFeeFor( totalSendAmount, - 1, + BigInt.one, feeMultiplier: 1.0, recipients: recipients, assetId: asset, @@ -690,7 +690,7 @@ class XelisWallet extends LibXelisWallet { @override Future estimateFeeFor( Amount amount, - int feeRate, { + BigInt feeRate, { double? feeMultiplier, List recipients = const [], String? assetId, diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index b6b30de34..90b426e96 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -51,33 +51,33 @@ abstract class LibMoneroWallet final bus = GlobalEventBus.instance; // Listen for tor status changes. - _torStatusListener = bus.on().listen( - (event) async { - switch (event.newStatus) { - case TorConnectionStatus.connecting: - if (!_torConnectingLock.isLocked) { - await _torConnectingLock.acquire(); - } - _requireMutex = true; - break; + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + if (!_torConnectingLock.isLocked) { + await _torConnectingLock.acquire(); + } + _requireMutex = true; + break; - case TorConnectionStatus.connected: - case TorConnectionStatus.disconnected: - if (_torConnectingLock.isLocked) { - _torConnectingLock.release(); - } - _requireMutex = false; - break; - } - }, - ); + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + _requireMutex = false; + break; + } + }); // Listen for tor preference changes. - _torPreferenceListener = bus.on().listen( - (event) async { - await updateNode(); - }, - ); + _torPreferenceListener = bus.on().listen(( + event, + ) async { + await updateNode(); + }); // Potentially dangerous hack. See comments in _startInit() _startInit(); @@ -93,17 +93,13 @@ abstract class LibMoneroWallet .walletIdEqualTo(walletId) .watch(fireImmediately: true) .listen((utxos) async { - try { - await onUTXOsChanged(utxos); - await updateBalance(shouldUpdateUtxos: false); - } catch (e, s) { - lib_monero.Logging.log?.i( - "_startInit", - error: e, - stackTrace: s, - ); - } - }); + try { + await onUTXOsChanged(utxos); + await updateBalance(shouldUpdateUtxos: false); + } catch (e, s) { + lib_monero.Logging.log?.i("_startInit", error: e, stackTrace: s); + } + }); }); } @@ -179,11 +175,7 @@ abstract class LibMoneroWallet onNewBlock: onNewBlock, onBalancesChanged: onBalancesChanged, onError: (e, s) { - Logging.instance.w( - "$e\n$s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); }, ), ); @@ -197,16 +189,14 @@ abstract class LibMoneroWallet if (libMoneroWallet == null) { wasNull = true; // libMoneroWalletT?.close(); - final path = await pathForWallet( - name: walletId, - type: compatType, - ); + final path = await pathForWallet(name: walletId, type: compatType); final String password; try { - password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), - ))!; + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); } @@ -247,9 +237,7 @@ abstract class LibMoneroWallet } @Deprecated("Only used in the case of older wallets") - lib_monero_compat.WalletInfo? getLibMoneroWalletInfo( - String walletId, - ) { + lib_monero_compat.WalletInfo? getLibMoneroWalletInfo(String walletId) { try { return DB.instance.moneroWalletInfoBox.values.firstWhere( (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), @@ -297,9 +285,7 @@ abstract class LibMoneroWallet Future getKeys() async { final base = libMoneroWallet; - final oldInfo = getLibMoneroWalletInfo( - walletId, - ); + final oldInfo = getLibMoneroWalletInfo(walletId); if (base == null || (oldInfo != null && oldInfo.name != walletId)) { return null; } @@ -324,13 +310,14 @@ abstract class LibMoneroWallet } Future<(String, String)> - hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { + hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { final path = await pathForWallet(name: walletId, type: compatType); final String password; try { - password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), - ))!; + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); } @@ -341,10 +328,7 @@ abstract class LibMoneroWallet @override Future init({bool? isRestore, int? wordCount}) async { - final path = await pathForWallet( - name: walletId, - type: compatType, - ); + final path = await pathForWallet(name: walletId, type: compatType); if (!(walletExists(path)) && isRestore != true) { if (wordCount == null) { throw Exception("Missing word count for new xmr/wow wallet!"); @@ -424,10 +408,7 @@ abstract class LibMoneroWallet final String name = walletId; - final path = await pathForWallet( - name: name, - type: compatType, - ); + final path = await pathForWallet(name: name, type: compatType); try { final password = generatePassword(); @@ -450,7 +431,8 @@ abstract class LibMoneroWallet _setListener(); - final newReceivingAddress = await getCurrentReceivingAddress() ?? + final newReceivingAddress = + await getCurrentReceivingAddress() ?? Address( walletId: walletId, derivationIndex: 0, @@ -481,8 +463,11 @@ abstract class LibMoneroWallet libMoneroWallet?.startListeners(); libMoneroWallet?.startAutoSaving(); } catch (e, s) { - Logging.instance.e("Exception rethrown from recoverFromMnemonic(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from recoverFromMnemonic(): ", + error: e, + stackTrace: s, + ); rethrow; } }); @@ -551,8 +536,11 @@ abstract class LibMoneroWallet _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); } catch (e, s) { _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - Logging.instance.e("Exception caught in $runtimeType.updateNode(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception caught in $runtimeType.updateNode(): ", + error: e, + stackTrace: s, + ); } return; @@ -566,13 +554,14 @@ abstract class LibMoneroWallet return; } - final localTxids = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .heightGreaterThan(0) - .txidProperty() - .findAll(); + final localTxids = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .heightGreaterThan(0) + .txidProperty() + .findAll(); final allTxids = await base.getAllTxids(refresh: true); @@ -582,10 +571,7 @@ abstract class LibMoneroWallet return; } - final transactions = await base.getTxs( - txids: txidsToFetch, - refresh: false, - ); + final transactions = await base.getTxs(txids: txidsToFetch, refresh: false); final allOutputs = await base.getOutputs(includeSpent: true, refresh: true); @@ -673,14 +659,16 @@ abstract class LibMoneroWallet type: type, subType: TransactionSubType.none, otherData: jsonEncode({ - TxV2OdKeys.overrideFee: Amount( - rawValue: tx.fee, - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), - TxV2OdKeys.moneroAmount: Amount( - rawValue: tx.amount, - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + TxV2OdKeys.overrideFee: + Amount( + rawValue: tx.fee, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), + TxV2OdKeys.moneroAmount: + Amount( + rawValue: tx.amount, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), TxV2OdKeys.moneroAccountIndex: tx.accountIndex, TxV2OdKeys.isMoneroTransaction: true, }), @@ -756,9 +744,10 @@ abstract class LibMoneroWallet Future pathForWallet({ required String name, required lib_monero_compat.WalletType type, - }) async => - await pathForWalletDir(name: name, type: type) - .then((path) => '$path/$name'); + }) async => await pathForWalletDir( + name: name, + type: type, + ).then((path) => '$path/$name'); void onSyncingUpdate({ required int syncHeight, @@ -903,16 +892,10 @@ abstract class LibMoneroWallet } GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highest, - walletId, - ), + RefreshPercentChangedEvent(highest, walletId), ); GlobalEventBus.instance.fire( - BlocksRemainingEvent( - blocksLeft, - walletId, - ), + BlocksRemainingEvent(blocksLeft, walletId), ); } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { status = WalletSyncStatus.synced; @@ -922,10 +905,7 @@ abstract class LibMoneroWallet } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { status = WalletSyncStatus.unableToSync; @@ -933,18 +913,12 @@ abstract class LibMoneroWallet } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { status = WalletSyncStatus.unableToSync; @@ -953,11 +927,7 @@ abstract class LibMoneroWallet if (status != null) { GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - status, - walletId, - info.coin, - ), + WalletSyncStatusChangedEvent(status, walletId, info.coin), ); } } @@ -1019,24 +989,27 @@ abstract class LibMoneroWallet @override Future updateUTXOs() async { final List outputArray = []; - final utxos = await libMoneroWallet?.getOutputs(refresh: true) ?? + final utxos = + await libMoneroWallet?.getOutputs(refresh: true) ?? []; for (final rawUTXO in utxos) { if (!rawUTXO.spent) { - final current = await mainDB.isar.utxos - .where() - .walletIdEqualTo(walletId) - .filter() - .voutEqualTo(rawUTXO.vout) - .and() - .txidEqualTo(rawUTXO.hash) - .findFirst(); - final tx = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .txidEqualTo(rawUTXO.hash) - .findFirst(); + final current = + await mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .voutEqualTo(rawUTXO.vout) + .and() + .txidEqualTo(rawUTXO.hash) + .findFirst(); + final tx = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(rawUTXO.hash) + .findFirst(); final otherDataMap = { UTXOOtherDataKeys.keyImage: rawUTXO.keyImage, @@ -1161,8 +1134,11 @@ abstract class LibMoneroWallet isar: mainDB.isar, ); } catch (e, s) { - Logging.instance - .e("Exception in generateNewAddress(): ", error: e, stackTrace: s); + Logging.instance.e( + "Exception in generateNewAddress(): ", + error: e, + stackTrace: s, + ); } } @@ -1173,9 +1149,10 @@ abstract class LibMoneroWallet throw Exception(); } catch (_, s) { Logging.instance.e( - "checkReceivingAddressForTransactions called but reuse address flag set: $s", - error: e, - stackTrace: s); + "checkReceivingAddressForTransactions called but reuse address flag set: $s", + error: e, + stackTrace: s, + ); } } @@ -1185,9 +1162,10 @@ abstract class LibMoneroWallet if (entries != null) { for (final element in entries) { if (!element.isSpend) { - final int curAddressIndex = element.addressIndexes.isEmpty - ? 0 - : element.addressIndexes.reduce(max); + final int curAddressIndex = + element.addressIndexes.isEmpty + ? 0 + : element.addressIndexes.reduce(max); if (curAddressIndex > highestIndex) { highestIndex = curAddressIndex; } @@ -1206,11 +1184,12 @@ abstract class LibMoneroWallet // Use new index to derive a new receiving address final newReceivingAddress = addressFor(index: newReceivingIndex); - final existing = await mainDB - .getAddresses(walletId) - .filter() - .valueEqualTo(newReceivingAddress.value) - .findFirst(); + final existing = + await mainDB + .getAddresses(walletId) + .filter() + .valueEqualTo(newReceivingAddress.value) + .findFirst(); if (existing == null) { // Add that new change address await mainDB.putAddress(newReceivingAddress); @@ -1225,15 +1204,17 @@ abstract class LibMoneroWallet } } on SocketException catch (se, s) { Logging.instance.e( - "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s", - error: e, - stackTrace: s); + "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s", + error: e, + stackTrace: s, + ); return; } catch (e, s) { Logging.instance.e( - "Exception rethrown from _checkReceivingAddressForTransactions(): ", - error: e, - stackTrace: s); + "Exception rethrown from _checkReceivingAddressForTransactions(): ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -1241,13 +1222,13 @@ abstract class LibMoneroWallet // TODO: this needs some work. Prio's may need to be changed as well as estimated blocks @override Future get fees async => FeeObject( - numberOfBlocksFast: 10, - numberOfBlocksAverage: 15, - numberOfBlocksSlow: 20, - fast: lib_monero.TransactionPriority.high.value, - medium: lib_monero.TransactionPriority.medium.value, - slow: lib_monero.TransactionPriority.normal.value, - ); + numberOfBlocksFast: 10, + numberOfBlocksAverage: 15, + numberOfBlocksSlow: 20, + fast: BigInt.from(lib_monero.TransactionPriority.high.value), + medium: BigInt.from(lib_monero.TransactionPriority.medium.value), + slow: BigInt.from(lib_monero.TransactionPriority.normal.value), + ); @override Future updateChainHeight() async { @@ -1321,25 +1302,27 @@ abstract class LibMoneroWallet } final height = await chainHeight; - final inputs = txData.utxos - ?.map( - (e) => lib_monero.Output( - address: e.address!, - hash: e.txid, - keyImage: e.keyImage!, - value: BigInt.from(e.value), - isFrozen: e.isBlocked, - isUnlocked: e.blockHeight != null && - (height - (e.blockHeight ?? 0)) >= - cryptoCurrency.minConfirms, - height: e.blockHeight ?? 0, - vout: e.vout, - spent: e.used ?? false, - spentHeight: null, // doesn't matter here - coinbase: e.isCoinbase, - ), - ) - .toList(); + final inputs = + txData.utxos + ?.map( + (e) => lib_monero.Output( + address: e.address!, + hash: e.txid, + keyImage: e.keyImage!, + value: BigInt.from(e.value), + isFrozen: e.isBlocked, + isUnlocked: + e.blockHeight != null && + (height - (e.blockHeight ?? 0)) >= + cryptoCurrency.minConfirms, + height: e.blockHeight ?? 0, + vout: e.vout, + spent: e.used ?? false, + spentHeight: null, // doesn't matter here + coinbase: e.isCoinbase, + ), + ) + .toList(); return await prepareSendMutex.protect(() async { final lib_monero.PendingTransaction pendingTransaction; @@ -1380,8 +1363,11 @@ abstract class LibMoneroWallet throw ArgumentError("Invalid fee rate argument provided!"); } } catch (e, s) { - Logging.instance.i("Exception rethrown from prepare send(): ", - error: e, stackTrace: s); + Logging.instance.i( + "Exception rethrown from prepare send(): ", + error: e, + stackTrace: s, + ); if (e.toString().contains("Incorrect unlocked balance")) { throw Exception("Insufficient balance!"); @@ -1395,9 +1381,7 @@ abstract class LibMoneroWallet Future confirmSend({required TxData txData}) async { try { try { - await libMoneroWallet!.commitTx( - txData.pendingTransaction!, - ); + await libMoneroWallet!.commitTx(txData.pendingTransaction!); Logging.instance.d( "transaction ${txData.pendingTransaction!.txid} has been sent", @@ -1405,14 +1389,18 @@ abstract class LibMoneroWallet return txData.copyWith(txid: txData.pendingTransaction!.txid); } catch (e, s) { Logging.instance.e( - "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", - error: e, - stackTrace: s); + "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", + error: e, + stackTrace: s, + ); rethrow; } } catch (e, s) { - Logging.instance.e("Exception rethrown from confirmSend(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from confirmSend(): ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -1435,10 +1423,7 @@ abstract class LibMoneroWallet final String name = walletId; - final path = await pathForWallet( - name: name, - type: compatType, - ); + final path = await pathForWallet(name: name, type: compatType); final password = generatePassword(); await secureStorageInterface.write( @@ -1461,7 +1446,8 @@ abstract class LibMoneroWallet _setListener(); - final newReceivingAddress = await getCurrentReceivingAddress() ?? + final newReceivingAddress = + await getCurrentReceivingAddress() ?? Address( walletId: walletId, derivationIndex: 0, @@ -1488,8 +1474,11 @@ abstract class LibMoneroWallet libMoneroWallet?.startListeners(); libMoneroWallet?.startAutoSaving(); } catch (e, s) { - Logging.instance.e("Exception rethrown from recoverViewOnly(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from recoverViewOnly(): ", + error: e, + stackTrace: s, + ); rethrow; } }); diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index be21c5282..9ed0c9c6e 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -127,11 +127,7 @@ abstract class Wallet { await updateChainHeight(); } catch (e, s) { // do nothing on failure (besides logging) - Logging.instance.w( - "$e\n$s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); } // return regardless of whether it was updated or not as we want a @@ -173,7 +169,8 @@ abstract class Wallet { value: viewOnlyData!.toJsonEncodedString(), ); } else if (wallet is MnemonicInterface) { - if (wallet is CryptonoteWallet || wallet is XelisWallet) { // + if (wallet is CryptonoteWallet || wallet is XelisWallet) { + // // currently a special case due to the xmr/wow/xelis libraries handling their // own mnemonic generation on new wallet creation // if its a restore we must set them @@ -238,10 +235,11 @@ abstract class Wallet { required NodeService nodeService, required Prefs prefs, }) async { - final walletInfo = await mainDB.isar.walletInfo - .where() - .walletIdEqualTo(walletId) - .findFirst(); + final walletInfo = + await mainDB.isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .findFirst(); Logging.instance.i( "Wallet.load loading" @@ -270,10 +268,7 @@ abstract class Wallet { required EthereumWallet ethWallet, required EthContract contract, }) { - final Wallet wallet = EthTokenWallet( - ethWallet, - contract, - ); + final Wallet wallet = EthTokenWallet(ethWallet, contract); wallet.prefs = ethWallet.prefs; wallet.nodeService = ethWallet.nodeService; @@ -287,27 +282,19 @@ abstract class Wallet { // ========== Static Util ==================================================== // secure storage key - static String mnemonicKey({ - required String walletId, - }) => + static String mnemonicKey({required String walletId}) => "${walletId}_mnemonic"; // secure storage key - static String mnemonicPassphraseKey({ - required String walletId, - }) => + static String mnemonicPassphraseKey({required String walletId}) => "${walletId}_mnemonicPassphrase"; // secure storage key - static String privateKeyKey({ - required String walletId, - }) => + static String privateKeyKey({required String walletId}) => "${walletId}_privateKey"; // secure storage key - static String getViewOnlyWalletDataSecStoreKey({ - required String walletId, - }) => + static String getViewOnlyWalletDataSecStoreKey({required String walletId}) => "${walletId}_viewOnlyWalletData"; //============================================================================ @@ -321,9 +308,7 @@ abstract class Wallet { required NodeService nodeService, required Prefs prefs, }) async { - final Wallet wallet = _loadWallet( - walletInfo: walletInfo, - ); + final Wallet wallet = _loadWallet(walletInfo: walletInfo); wallet.prefs = prefs; wallet.nodeService = nodeService; @@ -339,9 +324,7 @@ abstract class Wallet { .._walletId = walletInfo.walletId; } - static Wallet _loadWallet({ - required WalletInfo walletInfo, - }) { + static Wallet _loadWallet({required WalletInfo walletInfo}) { final net = walletInfo.coin.network; switch (walletInfo.coin.runtimeType) { case const (Banano): @@ -421,12 +404,11 @@ abstract class Wallet { _periodicPingCheck(); // then periodically check - _networkAliveTimer = Timer.periodic( - Constants.networkAliveTimerDuration, - (_) async { - _periodicPingCheck(); - }, - ); + _networkAliveTimer = Timer.periodic(Constants.networkAliveTimerDuration, ( + _, + ) async { + _periodicPingCheck(); + }); } void _periodicPingCheck() async { @@ -438,15 +420,12 @@ abstract class Wallet { final bool hasNetwork = await pingCheck(); if (_isConnected != hasNetwork) { - final NodeConnectionStatus status = hasNetwork - ? NodeConnectionStatus.connected - : NodeConnectionStatus.disconnected; + final NodeConnectionStatus status = + hasNetwork + ? NodeConnectionStatus.connected + : NodeConnectionStatus.disconnected; GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - status, - walletId, - cryptoCurrency, - ), + NodeConnectionStatusChangedEvent(status, walletId, cryptoCurrency), ); _isConnected = hasNetwork; @@ -499,7 +478,7 @@ abstract class Wallet { /// updates the wallet info's cachedChainHeight Future updateChainHeight(); - Future estimateFeeFor(Amount amount, int feeRate); + Future estimateFeeFor(Amount amount, BigInt feeRate); Future get fees; @@ -518,7 +497,8 @@ abstract class Wallet { } NodeModel getCurrentNode() { - final node = nodeService.getPrimaryNodeFor(currency: cryptoCurrency) ?? + final node = + nodeService.getPrimaryNodeFor(currency: cryptoCurrency) ?? cryptoCurrency.defaultNode; return node; @@ -538,8 +518,9 @@ abstract class Wallet { ); if (shouldAutoSync) { - _periodicRefreshTimer ??= - Timer.periodic(const Duration(seconds: 150), (timer) async { + _periodicRefreshTimer ??= Timer.periodic(const Duration(seconds: 150), ( + timer, + ) async { // chain height check currently broken // if ((await chainHeight) != (await storedChainHeight)) { @@ -596,7 +577,8 @@ abstract class Wallet { } final start = DateTime.now(); - final viewOnly = this is ViewOnlyOptionInterface && + final viewOnly = + this is ViewOnlyOptionInterface && (this as ViewOnlyOptionInterface).isViewOnly; try { @@ -621,8 +603,9 @@ abstract class Wallet { final Set codesToCheck = {}; if (this is PaynymInterface && !viewOnly) { // isSegwit does not matter here at all - final myCode = - await (this as PaynymInterface).getPaymentCode(isSegwit: false); + final myCode = await (this as PaynymInterface).getPaymentCode( + isSegwit: false, + ); final nym = await PaynymIsApi().nym(myCode.toString()); if (nym.value != null) { @@ -685,8 +668,9 @@ abstract class Wallet { // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided. if (!viewOnly && this is PaynymInterface && codesToCheck.isNotEmpty) { - await (this as PaynymInterface) - .checkForNotificationTransactionsTo(codesToCheck); + await (this as PaynymInterface).checkForNotificationTransactionsTo( + codesToCheck, + ); // check utxos again for notification outputs await updateUTXOs(); } @@ -746,10 +730,11 @@ abstract class Wallet { // Check if there's another wallet of this coin on the sync list. final List walletIds = []; for (final id in prefs.walletIdsSyncOnStartup) { - final wallet = mainDB.isar.walletInfo - .where() - .walletIdEqualTo(id) - .findFirstSync()!; + final wallet = + mainDB.isar.walletInfo + .where() + .walletIdEqualTo(id) + .findFirstSync()!; if (wallet.coin == cryptoCurrency) { walletIds.add(id); @@ -802,17 +787,11 @@ abstract class Wallet { return await mainDB.isar.addresses .buildQuery
( whereClauses: [ - IndexWhereClause.equalTo( - indexName: r"walletId", - value: [walletId], - ), + IndexWhereClause.equalTo(indexName: r"walletId", value: [walletId]), ], filter: filterOperation, sortBy: [ - const SortProperty( - property: r"derivationIndex", - sort: Sort.desc, - ), + const SortProperty(property: r"derivationIndex", sort: Sort.desc), ], ) .findFirst(); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index e393ceb9d..8fe157a61 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -439,7 +439,7 @@ mixin ElectrumXInterface required BigInt satoshisBeingUsed, required List utxoSigningData, required int? satsPerVByte, - required int feeRatePerKB, + required BigInt feeRatePerKB, }) async { Logging.instance.d("Attempting to send all $cryptoCurrency"); if (txData.recipients!.length != 1) { @@ -1225,17 +1225,17 @@ mixin ElectrumXInterface Amount.fromDecimal( fast, fractionDigits: info.coin.fractionDigits, - ).raw.toInt(), + ).raw, medium: Amount.fromDecimal( medium, fractionDigits: info.coin.fractionDigits, - ).raw.toInt(), + ).raw, slow: Amount.fromDecimal( slow, fractionDigits: info.coin.fractionDigits, - ).raw.toInt(), + ).raw, ); Logging.instance.d("fetched fees: $feeObject"); @@ -1256,7 +1256,7 @@ mixin ElectrumXInterface } @override - Future estimateFeeFor(Amount amount, int feeRate) async { + Future estimateFeeFor(Amount amount, BigInt feeRate) async { final available = info.cachedBalance.spendable; final utxos = _spendableUTXOs(await mainDB.getUTXOs(walletId).findAll()); @@ -1713,7 +1713,7 @@ mixin ElectrumXInterface } final result = await coinSelection( - txData: txData.copyWith(feeRateAmount: -1), + txData: txData.copyWith(feeRateAmount: BigInt.from(-1)), isSendAll: isSendAll, utxos: utxos?.toList(), coinControl: coinControl, @@ -1729,10 +1729,10 @@ mixin ElectrumXInterface } return result; - } else if (feeRateType is FeeRateType || feeRateAmount is int) { - late final int rate; + } else if (feeRateType is FeeRateType || feeRateAmount is BigInt) { + late final BigInt rate; if (feeRateType is FeeRateType) { - int fee = 0; + BigInt fee = BigInt.zero; final feeObject = await fees; switch (feeRateType) { case FeeRateType.fast: @@ -1749,7 +1749,7 @@ mixin ElectrumXInterface } rate = fee; } else { - rate = feeRateAmount as int; + rate = feeRateAmount!; } // check for send all @@ -1832,8 +1832,8 @@ mixin ElectrumXInterface // =========================================================================== // ========== Interface functions ============================================ - int estimateTxFee({required int vSize, required int feeRatePerKB}); - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}); + Amount roughFeeEstimate(int inputCount, int outputCount, BigInt feeRatePerKB); Future> fetchAddressesForElectrumXScan(); @@ -1864,7 +1864,10 @@ mixin ElectrumXInterface .toList(); } - Future _sweepAllEstimate(int feeRate, List usableUTXOs) async { + Future _sweepAllEstimate( + BigInt feeRate, + List usableUTXOs, + ) async { final available = usableUTXOs .map((e) => BigInt.from(e.value)) .fold(BigInt.zero, (p, e) => p + e); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart index 148bd61a2..1a7937113 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart @@ -48,46 +48,50 @@ mixin LelantusInterface } Future> _getLelantusEntry() async { - final List lelantusCoins = await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .group( - (q) => q - .valueEqualTo("0") - .or() - .anonymitySetIdEqualTo(LelantusFfiWrapper.ANONYMITY_SET_EMPTY_ID), - ) - .findAll(); + final List lelantusCoins = + await mainDB.isar.lelantusCoins + .where() + .walletIdEqualTo(walletId) + .filter() + .isUsedEqualTo(false) + .not() + .group( + (q) => q + .valueEqualTo("0") + .or() + .anonymitySetIdEqualTo( + LelantusFfiWrapper.ANONYMITY_SET_EMPTY_ID, + ), + ) + .findAll(); final root = await getRootHDNode(); - final waitLelantusEntries = lelantusCoins.map((coin) async { - final derivePath = cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: LelantusFfiWrapper.MINT_INDEX, - index: coin.mintIndex, - ); + final waitLelantusEntries = + lelantusCoins.map((coin) async { + final derivePath = cryptoCurrency.constructDerivePath( + derivePathType: DerivePathType.bip44, + chain: LelantusFfiWrapper.MINT_INDEX, + index: coin.mintIndex, + ); - try { - final keyPair = root.derivePath(derivePath); - final String privateKey = keyPair.privateKey.data.toHex; - return lelantus.DartLelantusEntry( - coin.isUsed ? 1 : 0, - 0, - coin.anonymitySetId, - int.parse(coin.value), - coin.mintIndex, - privateKey, - ); - } catch (e, s) { - Logging.instance.e("error bad key"); - Logging.instance.t("error bad key", error: e, stackTrace: s); - return lelantus.DartLelantusEntry(1, 0, 0, 0, 0, ''); - } - }).toList(); + try { + final keyPair = root.derivePath(derivePath); + final String privateKey = keyPair.privateKey.data.toHex; + return lelantus.DartLelantusEntry( + coin.isUsed ? 1 : 0, + 0, + coin.anonymitySetId, + int.parse(coin.value), + coin.mintIndex, + privateKey, + ); + } catch (e, s) { + Logging.instance.e("error bad key"); + Logging.instance.t("error bad key", error: e, stackTrace: s); + return lelantus.DartLelantusEntry(1, 0, 0, 0, 0, ''); + } + }).toList(); final lelantusEntries = await Future.wait(waitLelantusEntries); @@ -100,13 +104,9 @@ mixin LelantusInterface return lelantusEntries; } - Future prepareSendLelantus({ - required TxData txData, - }) async { + Future prepareSendLelantus({required TxData txData}) async { if (txData.recipients!.length != 1) { - throw Exception( - "Lelantus send requires a single recipient", - ); + throw Exception("Lelantus send requires a single recipient"); } if (txData.recipients!.first.amount.raw > @@ -125,8 +125,9 @@ mixin LelantusInterface isSendAll = true; } - final lastUsedIndex = - await mainDB.getHighestUsedMintIndex(walletId: walletId); + final lastUsedIndex = await mainDB.getHighestUsedMintIndex( + walletId: walletId, + ); final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; final root = await getRootHDNode(); @@ -174,18 +175,15 @@ mixin LelantusInterface } } - Future confirmSendLelantus({ - required TxData txData, - }) async { + Future confirmSendLelantus({required TxData txData}) async { final latestSetId = await electrumXClient.getLelantusLatestCoinId(); - final txid = await electrumXClient.broadcastTransaction( - rawTx: txData.raw!, - ); + final txid = await electrumXClient.broadcastTransaction(rawTx: txData.raw!); assert(txid == txData.txid!); - final lastUsedIndex = - await mainDB.getHighestUsedMintIndex(walletId: walletId); + final lastUsedIndex = await mainDB.getHighestUsedMintIndex( + walletId: walletId, + ); final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; if (txData.spendCoinIndexes != null) { @@ -197,10 +195,11 @@ mixin LelantusInterface // Update all of the coins that have been spent. for (final index in spentCoinIndexes) { - final possibleCoin = await mainDB.isar.lelantusCoins - .where() - .mintIndexWalletIdEqualTo(index, walletId) - .findFirst(); + final possibleCoin = + await mainDB.isar.lelantusCoins + .where() + .mintIndexWalletIdEqualTo(index, walletId) + .findFirst(); if (possibleCoin != null) { updatedCoins.add(possibleCoin.copyWith(isUsed: true)); @@ -232,11 +231,7 @@ mixin LelantusInterface await mainDB.isar.lelantusCoins.put(jmint); }); } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); rethrow; } @@ -264,7 +259,8 @@ mixin LelantusInterface numberOfMessages: null, ); - final transactionAddress = await mainDB + final transactionAddress = + await mainDB .getAddresses(walletId) .filter() .valueEqualTo(txData.recipients!.first.address) @@ -311,18 +307,12 @@ mixin LelantusInterface await mainDB.isar.lelantusCoins.putAll(updatedCoins); }); } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); rethrow; } } - return txData.copyWith( - txid: txid, - ); + return txData.copyWith(txid: txid); } Future>> fastFetch(List allTxHashes) async { @@ -334,10 +324,10 @@ mixin LelantusInterface for (final txHash in allTxHashes) { final Future> transactionFuture = electrumXCachedClient.getTransaction( - txHash: txHash, - verbose: true, - cryptoCurrency: cryptoCurrency, - ); + txHash: txHash, + verbose: true, + cryptoCurrency: cryptoCurrency, + ); transactionFutures.add(transactionFuture); currentFutureCount++; if (currentFutureCount > futureLimit) { @@ -373,8 +363,9 @@ mixin LelantusInterface ) async { try { final Map txs = {}; - final List> allTransactions = - await fastFetch(transactions); + final List> allTransactions = await fastFetch( + transactions, + ); for (int i = 0; i < allTransactions.length; i++) { try { @@ -397,16 +388,18 @@ mixin LelantusInterface final txn = Transaction( walletId: walletId, txid: tx["txid"] as String, - timestamp: tx["time"] as int? ?? + timestamp: + tx["time"] as int? ?? (DateTime.now().millisecondsSinceEpoch ~/ 1000), type: TransactionType.outgoing, subType: TransactionSubType.join, amount: amount.raw.toInt(), amountString: amount.toJsonString(), - fee: Amount.fromDecimal( - Decimal.parse(tx["fees"].toString()), - fractionDigits: cryptoCurrency.fractionDigits, - ).raw.toInt(), + fee: + Amount.fromDecimal( + Decimal.parse(tx["fees"].toString()), + fractionDigits: cryptoCurrency.fractionDigits, + ).raw.toInt(), height: tx["height"] as int?, isCancelled: false, isLelantus: true, @@ -418,7 +411,8 @@ mixin LelantusInterface numberOfMessages: null, ); - final address = await mainDB + final address = + await mainDB .getAddresses(walletId) .filter() .valueEqualTo(tx["address"] as String) @@ -488,8 +482,10 @@ mixin LelantusInterface final Map setDataMap = {}; final anonymitySets = await fetchAnonymitySets(); for (int setId = 1; setId <= latestSetId; setId++) { - final setData = anonymitySets - .firstWhere((element) => element["setId"] == setId, orElse: () => {}); + final setData = anonymitySets.firstWhere( + (element) => element["setId"] == setId, + orElse: () => {}, + ); if (setData.isNotEmpty) { setDataMap[setId] = setData; @@ -500,22 +496,22 @@ mixin LelantusInterface // TODO: verify this function does what we think it does Future refreshLelantusData() async { - final lelantusCoins = await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .valueEqualTo(0.toString()) - .findAll(); + final lelantusCoins = + await mainDB.isar.lelantusCoins + .where() + .walletIdEqualTo(walletId) + .filter() + .isUsedEqualTo(false) + .not() + .valueEqualTo(0.toString()) + .findAll(); final List updatedCoins = []; final usedSerialNumbersSet = (await electrumXCachedClient.getUsedCoinSerials( - cryptoCurrency: info.coin, - )) - .toSet(); + cryptoCurrency: info.coin, + )).toSet(); final root = await getRootHDNode(); @@ -563,11 +559,7 @@ mixin LelantusInterface await mainDB.isar.lelantusCoins.putAll(updatedCoins); }); } catch (e, s) { - Logging.instance.f( - " ", - error: e, - stackTrace: s, - ); + Logging.instance.f(" ", error: e, stackTrace: s); rethrow; } } @@ -607,13 +599,14 @@ mixin LelantusInterface final currentHeight = await chainHeight; - final txns = await mainDB - .getTransactions(walletId) - .filter() - .isLelantusIsNull() - .or() - .isLelantusEqualTo(false) - .findAll(); + final txns = + await mainDB + .getTransactions(walletId) + .filter() + .isLelantusIsNull() + .or() + .isLelantusEqualTo(false) + .findAll(); // TODO: [prio=high] shouldn't these be v2? If it doesn't matter than we can get rid of this logic // Edit the receive transactions with the mint fees. @@ -663,10 +656,11 @@ mixin LelantusInterface type: inputTx.type, subType: TransactionSubType.mint, amount: inputTx.amount, - amountString: Amount( - rawValue: BigInt.from(inputTx.amount), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + amountString: + Amount( + rawValue: BigInt.from(inputTx.amount), + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), fee: sharedFee, height: inputTx.height, isCancelled: false, @@ -706,11 +700,7 @@ mixin LelantusInterface await mainDB.isar.lelantusCoins.putAll(result.lelantusCoins); }); } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); // don't just rethrow since isar likes to strip stack traces for some reason throw Exception("e=$e & s=$s"); } @@ -722,13 +712,12 @@ mixin LelantusInterface } // Create the joinsplit transactions. - final spendTxs = await getJMintTransactions( - result.spendTxIds, - ); + final spendTxs = await getJMintTransactions(result.spendTxIds); Logging.instance.d("lelantus spendTxs: $spendTxs"); for (final element in spendTxs.entries) { - final address = element.value.address.value ?? + final address = + element.value.address.value ?? data[element.value.txid]?.item1 ?? element.key; // Address( @@ -747,8 +736,9 @@ mixin LelantusInterface for (final value in data.values) { final transactionAddress = value.item1!; - final outs = - value.item2.outputs.where((_) => true).toList(growable: false); + final outs = value.item2.outputs + .where((_) => true) + .toList(growable: false); final ins = value.item2.inputs.where((_) => true).toList(growable: false); txnsData.add( @@ -778,9 +768,7 @@ mixin LelantusInterface wif: cryptoCurrency.networkParams.wifPrefix, ); - final txb = bitcoindart.TransactionBuilder( - network: convertedNetwork, - ); + final txb = bitcoindart.TransactionBuilder(network: convertedNetwork); txb.setVersion(2); final int height = await chainHeight; @@ -794,42 +782,40 @@ mixin LelantusInterface switch (signingData[i].derivePathType) { case DerivePathType.bip44: - data = bitcoindart - .P2PKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; + data = + bitcoindart + .P2PKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip49: - final p2wpkh = bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; - data = bitcoindart - .P2SH( - data: bitcoindart.PaymentData(redeem: p2wpkh), - network: convertedNetwork, - ) - .data; + final p2wpkh = + bitcoindart + .P2WPKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; + data = + bitcoindart + .P2SH( + data: bitcoindart.PaymentData(redeem: p2wpkh), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip84: - data = bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData( - pubkey: pubKey, - ), - network: convertedNetwork, - ) - .data; + data = + bitcoindart + .P2WPKH( + data: bitcoindart.PaymentData(pubkey: pubKey), + network: convertedNetwork, + ) + .data; break; case DerivePathType.bip86: @@ -851,8 +837,9 @@ mixin LelantusInterface for (final mintsElement in txData.mintsMapLelantus!) { Logging.instance.d("using $mintsElement"); - final Uint8List mintu8 = - Format.stringToUint8List(mintsElement['script'] as String); + final Uint8List mintu8 = Format.stringToUint8List( + mintsElement['script'] as String, + ); txb.addOutput(mintu8, mintsElement['value'] as int); } @@ -922,11 +909,12 @@ mixin LelantusInterface /// Returns the mint transaction hex to mint all of the available funds. Future _mintSelection() async { final currentChainHeight = await chainHeight; - final List availableOutputs = await mainDB - .getUTXOs(walletId) - .filter() - .isBlockedEqualTo(false) - .findAll(); + final List availableOutputs = + await mainDB + .getUTXOs(walletId) + .filter() + .isBlockedEqualTo(false) + .findAll(); final List spendableOutputs = []; // Build list of spendable outputs and totaling their satoshi amount @@ -944,21 +932,23 @@ mixin LelantusInterface } } - final lelantusCoins = await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .not() - .valueEqualTo(0.toString()) - .findAll(); - - final data = await mainDB - .getTransactions(walletId) - .filter() - .isLelantusIsNull() - .or() - .isLelantusEqualTo(false) - .findAll(); + final lelantusCoins = + await mainDB.isar.lelantusCoins + .where() + .walletIdEqualTo(walletId) + .filter() + .not() + .valueEqualTo(0.toString()) + .findAll(); + + final data = + await mainDB + .getTransactions(walletId) + .filter() + .isLelantusIsNull() + .or() + .isLelantusEqualTo(false) + .findAll(); for (final value in data) { if (value.inputs.isNotEmpty) { @@ -969,8 +959,9 @@ mixin LelantusInterface orElse: () => null, ) != null) { - spendableOutputs - .removeWhere((output) => output!.txid == element.txid); + spendableOutputs.removeWhere( + (output) => output!.txid == element.txid, + ); } } } @@ -1005,10 +996,11 @@ mixin LelantusInterface final feesObject = await fees; - final Decimal fastFee = Amount( - rawValue: BigInt.from(feesObject.fast), - fractionDigits: cryptoCurrency.fractionDigits, - ).decimal; + final Decimal fastFee = + Amount( + rawValue: feesObject.fast, + fractionDigits: cryptoCurrency.fractionDigits, + ).decimal; int firoFee = (dvSize * fastFee * Decimal.fromInt(100000)).toDouble().ceil(); // int firoFee = (vSize * feesObject.fast * (1 / 1000.0) * 100000000).ceil(); @@ -1022,9 +1014,7 @@ mixin LelantusInterface final mintsWithFee = await _createMintsFromAmount(satoshiAmountToSend); txData = await buildMintTransaction( - txData: txData.copyWith( - mintsMapLelantus: mintsWithFee, - ), + txData: txData.copyWith(mintsMapLelantus: mintsWithFee), ); return txData; @@ -1039,8 +1029,9 @@ mixin LelantusInterface int tmpTotal = total; int counter = 0; - final lastUsedIndex = - await mainDB.getHighestUsedMintIndex(walletId: walletId); + final lastUsedIndex = await mainDB.getHighestUsedMintIndex( + walletId: walletId, + ); final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; final isTestnet = cryptoCurrency.network.isTestNet; @@ -1118,12 +1109,9 @@ mixin LelantusInterface isTestNet: isTestnet, ); - mints.add({ - "value": mintValue, - "script": mint, - "index": index, - }); - tmpTotal = tmpTotal - + mints.add({"value": mintValue, "script": mint, "index": index}); + tmpTotal = + tmpTotal - (isTestnet ? LelantusFfiWrapper.MINT_LIMIT_TESTNET : LelantusFfiWrapper.MINT_LIMIT); @@ -1156,32 +1144,29 @@ mixin LelantusInterface // call to super to update transparent balance final normalBalanceFuture = super.updateBalance(); - final lelantusCoins = await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .valueEqualTo(0.toString()) - .findAll(); + final lelantusCoins = + await mainDB.isar.lelantusCoins + .where() + .walletIdEqualTo(walletId) + .filter() + .isUsedEqualTo(false) + .not() + .valueEqualTo(0.toString()) + .findAll(); final currentChainHeight = await chainHeight; int intLelantusBalance = 0; int unconfirmedLelantusBalance = 0; for (final lelantusCoin in lelantusCoins) { - final Transaction? txn = mainDB.isar.transactions - .where() - .txidWalletIdEqualTo( - lelantusCoin.txid, - walletId, - ) - .findFirstSync(); + final Transaction? txn = + mainDB.isar.transactions + .where() + .txidWalletIdEqualTo(lelantusCoin.txid, walletId) + .findFirstSync(); if (txn == null) { - Logging.instance.e( - "Transaction not found in DB for lelantus coin", - ); + Logging.instance.e("Transaction not found in DB for lelantus coin"); Logging.instance.d( "Transaction not found in DB for lelantus coin: $lelantusCoin", ); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart index 1d725afb4..4c3233de7 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart @@ -28,9 +28,7 @@ import '../intermediate/bip39_wallet.dart'; const _kWorkServer = "https://nodes.nanswap.com/XNO"; Map _buildHeaders(String url) { - final result = { - 'Content-type': 'application/json', - }; + final result = {'Content-type': 'application/json'}; if (url case "https://nodes.nanswap.com/XNO" || "https://nodes.nanswap.com/BAN") { result["nodes-api-key"] = kNanoSwapRpcApiKey; @@ -52,28 +50,24 @@ mixin NanoInterface on Bip39Wallet { _hackedCheckTorNodePrefs(); return _httpClient .post( - url: Uri.parse(_kWorkServer), // this should be a - headers: _buildHeaders(_kWorkServer), - body: json.encode( - { - "action": "work_generate", - "hash": hash, - }, - ), - proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null, - ) + url: Uri.parse(_kWorkServer), // this should be a + headers: _buildHeaders(_kWorkServer), + body: json.encode({"action": "work_generate", "hash": hash}), + proxyInfo: + prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null, + ) .then((_httpClient) { - if (_httpClient.code == 200) { - final Map decoded = - json.decode(_httpClient.body) as Map; - if (decoded.containsKey("error")) { - throw Exception("Received error ${decoded["error"]}"); - } - return decoded["work"] as String?; - } else { - throw Exception("Received error ${_httpClient.code}"); - } - }); + if (_httpClient.code == 200) { + final Map decoded = + json.decode(_httpClient.body) as Map; + if (decoded.containsKey("error")) { + throw Exception("Received error ${decoded["error"]}"); + } + return decoded["work"] as String?; + } else { + throw Exception("Received error ${_httpClient.code}"); + } + }); } Future _getPrivateKeyFromMnemonic() async { @@ -87,8 +81,10 @@ mixin NanoInterface on Bip39Wallet { await _getPrivateKeyFromMnemonic(), ); - final addressString = - NanoAccounts.createAccount(cryptoCurrency.nanoAccountType, publicKey); + final addressString = NanoAccounts.createAccount( + cryptoCurrency.nanoAccountType, + publicKey, + ); return Address( walletId: walletId, @@ -146,8 +142,9 @@ mixin NanoInterface on Bip39Wallet { ); final balanceData = jsonDecode(balanceResponse.body); - final BigInt currentBalance = - BigInt.parse(balanceData["balance"].toString()); + final BigInt currentBalance = BigInt.parse( + balanceData["balance"].toString(), + ); final BigInt txAmount = BigInt.parse(amountRaw); final BigInt balanceAfterTx = currentBalance + txAmount; @@ -162,16 +159,19 @@ mixin NanoInterface on Bip39Wallet { // link = send block hash: final String link = blockHash; // this "linkAsAccount" is meaningless: - final String linkAsAccount = - NanoAccounts.createAccount(NanoAccountType.BANANO, blockHash); + final String linkAsAccount = NanoAccounts.createAccount( + NanoAccountType.BANANO, + blockHash, + ); // construct the receive block: final Map receiveBlock = { "type": "state", "account": publicAddress, - "previous": openBlock - ? "0000000000000000000000000000000000000000000000000000000000000000" - : frontier, + "previous": + openBlock + ? "0000000000000000000000000000000000000000000000000000000000000000" + : frontier, "representative": representative, "balance": balanceAfterTx.toString(), "link": link, @@ -320,8 +320,10 @@ mixin NanoInterface on Bip39Wallet { @override Future updateNode() async { - _cachedNode = NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? + _cachedNode = + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? info.coin.defaultNode; unawaited(refresh()); @@ -330,8 +332,9 @@ mixin NanoInterface on Bip39Wallet { @override NodeModel getCurrentNode() { return _cachedNode ?? - NodeService(secureStorageInterface: secureStorageInterface) - .getPrimaryNodeFor(currency: info.coin) ?? + NodeService( + secureStorageInterface: secureStorageInterface, + ).getPrimaryNodeFor(currency: info.coin) ?? info.coin.defaultNode; } @@ -365,11 +368,7 @@ mixin NanoInterface on Bip39Wallet { final response = await _httpClient.post( url: uri, headers: _buildHeaders(node.host), - body: jsonEncode( - { - "action": "version", - }, - ), + body: jsonEncode({"action": "version"}), proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null, ); @@ -485,15 +484,9 @@ mixin NanoInterface on Bip39Wallet { } // return the hash of the transaction: - return txData.copyWith( - txid: decoded["hash"].toString(), - ); + return txData.copyWith(txid: decoded["hash"].toString()); } catch (e, s) { - Logging.instance.e( - "Error sending transaction", - error: e, - stackTrace: s, - ); + Logging.instance.e("Error sending transaction", error: e, stackTrace: s); rethrow; } } @@ -544,8 +537,9 @@ mixin NanoInterface on Bip39Wallet { ); // this should really have proper type checking and error propagation but I'm out of time - final newData = - Map.from((await jsonDecode(response.body)) as Map); + final newData = Map.from( + (await jsonDecode(response.body)) as Map, + ); if (newData["previous"] is String) { if (data?["history"] is List) { @@ -572,9 +566,10 @@ mixin NanoInterface on Bip39Wallet { final data = await _fetchAll(publicAddress, null, null); - final transactions = data["history"] is List - ? data["history"] as List - : []; + final transactions = + data["history"] is List + ? data["history"] as List + : []; if (transactions.isEmpty) { return; } else { @@ -612,17 +607,18 @@ mixin NanoInterface on Bip39Wallet { numberOfMessages: null, ); - final Address address = transactionType == TransactionType.incoming - ? receivingAddress - : Address( - walletId: walletId, - publicKey: [], - value: tx["account"].toString(), - derivationIndex: 0, - derivationPath: null, - type: info.mainAddressType, - subType: AddressSubType.nonWallet, - ); + final Address address = + transactionType == TransactionType.incoming + ? receivingAddress + : Address( + walletId: walletId, + publicKey: [], + value: tx["account"].toString(), + derivationIndex: 0, + derivationPath: null, + type: info.mainAddressType, + subType: AddressSubType.nonWallet, + ); final Tuple2 tuple = Tuple2(transaction, address); transactionList.add(tuple); } @@ -653,8 +649,9 @@ mixin NanoInterface on Bip39Wallet { final data = jsonDecode(response.body); final balance = Balance( total: Amount( - rawValue: (BigInt.parse(data["balance"].toString()) + - BigInt.parse(data["receivable"].toString())), + rawValue: + (BigInt.parse(data["balance"].toString()) + + BigInt.parse(data["receivable"].toString())), fractionDigits: cryptoCurrency.fractionDigits, ), spendable: Amount( @@ -703,10 +700,8 @@ mixin NanoInterface on Bip39Wallet { ); final infoData = jsonDecode(infoResponse.body); - final height = int.tryParse( - infoData["confirmation_height"].toString(), - ) ?? - 0; + final height = + int.tryParse(infoData["confirmation_height"].toString()) ?? 0; await info.updateCachedChainHeight(newHeight: height, isar: mainDB.isar); } catch (e, s) { @@ -734,21 +729,21 @@ mixin NanoInterface on Bip39Wallet { @override // nano has no fees - Future estimateFeeFor(Amount amount, int feeRate) async => Amount( - rawValue: BigInt.from(0), - fractionDigits: cryptoCurrency.fractionDigits, - ); + Future estimateFeeFor(Amount amount, BigInt feeRate) async => Amount( + rawValue: BigInt.from(0), + fractionDigits: cryptoCurrency.fractionDigits, + ); @override // nano has no fees Future get fees async => FeeObject( - numberOfBlocksFast: 1, - numberOfBlocksAverage: 1, - numberOfBlocksSlow: 1, - fast: 0, - medium: 0, - slow: 0, - ); + numberOfBlocksFast: 1, + numberOfBlocksAverage: 1, + numberOfBlocksSlow: 1, + fast: BigInt.zero, + medium: BigInt.zero, + slow: BigInt.zero, + ); void _hackedCheckTorNodePrefs() { final node = getCurrentNode(); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart index 5c0ace879..1bfb3a2a3 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart @@ -457,7 +457,7 @@ mixin PaynymInterface } Future prepareNotificationTx({ - required int selectedTxFeeRate, + required BigInt selectedTxFeeRate, required String targetPaymentCodeString, int additionalOutputs = 0, List? utxos, diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart index 1840e04d9..b6fb74c7c 100644 --- a/lib/widgets/desktop/desktop_fee_dialog.dart +++ b/lib/widgets/desktop/desktop_fee_dialog.dart @@ -43,7 +43,7 @@ class _DesktopFeeDialogState extends ConsumerState { Future feeFor({ required Amount amount, required FeeRateType feeRateType, - required int feeRate, + required BigInt feeRate, required CryptoCurrency coin, }) async { switch (feeRateType) { @@ -62,7 +62,7 @@ class _DesktopFeeDialogState extends ConsumerState { if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.high.value, + BigInt.from(lib_monero.TransactionPriority.high.value), ); ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; } else if (coin is Firo) { @@ -116,7 +116,7 @@ class _DesktopFeeDialogState extends ConsumerState { if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.medium.value, + BigInt.from(lib_monero.TransactionPriority.medium.value), ); ref.read(feeSheetSessionCacheProvider).average[amount] = fee; } else if (coin is Firo) { @@ -170,7 +170,7 @@ class _DesktopFeeDialogState extends ConsumerState { if (coin is Monero || coin is Wownero) { final fee = await wallet.estimateFeeFor( amount, - lib_monero.TransactionPriority.normal.value, + BigInt.from(lib_monero.TransactionPriority.normal.value), ); ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; } else if (coin is Firo) { @@ -291,7 +291,7 @@ class DesktopFeeItem extends ConsumerStatefulWidget { final Future Function({ required Amount amount, required FeeRateType feeRateType, - required int feeRate, + required BigInt feeRate, required CryptoCurrency coin, }) feeFor; diff --git a/test/models/fee_object_model_test.dart b/test/models/fee_object_model_test.dart index 52045d662..1f108d531 100644 --- a/test/models/fee_object_model_test.dart +++ b/test/models/fee_object_model_test.dart @@ -4,27 +4,16 @@ import 'package:stackwallet/models/models.dart'; void main() { test("FeeObject constructor", () { final feeObject = FeeObject( - fast: 3, - medium: 2, - slow: 1, + fast: BigInt.from(3), + medium: BigInt.from(2), + slow: BigInt.from(1), numberOfBlocksFast: 4, numberOfBlocksSlow: 5, numberOfBlocksAverage: 10, ); - expect(feeObject.toString(), - "{fast: 3, medium: 2, slow: 1, numberOfBlocksFast: 4, numberOfBlocksAverage: 10, numberOfBlocksSlow: 5}"); - }); - - test("FeeObject.fromJson factory", () { - final feeObject = FeeObject.fromJson({ - "fast": 3, - "average": 2, - "slow": 1, - "numberOfBlocksFast": 4, - "numberOfBlocksSlow": 5, - "numberOfBlocksAverage": 6, - }); - expect(feeObject.toString(), - "{fast: 3, medium: 2, slow: 1, numberOfBlocksFast: 4, numberOfBlocksAverage: 6, numberOfBlocksSlow: 5}"); + expect( + feeObject.toString(), + "{fast: 3, medium: 2, slow: 1, numberOfBlocksFast: 4, numberOfBlocksAverage: 10, numberOfBlocksSlow: 5}", + ); }); } From 289cc95cea9f0f18cc67408ada8f62ac0a3f6bda Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Apr 2025 15:52:38 -0600 Subject: [PATCH 021/206] fix token fee display issue --- .../wallet_view/sub_widgets/desktop_send.dart | 1 + .../sub_widgets/desktop_send_fee_form.dart | 125 +++++++++++------- .../sub_widgets/desktop_token_send.dart | 1 + 3 files changed, 78 insertions(+), 49 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 3aed8ba95..e11a55ff5 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -1632,6 +1632,7 @@ class _DesktopSendState extends ConsumerState { if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) DesktopSendFeeForm( walletId: walletId, + isToken: false, onCustomFeeSliderChanged: (value) => customFeeRate = value, onCustomFeeOptionChanged: (value) => isCustomFee = value, ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 62989f1dc..28c385bfd 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; import '../../../../providers/providers.dart'; +import '../../../../providers/wallet/desktop_fee_providers.dart'; import '../../../../providers/wallet/public_private_balance_state_provider.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/amount/amount.dart'; @@ -12,6 +13,7 @@ import '../../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../wallets/crypto_currency/interfaces/electrumx_currency_interface.dart'; +import '../../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../../widgets/animated_text.dart'; @@ -25,11 +27,13 @@ class DesktopSendFeeForm extends ConsumerStatefulWidget { const DesktopSendFeeForm({ super.key, required this.walletId, + required this.isToken, required this.onCustomFeeSliderChanged, required this.onCustomFeeOptionChanged, }); final String walletId; + final bool isToken; final void Function(int) onCustomFeeSliderChanged; final void Function(bool) onCustomFeeOptionChanged; @@ -86,8 +90,10 @@ class _DesktopSendFeeFormState extends ConsumerState { await showDialog<(FeeRateType, String?, String?)?>( context: context, builder: - (_) => - DesktopFeeDialog(walletId: widget.walletId), + (_) => DesktopFeeDialog( + walletId: widget.walletId, + isToken: widget.isToken, + ), ); if (feeSelectionResult != null) { @@ -144,69 +150,90 @@ class _DesktopSendFeeFormState extends ConsumerState { required CryptoCurrency coin, }) async { if (ref - .read(feeSheetSessionCacheProvider) + .read( + widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider, + ) .average[amount] == null) { - final wallet = ref - .read(pWallets) - .getWallet(widget.walletId); + if (widget.isToken == false) { + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - BigInt.from( - lib_monero - .TransactionPriority - .medium - .value, - ), - ); - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - fee; - } else if ((coin is Firo) && + if (coin is Monero || coin is Wownero) { + final fee = await wallet.estimateFeeFor( + amount, + BigInt.from( + lib_monero + .TransactionPriority + .medium + .value, + ), + ); ref + .read(feeSheetSessionCacheProvider) + .average[amount] = + fee; + } else if ((coin is Firo) && + ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) { + final firoWallet = wallet as FiroWallet; + + if (ref .read( publicPrivateBalanceStateProvider .state, ) - .state != - FiroType.public) { - final firoWallet = wallet as FiroWallet; - - if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.lelantus) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await firoWallet - .estimateFeeForLelantus(amount); - } else if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.spark) { + .state == + FiroType.lelantus) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForLelantus(amount); + } else if (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state == + FiroType.spark) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForSpark(amount); + } + } else { ref .read(feeSheetSessionCacheProvider) - .average[amount] = await firoWallet - .estimateFeeForSpark(amount); + .average[amount] = await wallet + .estimateFeeFor(amount, feeRate); } } else { + final tokenWallet = + ref.read(pCurrentTokenWallet)!; + final fee = await tokenWallet.estimateFeeFor( + amount, + feeRate, + ); ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await wallet - .estimateFeeFor(amount, feeRate); + .read(tokenFeeSessionCacheProvider) + .average[amount] = + fee; } } return ref - .read(feeSheetSessionCacheProvider) + .read( + widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider, + ) .average[amount]!; }, isSelected: true, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 1f346dd1a..45fcfc42a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -1026,6 +1026,7 @@ class _DesktopTokenSendState extends ConsumerState { const SizedBox(height: 20), DesktopSendFeeForm( walletId: walletId, + isToken: true, onCustomFeeSliderChanged: (value) => {}, onCustomFeeOptionChanged: (value) {}, ), From ec4f7d80e012199c94161c281bf381fdc97caec5 Mon Sep 17 00:00:00 2001 From: dethe <76167420+detherminal@users.noreply.github.com> Date: Tue, 8 Apr 2025 23:23:01 +0300 Subject: [PATCH 022/206] feat: add block height option to scanned coins --- .../name_your_wallet_view.dart | 2 +- .../restore_options_view.dart | 277 ++++++++++++++++-- .../restore_view_only_wallet_view.dart | 21 +- .../restore_wallet_view.dart | 39 +-- lib/route_generator.dart | 8 +- 5 files changed, 261 insertions(+), 86 deletions(-) diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index f17ed06ff..7f867d505 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -322,7 +322,7 @@ class _NameYourWalletViewState extends ConsumerState { ) : Semantics( label: - "Generate Random Wallet Name Button. Generates A Random Name For Wallet.", + "Clear Block Height Field Button. Clears the block height field.", excludeSemantics: true, child: XIcon( width: isDesktop ? 21 : 18, diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index 384cacb0c..b4a7d3231 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -12,6 +12,7 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:logger/logger.dart'; import 'package:tuple/tuple.dart'; import '../../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; @@ -20,6 +21,7 @@ import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/format.dart'; +import '../../../../utilities/logger.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; @@ -27,13 +29,16 @@ import '../../../../wallets/crypto_currency/interfaces/view_only_option_currency import '../../../../wallets/crypto_currency/intermediate/cryptonote_currency.dart'; import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../../widgets/custom_buttons/checkbox_text_button.dart'; import '../../../../widgets/date_picker/date_picker.dart'; import '../../../../widgets/desktop/desktop_app_bar.dart'; import '../../../../widgets/desktop/desktop_scaffold.dart'; import '../../../../widgets/expandable.dart'; +import '../../../../widgets/icon_widgets/x_icon.dart'; import '../../../../widgets/rounded_white_container.dart'; import '../../../../widgets/stack_text_field.dart'; +import '../../../../widgets/textfield_icon_button.dart'; import '../../../../widgets/toggle.dart'; import '../../create_or_restore_wallet_view/sub_widgets/coin_image.dart'; import '../restore_view_only_wallet_view.dart'; @@ -44,6 +49,8 @@ import 'sub_widgets/restore_from_date_picker.dart'; import 'sub_widgets/restore_options_next_button.dart'; import 'sub_widgets/restore_options_platform_layout.dart'; +import 'package:cs_monero/src/deprecated/get_height_by_date.dart' as cs_monero_deprecated; + class RestoreOptionsView extends ConsumerStatefulWidget { const RestoreOptionsView({ super.key, @@ -66,6 +73,9 @@ class _RestoreOptionsViewState extends ConsumerState { late final bool isDesktop; late TextEditingController _dateController; + late TextEditingController _blockHeightController; + late FocusNode _blockHeightFocusNode; + final ValueNotifier _isUsingDateNotifier = ValueNotifier(true); late FocusNode textFieldFocusNode; late final FocusNode passwordFocusNode; late final TextEditingController passwordController; @@ -89,6 +99,9 @@ class _RestoreOptionsViewState extends ConsumerState { textFieldFocusNode = FocusNode(); passwordController = TextEditingController(); passwordFocusNode = FocusNode(); + _blockHeightController = TextEditingController(); + _blockHeightFocusNode = FocusNode(); + _isUsingDateNotifier.value = true; super.initState(); } @@ -96,6 +109,7 @@ class _RestoreOptionsViewState extends ConsumerState { @override void dispose() { _dateController.dispose(); + _blockHeightController.dispose(); textFieldFocusNode.dispose(); passwordController.dispose(); passwordFocusNode.dispose(); @@ -116,6 +130,12 @@ class _RestoreOptionsViewState extends ConsumerState { } if (mounted) { + int height = 0; + if (_isUsingDateNotifier.value) { + height = getBlockHeightFromDate(_restoreFromDate); + } else { + height = int.tryParse(_blockHeightController.text) ?? 0; + } if (!_showViewOnlyOption) { await Navigator.of(context).pushNamed( RestoreWalletView.routeName, @@ -123,7 +143,7 @@ class _RestoreOptionsViewState extends ConsumerState { walletName, coin, ref.read(mnemonicWordCountStateProvider.state).state, - _restoreFromDate, + height, passwordController.text, enableLelantusScanning, ), @@ -134,7 +154,7 @@ class _RestoreOptionsViewState extends ConsumerState { arguments: ( walletName: walletName, coin: coin, - restoreFromDate: _restoreFromDate, + restoreBlockHeight: height, enableLelantusScanning: enableLelantusScanning, ), ); @@ -186,6 +206,48 @@ class _RestoreOptionsViewState extends ConsumerState { ); } + int getBlockHeightFromDate(DateTime? date) { + try { + int height = 0; + if (date != null) { + if (widget.coin is Monero) { + height = cs_monero_deprecated.getMoneroHeightByDate( + date: date, + ); + } + if (widget.coin is Wownero) { + height = cs_monero_deprecated.getWowneroHeightByDate( + date: date, + ); + } + if (height < 0) { + height = 0; + } + + if (widget.coin is Epiccash) { + final int secondsSinceEpoch = + date.millisecondsSinceEpoch ~/ 1000; + const int epicCashFirstBlock = 1565370278; + const double overestimateSecondsPerBlock = 61; + final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock; + final int approximateHeight = + chosenSeconds ~/ overestimateSecondsPerBlock; + + height = approximateHeight; + if (height < 0) { + height = 0; + } + } + } else { + height = 0; + } + return height; + } catch (e) { + Logging.instance.log(Level.info, "Error getting block height from date: $e"); + return 0; + } + } + bool _showViewOnlyOption = false; @override @@ -281,10 +343,16 @@ class _RestoreOptionsViewState extends ConsumerState { dateController: _dateController, dateChooserFunction: isDesktop ? chooseDesktopDate : chooseDate, + blockHeightController: _blockHeightController, + blockHeightFocusNode: _blockHeightFocusNode, + isUsingDateNotifier: _isUsingDateNotifier, ) : SeedRestoreOption( coin: coin, dateController: _dateController, + blockHeightController: _blockHeightController, + blockHeightFocusNode: _blockHeightFocusNode, + isUsingDateNotifier: _isUsingDateNotifier, pwController: passwordController, pwFocusNode: passwordFocusNode, supportsMnemonicPassphrase: supportsMnemonicPassphrase, @@ -324,6 +392,9 @@ class SeedRestoreOption extends ConsumerStatefulWidget { super.key, required this.coin, required this.dateController, + required this.blockHeightController, + required this.blockHeightFocusNode, + required this.isUsingDateNotifier, required this.pwController, required this.pwFocusNode, required this.supportsMnemonicPassphrase, @@ -334,6 +405,9 @@ class SeedRestoreOption extends ConsumerStatefulWidget { final CryptoCurrency coin; final TextEditingController dateController; + final TextEditingController blockHeightController; + final FocusNode blockHeightFocusNode; + final ValueNotifier isUsingDateNotifier; final TextEditingController pwController; final FocusNode pwFocusNode; final bool supportsMnemonicPassphrase; @@ -350,6 +424,7 @@ class _SeedRestoreOptionState extends ConsumerState { bool _hidePassword = true; bool _expandedAdvanced = false; bool _enableLelantusScanning = false; + bool _blockFieldEmpty = true; @override Widget build(BuildContext context) { @@ -363,25 +438,86 @@ class _SeedRestoreOptionState extends ConsumerState { return Column( children: [ if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - Text( - "Choose start date", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), - textAlign: TextAlign.left, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.isUsingDateNotifier.value + ? "Choose start date" + : "Block height", + style: Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + CustomTextButton( + text: widget.isUsingDateNotifier.value + ? "Use block height" + : "Use date", + onTap: () { + setState(() { + widget.isUsingDateNotifier.value = + !widget.isUsingDateNotifier.value; + }); + }, + ), + ], ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) SizedBox( height: Util.isDesktop ? 16 : 8, ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + widget.isUsingDateNotifier.value ? RestoreFromDatePicker( onTap: widget.dateChooserFunction, controller: widget.dateController, - ), + ) : + TextField( + focusNode: widget.blockHeightFocusNode, + controller: widget.blockHeightController, + keyboardType: TextInputType.number, + textInputAction: TextInputAction.done, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + onChanged: (value) { + setState(() { + _blockFieldEmpty = value.isEmpty; + }); + }, + decoration: standardInputDecoration( + "Start scanning from...", + widget.blockHeightFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: TextFieldIconButton(child: + Semantics( + label: "Clear Block Height Field Button. Clears the block height field", + excludeSemantics: true, + child: !_blockFieldEmpty + ? XIcon( + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) + : const SizedBox.shrink(), + ), + onTap: () { + widget.blockHeightController.text = ""; + setState(() { + _blockFieldEmpty = true; + }); + }, + ), + ), + ), + ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) const SizedBox( height: 8, @@ -390,7 +526,9 @@ class _SeedRestoreOptionState extends ConsumerState { RoundedWhiteContainer( child: Center( child: Text( - "Choose the date you made the wallet (approximate is fine)", + widget.isUsingDateNotifier.value + ? "Choose the date you made the wallet (approximate is fine)" + : "Enter the initial block height of the wallet", style: Util.isDesktop ? STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of(context) @@ -635,6 +773,15 @@ class _SeedRestoreOptionState extends ConsumerState { ], ); } + + @override + void initState() { + super.initState(); + + setState(() { + _blockFieldEmpty = widget.blockHeightController.text.isEmpty; + }); + } } class ViewOnlyRestoreOption extends StatefulWidget { @@ -643,10 +790,16 @@ class ViewOnlyRestoreOption extends StatefulWidget { required this.coin, required this.dateController, required this.dateChooserFunction, + required this.blockHeightController, + required this.blockHeightFocusNode, + required this.isUsingDateNotifier, }); final CryptoCurrency coin; final TextEditingController dateController; + final TextEditingController blockHeightController; + final FocusNode blockHeightFocusNode; + final ValueNotifier isUsingDateNotifier; final Future Function() dateChooserFunction; @@ -655,31 +808,90 @@ class ViewOnlyRestoreOption extends StatefulWidget { } class _ViewOnlyRestoreOptionState extends State { + bool _blockFieldEmpty = true; + @override Widget build(BuildContext context) { final showDateOption = widget.coin is CryptonoteCurrency; return Column( children: [ if (showDateOption) - Text( - "Choose start date", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), - textAlign: TextAlign.left, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.isUsingDateNotifier.value + ? "Choose start date" + : "Block height", + style: Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + CustomTextButton( + text: widget.isUsingDateNotifier.value + ? "Use block height" + : "Use date", + onTap: () { + setState(() { + widget.isUsingDateNotifier.value = + !widget.isUsingDateNotifier.value; + }); + }, + ), + ], ), if (showDateOption) SizedBox( height: Util.isDesktop ? 16 : 8, ), if (showDateOption) - RestoreFromDatePicker( - onTap: widget.dateChooserFunction, - controller: widget.dateController, - ), + widget.isUsingDateNotifier.value + ? RestoreFromDatePicker( + onTap: widget.dateChooserFunction, + controller: widget.dateController, + ) + : TextField( + focusNode: widget.blockHeightFocusNode, + controller: widget.blockHeightController, + keyboardType: TextInputType.number, + textInputAction: TextInputAction.done, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + decoration: standardInputDecoration( + "Start scanning from...", + widget.blockHeightFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: TextFieldIconButton( + child: Semantics( + label: + "Clear Block Height Field Button. Clears the block height field", + excludeSemantics: true, + child: !_blockFieldEmpty + ? XIcon( + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) + : const SizedBox.shrink(), + ), + onTap: () { + widget.blockHeightController.text = ""; + setState(() { + _blockFieldEmpty = true; + }); + }, + ), + ), + ), + ), if (showDateOption) const SizedBox( height: 8, @@ -688,7 +900,9 @@ class _ViewOnlyRestoreOptionState extends State { RoundedWhiteContainer( child: Center( child: Text( - "Choose the date you made the wallet (approximate is fine)", + widget.isUsingDateNotifier.value + ? "Choose the date you made the wallet (approximate is fine)" + : "Enter the initial block height of the wallet", style: Util.isDesktop ? STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of(context) @@ -708,4 +922,13 @@ class _ViewOnlyRestoreOptionState extends State { ], ); } + + @override + void initState() { + super.initState(); + + setState(() { + _blockFieldEmpty = widget.blockHeightController.text.isEmpty; + }); + } } diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart index 9123b2f46..b4b7d03e3 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart @@ -51,7 +51,7 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { super.key, required this.walletName, required this.coin, - required this.restoreFromDate, + required this.restoreBlockHeight, this.enableLelantusScanning = false, this.barcodeScanner = const BarcodeScannerWrapper(), this.clipboard = const ClipboardWrapper(), @@ -61,7 +61,7 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { final String walletName; final CryptoCurrency coin; - final DateTime? restoreFromDate; + final int restoreBlockHeight; final bool enableLelantusScanning; final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @@ -114,7 +114,6 @@ class _RestoreViewOnlyWalletViewState } Future _attemptRestore() async { - int height = 0; final Map otherDataJson = { WalletInfoKeys.isViewOnlyKey: true, }; @@ -134,20 +133,6 @@ class _RestoreViewOnlyWalletViewState ? ViewOnlyWalletType.addressOnly : ViewOnlyWalletType.xPub; } else if (widget.coin is CryptonoteCurrency) { - if (widget.restoreFromDate != null) { - if (widget.coin is Monero) { - height = cs_monero_deprecated.getMoneroHeightByDate( - date: widget.restoreFromDate!, - ); - } - if (widget.coin is Wownero) { - height = cs_monero_deprecated.getWowneroHeightByDate( - date: widget.restoreFromDate!, - ); - } - if (height < 0) height = 0; - } - viewOnlyWalletType = ViewOnlyWalletType.cryptonote; } else { throw Exception( @@ -163,7 +148,7 @@ class _RestoreViewOnlyWalletViewState final info = WalletInfo.createNew( coin: widget.coin, name: widget.walletName, - restoreHeight: height, + restoreHeight: widget.restoreBlockHeight, otherDataJsonString: jsonEncode(otherDataJson), ); diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 972012c00..59d479112 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -17,8 +17,6 @@ import 'dart:math'; import 'package:bip39/bip39.dart' as bip39; import 'package:bip39/src/wordlists/english.dart' as bip39wordlist; import 'package:cs_monero/cs_monero.dart' as lib_monero; -import 'package:cs_monero/src/deprecated/get_height_by_date.dart' - as cs_monero_deprecated; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -79,7 +77,7 @@ class RestoreWalletView extends ConsumerStatefulWidget { required this.coin, required this.seedWordsLength, required this.mnemonicPassphrase, - required this.restoreFromDate, + required this.restoreBlockHeight, this.enableLelantusScanning = false, this.barcodeScanner = const BarcodeScannerWrapper(), this.clipboard = const ClipboardWrapper(), @@ -91,7 +89,7 @@ class RestoreWalletView extends ConsumerStatefulWidget { final CryptoCurrency coin; final String mnemonicPassphrase; final int seedWordsLength; - final DateTime? restoreFromDate; + final int restoreBlockHeight; final bool enableLelantusScanning; final BarcodeScannerInterface barcodeScanner; @@ -233,42 +231,11 @@ class _RestoreWalletViewState extends ConsumerState { } mnemonic = mnemonic.trim(); - int height = 0; + final int height = widget.restoreBlockHeight; String? otherDataJsonString; - if (widget.restoreFromDate != null) { - if (widget.coin is Monero) { - height = cs_monero_deprecated.getMoneroHeightByDate( - date: widget.restoreFromDate!, - ); - } - if (widget.coin is Wownero) { - height = cs_monero_deprecated.getWowneroHeightByDate( - date: widget.restoreFromDate!, - ); - } - if (height < 0) { - height = 0; - } - } - // TODO: make more robust estimate of date maybe using https://explorer.epic.tech/api-index if (widget.coin is Epiccash) { - if (widget.restoreFromDate != null) { - final int secondsSinceEpoch = - widget.restoreFromDate!.millisecondsSinceEpoch ~/ 1000; - const int epicCashFirstBlock = 1565370278; - const double overestimateSecondsPerBlock = 61; - final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock; - final int approximateHeight = - chosenSeconds ~/ overestimateSecondsPerBlock; - - height = approximateHeight; - } - if (height < 0) { - height = 0; - } - otherDataJsonString = jsonEncode( { WalletInfoKeys.epiccashData: jsonEncode( diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 6695a53b8..eaa8c1c06 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -1554,14 +1554,14 @@ class RouteGenerator { case RestoreWalletView.routeName: if (args - is Tuple6) { + is Tuple6) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => RestoreWalletView( walletName: args.item1, coin: args.item2, seedWordsLength: args.item3, - restoreFromDate: args.item4, + restoreBlockHeight: args.item4, mnemonicPassphrase: args.item5, enableLelantusScanning: args.item6 ?? false, ), @@ -1576,7 +1576,7 @@ class RouteGenerator { if (args is ({ String walletName, CryptoCurrency coin, - DateTime? restoreFromDate, + int restoreBlockHeight, bool enableLelantusScanning, })) { return getRoute( @@ -1584,7 +1584,7 @@ class RouteGenerator { builder: (_) => RestoreViewOnlyWalletView( walletName: args.walletName, coin: args.coin, - restoreFromDate: args.restoreFromDate, + restoreBlockHeight: args.restoreBlockHeight, enableLelantusScanning: args.enableLelantusScanning, ), settings: RouteSettings( From cf5c2fc5817aafea7433f31757ad114ff1b8feab Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 8 Apr 2025 16:27:56 -0600 Subject: [PATCH 023/206] desktop eth eip-1559 fees --- .../send_view/confirm_transaction_view.dart | 51 ++++++ lib/pages/send_view/send_view.dart | 14 +- .../transaction_fee_selection_sheet.dart | 57 +++++-- lib/pages/send_view/token_send_view.dart | 6 +- .../wallet_view/sub_widgets/desktop_send.dart | 17 +- .../sub_widgets/desktop_send_fee_form.dart | 12 +- .../sub_widgets/desktop_token_send.dart | 11 +- .../ui/fee_rate_type_state_provider.dart | 10 +- lib/wallets/models/tx_data.dart | 14 +- lib/wallets/wallet/impl/ethereum_wallet.dart | 145 ++++++++++++------ .../impl/sub_wallets/eth_token_wallet.dart | 64 +++----- lib/widgets/desktop/desktop_fee_dialog.dart | 5 +- lib/widgets/eth_fee_form.dart | 16 +- 13 files changed, 276 insertions(+), 146 deletions(-) diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 0b7a70224..98a8d9287 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -538,6 +538,21 @@ class _ConfirmTransactionViewState ], ), ), + if (coin is Ethereum) const SizedBox(height: 12), + if (coin is Ethereum) + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Nonce", style: STextStyles.smallMed12(context)), + SelectableText( + widget.txData.nonce.toString(), + style: STextStyles.itemSubtitle12(context), + textAlign: TextAlign.right, + ), + ], + ), + ), if (widget.txData.fee != null && widget.txData.vSize != null) const SizedBox(height: 12), if (widget.txData.fee != null && widget.txData.vSize != null) @@ -841,6 +856,42 @@ class _ConfirmTransactionViewState ], ), ), + if (coin is Ethereum) + Container( + height: 1, + color: + Theme.of( + context, + ).extension()!.background, + ), + if (coin is Ethereum) + Padding( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Nonce", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 2), + SelectableText( + widget.txData.nonce.toString(), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + ), + ], + ), + ), // Container( // height: 1, // color: Theme.of(context) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 780231f3c..43d600ea6 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -452,7 +452,7 @@ class _SendViewState extends ConsumerState { late final BigInt feeRate; - switch (ref.read(feeRateTypeStateProvider.state).state) { + switch (ref.read(feeRateTypeMobileStateProvider.state).state) { case FeeRateType.fast: feeRate = feeObject.fast; break; @@ -469,7 +469,7 @@ class _SendViewState extends ConsumerState { Amount fee; if (coin is Monero) { lib_monero.TransactionPriority specialMoneroId; - switch (ref.read(feeRateTypeStateProvider.state).state) { + switch (ref.read(feeRateTypeMobileStateProvider.state).state) { case FeeRateType.fast: specialMoneroId = lib_monero.TransactionPriority.high; break; @@ -641,7 +641,7 @@ class _SendViewState extends ConsumerState { Future txDataFuture; if (isPaynymSend) { - final feeRate = ref.read(feeRateTypeStateProvider); + final feeRate = ref.read(feeRateTypeMobileStateProvider); txDataFuture = (wallet as PaynymInterface).preparePaymentCodeSend( txData: TxData( paynymAccountLite: widget.accountLite!, @@ -676,7 +676,7 @@ class _SendViewState extends ConsumerState { isChange: false, ), ], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeMobileStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) @@ -690,7 +690,7 @@ class _SendViewState extends ConsumerState { recipients: [ (address: _address!, amount: amount, isChange: false), ], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeMobileStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) @@ -741,7 +741,7 @@ class _SendViewState extends ConsumerState { txData: TxData( recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeMobileStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (wallet is CoinControlInterface && @@ -2300,7 +2300,7 @@ class _SendViewState extends ConsumerState { Text( ref .watch( - feeRateTypeStateProvider + feeRateTypeMobileStateProvider .state, ) .state diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index 8f2f79b68..145a5e3ee 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -302,9 +302,11 @@ class _TransactionFeeSelectionSheetState GestureDetector( onTap: () { final state = - ref.read(feeRateTypeStateProvider.state).state; + ref + .read(feeRateTypeMobileStateProvider.state) + .state; if (state != FeeRateType.fast) { - ref.read(feeRateTypeStateProvider.state).state = + ref.read(feeRateTypeMobileStateProvider.state).state = FeeRateType.fast; } final String? fee = getAmount( @@ -336,12 +338,16 @@ class _TransactionFeeSelectionSheetState groupValue: ref .watch( - feeRateTypeStateProvider.state, + feeRateTypeMobileStateProvider + .state, ) .state, onChanged: (x) { ref - .read(feeRateTypeStateProvider.state) + .read( + feeRateTypeMobileStateProvider + .state, + ) .state = FeeRateType.fast; Navigator.of(context).pop(); @@ -433,9 +439,11 @@ class _TransactionFeeSelectionSheetState GestureDetector( onTap: () { final state = - ref.read(feeRateTypeStateProvider.state).state; + ref + .read(feeRateTypeMobileStateProvider.state) + .state; if (state != FeeRateType.average) { - ref.read(feeRateTypeStateProvider.state).state = + ref.read(feeRateTypeMobileStateProvider.state).state = FeeRateType.average; } final String? fee = getAmount( @@ -466,12 +474,16 @@ class _TransactionFeeSelectionSheetState groupValue: ref .watch( - feeRateTypeStateProvider.state, + feeRateTypeMobileStateProvider + .state, ) .state, onChanged: (x) { ref - .read(feeRateTypeStateProvider.state) + .read( + feeRateTypeMobileStateProvider + .state, + ) .state = FeeRateType.average; Navigator.of(context).pop(); }, @@ -562,9 +574,11 @@ class _TransactionFeeSelectionSheetState GestureDetector( onTap: () { final state = - ref.read(feeRateTypeStateProvider.state).state; + ref + .read(feeRateTypeMobileStateProvider.state) + .state; if (state != FeeRateType.slow) { - ref.read(feeRateTypeStateProvider.state).state = + ref.read(feeRateTypeMobileStateProvider.state).state = FeeRateType.slow; } final String? fee = getAmount(FeeRateType.slow, coin); @@ -592,12 +606,16 @@ class _TransactionFeeSelectionSheetState groupValue: ref .watch( - feeRateTypeStateProvider.state, + feeRateTypeMobileStateProvider + .state, ) .state, onChanged: (x) { ref - .read(feeRateTypeStateProvider.state) + .read( + feeRateTypeMobileStateProvider + .state, + ) .state = FeeRateType.slow; Navigator.of(context).pop(); }, @@ -689,10 +707,13 @@ class _TransactionFeeSelectionSheetState GestureDetector( onTap: () { final state = - ref.read(feeRateTypeStateProvider.state).state; + ref + .read(feeRateTypeMobileStateProvider.state) + .state; if (state != FeeRateType.custom) { - ref.read(feeRateTypeStateProvider.state).state = - FeeRateType.custom; + ref + .read(feeRateTypeMobileStateProvider.state) + .state = FeeRateType.custom; } widget.updateChosen("custom"); @@ -717,13 +738,15 @@ class _TransactionFeeSelectionSheetState groupValue: ref .watch( - feeRateTypeStateProvider.state, + feeRateTypeMobileStateProvider + .state, ) .state, onChanged: (x) { ref .read( - feeRateTypeStateProvider.state, + feeRateTypeMobileStateProvider + .state, ) .state = FeeRateType.custom; Navigator.of(context).pop(); diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index b22a9e9d0..1fa048dfd 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -362,7 +362,7 @@ class _TokenSendViewState extends ConsumerState { late final BigInt feeRate; - switch (ref.read(feeRateTypeStateProvider.state).state) { + switch (ref.read(feeRateTypeMobileStateProvider.state).state) { case FeeRateType.fast: feeRate = feeObject.fast; break; @@ -476,7 +476,7 @@ class _TokenSendViewState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( recipients: [(address: _address!, amount: amount, isChange: false)], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeMobileStateProvider), note: noteController.text, ), ); @@ -1200,7 +1200,7 @@ class _TokenSendViewState extends ConsumerState { Text( ref .watch( - feeRateTypeStateProvider + feeRateTypeMobileStateProvider .state, ) .state diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index e11a55ff5..4749cfa8a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -58,6 +58,7 @@ import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/qr_code_scanner_dialog.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/dialogs/firo_exchange_address_dialog.dart'; +import '../../../../widgets/eth_fee_form.dart'; import '../../../../widgets/icon_widgets/addressbook_icon.dart'; import '../../../../widgets/icon_widgets/clipboard_icon.dart'; import '../../../../widgets/icon_widgets/qrcode_icon.dart'; @@ -129,6 +130,7 @@ class _DesktopSendState extends ConsumerState { bool isCustomFee = false; int customFeeRate = 1; + EthEIP1559Fee? ethFee; Future scanWebcam() async { try { @@ -305,7 +307,7 @@ class _DesktopSendState extends ConsumerState { if (isPaynymSend) { final paynymWallet = wallet as PaynymInterface; - final feeRate = ref.read(feeRateTypeStateProvider); + final feeRate = ref.read(feeRateTypeDesktopStateProvider); txDataFuture = paynymWallet.preparePaymentCodeSend( txData: TxData( paynymAccountLite: widget.accountLite!, @@ -340,7 +342,7 @@ class _DesktopSendState extends ConsumerState { isChange: false, ), ], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && @@ -355,7 +357,7 @@ class _DesktopSendState extends ConsumerState { recipients: [ (address: _address!, amount: amount, isChange: false), ], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && @@ -407,7 +409,7 @@ class _DesktopSendState extends ConsumerState { txData: TxData( recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, nonce: wallet.cryptoCurrency is Ethereum @@ -419,6 +421,7 @@ class _DesktopSendState extends ConsumerState { ref.read(desktopUseUTXOs).isNotEmpty) ? ref.read(desktopUseUTXOs) : null, + ethEIP1559Fee: ethFee, ), ); } @@ -1634,7 +1637,11 @@ class _DesktopSendState extends ConsumerState { walletId: walletId, isToken: false, onCustomFeeSliderChanged: (value) => customFeeRate = value, - onCustomFeeOptionChanged: (value) => isCustomFee = value, + onCustomFeeOptionChanged: (value) { + isCustomFee = value; + ethFee = null; + }, + onCustomEip1559FeeOptionChanged: (value) => ethFee = value, ), if (coin is Ethereum) const SizedBox(height: 20), if (coin is Ethereum) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 28c385bfd..154955148 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -10,6 +10,7 @@ import '../../../../themes/stack_colors.dart'; import '../../../../utilities/amount/amount.dart'; import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/enums/fee_rate_type_enum.dart'; +import '../../../../utilities/eth_commons.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../wallets/crypto_currency/interfaces/electrumx_currency_interface.dart'; @@ -30,12 +31,14 @@ class DesktopSendFeeForm extends ConsumerStatefulWidget { required this.isToken, required this.onCustomFeeSliderChanged, required this.onCustomFeeOptionChanged, + this.onCustomEip1559FeeOptionChanged, }); final String walletId; final bool isToken; final void Function(int) onCustomFeeSliderChanged; final void Function(bool) onCustomFeeOptionChanged; + final void Function(EthEIP1559Fee)? onCustomEip1559FeeOptionChanged; @override ConsumerState createState() => _DesktopSendFeeFormState(); @@ -318,9 +321,12 @@ class _DesktopSendFeeFormState extends ConsumerState { ), if (isCustomFee && isEth) EthFeeForm( - stateChanged: (updatedFeeModel) { - print(updatedFeeModel); - }, + minGasLimit: + widget.isToken + ? kEthereumTokenMinGasLimit + : kEthereumMinGasLimit, + stateChanged: + (value) => widget.onCustomEip1559FeeOptionChanged?.call(value), ), if (isCustomFee && !isEth) Padding( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 45fcfc42a..48e8cb230 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -45,6 +45,7 @@ import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/secondary_button.dart'; +import '../../../../widgets/eth_fee_form.dart'; import '../../../../widgets/icon_widgets/addressbook_icon.dart'; import '../../../../widgets/icon_widgets/clipboard_icon.dart'; import '../../../../widgets/icon_widgets/x_icon.dart'; @@ -103,6 +104,8 @@ class _DesktopTokenSendState extends ConsumerState { bool _cryptoAmountChangeLock = false; late VoidCallback onCryptoAmountChanged; + EthEIP1559Fee? ethFee; + Future previewSend() async { final tokenWallet = ref.read(pCurrentTokenWallet)!; @@ -232,8 +235,9 @@ class _DesktopTokenSendState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( recipients: [(address: _address!, amount: amount, isChange: false)], - feeRateType: ref.read(feeRateTypeStateProvider), + feeRateType: ref.read(feeRateTypeDesktopStateProvider), nonce: int.tryParse(nonceController.text), + ethEIP1559Fee: ethFee, ), ); @@ -1028,7 +1032,10 @@ class _DesktopTokenSendState extends ConsumerState { walletId: walletId, isToken: true, onCustomFeeSliderChanged: (value) => {}, - onCustomFeeOptionChanged: (value) {}, + onCustomFeeOptionChanged: (value) { + ethFee = null; + }, + onCustomEip1559FeeOptionChanged: (value) => ethFee = value, ), const SizedBox(height: 20), Text( diff --git a/lib/providers/ui/fee_rate_type_state_provider.dart b/lib/providers/ui/fee_rate_type_state_provider.dart index 3e1421c14..8b309a2e5 100644 --- a/lib/providers/ui/fee_rate_type_state_provider.dart +++ b/lib/providers/ui/fee_rate_type_state_provider.dart @@ -9,7 +9,13 @@ */ import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../utilities/enums/fee_rate_type_enum.dart'; -final feeRateTypeStateProvider = - StateProvider.autoDispose((_) => FeeRateType.average); +final feeRateTypeMobileStateProvider = StateProvider.autoDispose( + (_) => FeeRateType.average, +); + +final feeRateTypeDesktopStateProvider = StateProvider( + (_) => FeeRateType.average, +); diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 1fbe077e2..114d0a1f9 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -7,6 +7,7 @@ import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/enums/fee_rate_type_enum.dart'; +import '../../widgets/eth_fee_form.dart'; import '../isar/models/spark_coin.dart'; import 'name_op_state.dart'; @@ -43,12 +44,11 @@ class TxData { // paynym specific final PaynymAccountLite? paynymAccountLite; - // eth token specific + // eth & token specific + final EthEIP1559Fee? ethEIP1559Fee; final web3dart.Transaction? web3dartTransaction; final int? nonce; final BigInt? chainId; - final BigInt? feeInWei; - // wownero and monero specific final lib_monero.PendingTransaction? pendingTransaction; @@ -98,10 +98,10 @@ class TxData { this.frostMSConfig, this.frostSigners, this.paynymAccountLite, + this.ethEIP1559Fee, this.web3dartTransaction, this.nonce, this.chainId, - this.feeInWei, this.pendingTransaction, this.jMintValue, this.spendCoinIndexes, @@ -221,10 +221,10 @@ class TxData { List? frostSigners, String? changeAddress, PaynymAccountLite? paynymAccountLite, + EthEIP1559Fee? ethEIP1559Fee, web3dart.Transaction? web3dartTransaction, int? nonce, BigInt? chainId, - BigInt? feeInWei, lib_monero.PendingTransaction? pendingTransaction, int? jMintValue, List? spendCoinIndexes, @@ -261,10 +261,10 @@ class TxData { frostSigners: frostSigners ?? this.frostSigners, changeAddress: changeAddress ?? this.changeAddress, paynymAccountLite: paynymAccountLite ?? this.paynymAccountLite, + ethEIP1559Fee: ethEIP1559Fee ?? this.ethEIP1559Fee, web3dartTransaction: web3dartTransaction ?? this.web3dartTransaction, nonce: nonce ?? this.nonce, chainId: chainId ?? this.chainId, - feeInWei: feeInWei ?? this.feeInWei, pendingTransaction: pendingTransaction ?? this.pendingTransaction, jMintValue: jMintValue ?? this.jMintValue, spendCoinIndexes: spendCoinIndexes ?? this.spendCoinIndexes, @@ -303,10 +303,10 @@ class TxData { 'frostSigners: $frostSigners, ' 'changeAddress: $changeAddress, ' 'paynymAccountLite: $paynymAccountLite, ' + 'ethEIP1559Fee: $ethEIP1559Fee, ' 'web3dartTransaction: $web3dartTransaction, ' 'nonce: $nonce, ' 'chainId: $chainId, ' - 'feeInWei: $feeInWei, ' 'pendingTransaction: $pendingTransaction, ' 'jMintValue: $jMintValue, ' 'spendCoinIndexes: $spendCoinIndexes, ' diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index db4c2fa50..1bb5ec7c7 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -421,85 +421,128 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { return false; } - @override - Future prepareSend({required TxData txData}) async { - final BigInt rate; + Future getMyWeb3Address() async { + final myAddress = (await getCurrentReceivingAddress())!.value; + final myWeb3Address = web3.EthereumAddress.fromHex(myAddress); + return myWeb3Address; + } + + Future< + ({ + int nonce, + BigInt chainId, + BigInt baseFee, + BigInt maxBaseFee, + BigInt priorityFee, + }) + > + internalSharedPrepareSend({ + required TxData txData, + required web3.EthereumAddress myWeb3Address, + }) async { + if (txData.feeRateType == null) throw Exception("Missing fee rate type."); + if (txData.feeRateType == FeeRateType.custom && + txData.ethEIP1559Fee == null) { + throw Exception("Missing custom EIP-1559 values."); + } + + await updateBalance(); + + final client = getEthClient(); + final chainId = await client.getChainId(); + final nonce = + txData.nonce ?? + await client.getTransactionCount( + myWeb3Address, + atBlock: const web3.BlockNum.pending(), + ); + final feeObject = await fees; + final baseFee = feeObject.suggestBaseFee; + BigInt maxBaseFee = baseFee; + BigInt priorityFee; + switch (txData.feeRateType!) { case FeeRateType.fast: - rate = feeObject.fast; + priorityFee = feeObject.fast - baseFee; + if (priorityFee.isNegative) priorityFee = BigInt.zero; break; + case FeeRateType.average: - rate = feeObject.medium; + priorityFee = feeObject.medium - baseFee; + if (priorityFee.isNegative) priorityFee = BigInt.zero; break; + case FeeRateType.slow: - rate = feeObject.slow; + priorityFee = feeObject.slow - baseFee; + if (priorityFee.isNegative) priorityFee = BigInt.zero; break; + case FeeRateType.custom: - throw UnimplementedError("custom eth fees"); + priorityFee = txData.ethEIP1559Fee!.priorityFeeWei; + maxBaseFee = txData.ethEIP1559Fee!.maxBaseFeeWei; + break; } - final feeEstimate = await estimateFeeFor(Amount.zero, rate); - - // bool isSendAll = false; - // final availableBalance = balance.spendable; - // if (satoshiAmount == availableBalance) { - // isSendAll = true; - // } - // - // if (isSendAll) { - // //Subtract fee amount from send amount - // satoshiAmount -= feeEstimate; - // } - - final client = getEthClient(); + if (baseFee > maxBaseFee) { + throw Exception("Base cannot be greater than max base fee"); + } + if (priorityFee > maxBaseFee) { + throw Exception("Priority fee cannot be greater than max base fee"); + } - final myAddress = (await getCurrentReceivingAddress())!.value; - final myWeb3Address = web3.EthereumAddress.fromHex(myAddress); + return ( + nonce: nonce, + chainId: chainId, + baseFee: baseFee, + maxBaseFee: maxBaseFee, + priorityFee: priorityFee, + ); + } + @override + Future prepareSend({required TxData txData}) async { final amount = txData.recipients!.first.amount; final address = txData.recipients!.first.address; - // final est = await client.estimateGas( - // sender: myWeb3Address, - // to: web3.EthereumAddress.fromHex(address), - // gasPrice: web3.EtherAmount.fromUnitAndValue( - // web3.EtherUnit.wei, - // rate, - // ), - // amountOfGas: BigInt.from((cryptoCurrency as Ethereum).gasLimit), - // value: web3.EtherAmount.inWei(amount.raw), - // ); + final myWeb3Address = await getMyWeb3Address(); - final nonce = - txData.nonce ?? - await client.getTransactionCount( - myWeb3Address, - atBlock: const web3.BlockNum.pending(), - ); + final prep = await internalSharedPrepareSend( + txData: txData, + myWeb3Address: myWeb3Address, + ); - // final nResponse = await EthereumAPI.getAddressNonce(address: myAddress); - // print("=============================================================="); - // print("ETH client.estimateGas: $est"); - // print("ETH estimateFeeFor : $feeEstimate"); - // print("ETH nonce custom response: $nResponse"); - // print("ETH actual nonce : $nonce"); - // print("=============================================================="); + // double check balance after internalSharedPrepareSend call to ensure + // balance is up to date + if (amount > info.cachedBalance.spendable) { + throw Exception("Insufficient balance"); + } final tx = web3.Transaction( to: web3.EthereumAddress.fromHex(address), - gasPrice: web3.EtherAmount.fromBigInt(web3.EtherUnit.wei, rate), - maxGas: (cryptoCurrency as Ethereum).gasLimit, + maxGas: txData.ethEIP1559Fee?.gasLimit ?? kEthereumMinGasLimit, value: web3.EtherAmount.inWei(amount.raw), - nonce: nonce, + nonce: prep.nonce, + maxFeePerGas: web3.EtherAmount.fromBigInt( + web3.EtherUnit.wei, + prep.maxBaseFee, + ), + maxPriorityFeePerGas: web3.EtherAmount.fromBigInt( + web3.EtherUnit.wei, + prep.priorityFee, + ), + ); + + final feeEstimate = await estimateFeeFor( + Amount.zero, + prep.maxBaseFee + prep.priorityFee, ); return txData.copyWith( nonce: tx.nonce, web3dartTransaction: tx, fee: feeEstimate, - feeInWei: rate, - chainId: (await client.getChainId()), + chainId: prep.chainId, ); } diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index b2379f28e..d32ae3db8 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -14,7 +14,6 @@ import '../../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../../models/paymint/fee_object_model.dart'; import '../../../../services/ethereum/ethereum_api.dart'; import '../../../../utilities/amount/amount.dart'; -import '../../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../../utilities/eth_commons.dart'; import '../../../../utilities/extensions/extensions.dart'; import '../../../../utilities/logger.dart'; @@ -206,41 +205,18 @@ class EthTokenWallet extends Wallet { @override Future prepareSend({required TxData txData}) async { - final feeRateType = txData.feeRateType!; - BigInt fee = BigInt.zero; - final feeObject = await fees; - switch (feeRateType) { - case FeeRateType.fast: - fee = feeObject.fast; - break; - case FeeRateType.average: - fee = feeObject.medium; - break; - case FeeRateType.slow: - fee = feeObject.slow; - break; - case FeeRateType.custom: - throw UnimplementedError("custom eth token fees"); - } - - final feeEstimate = await estimateFeeFor(Amount.zero, fee); - - final client = ethWallet.getEthClient(); - - final myAddress = (await getCurrentReceivingAddress())!.value; - final myWeb3Address = web3dart.EthereumAddress.fromHex(myAddress); - - final nonce = - txData.nonce ?? - await client.getTransactionCount( - myWeb3Address, - atBlock: const web3dart.BlockNum.pending(), - ); - final amount = txData.recipients!.first.amount; final address = txData.recipients!.first.address; - await updateBalance(); + final myWeb3Address = await ethWallet.getMyWeb3Address(); + + final prep = await ethWallet.internalSharedPrepareSend( + txData: txData, + myWeb3Address: myWeb3Address, + ); + + // double check balance after internalSharedPrepareSend call to ensure + // balance is up to date final info = await mainDB.isar.tokenWalletInfo .where() @@ -257,16 +233,26 @@ class EthTokenWallet extends Wallet { contract: _deployedContract, function: _sendFunction, parameters: [web3dart.EthereumAddress.fromHex(address), amount.raw], - maxGas: kEthereumTokenMinGasLimit, - gasPrice: web3dart.EtherAmount.fromBigInt(web3dart.EtherUnit.wei, fee), - nonce: nonce, + maxGas: txData.ethEIP1559Fee?.gasLimit ?? kEthereumTokenMinGasLimit, + nonce: prep.nonce, + maxFeePerGas: web3dart.EtherAmount.fromBigInt( + web3dart.EtherUnit.wei, + prep.maxBaseFee, + ), + maxPriorityFeePerGas: web3dart.EtherAmount.fromBigInt( + web3dart.EtherUnit.wei, + prep.priorityFee, + ), ); + final feeEstimate = await estimateFeeFor( + Amount.zero, + prep.maxBaseFee + prep.priorityFee, + ); return txData.copyWith( fee: feeEstimate, - feeInWei: fee, web3dartTransaction: tx, - chainId: await client.getChainId(), + chainId: prep.chainId, nonce: tx.nonce, ); } @@ -294,7 +280,7 @@ class EthTokenWallet extends Wallet { } @override - Future get fees => EthereumAPI.getFees(); + Future get fees => EthereumAPI.getFees(); @override Future pingCheck() async { diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart index b6fb74c7c..aa3175cac 100644 --- a/lib/widgets/desktop/desktop_fee_dialog.dart +++ b/lib/widgets/desktop/desktop_fee_dialog.dart @@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/models.dart'; import '../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; import '../../providers/global/wallets_provider.dart'; +import '../../providers/ui/fee_rate_type_state_provider.dart'; import '../../providers/wallet/desktop_fee_providers.dart'; import '../../providers/wallet/public_private_balance_state_provider.dart'; import '../../themes/stack_colors.dart'; @@ -350,6 +351,8 @@ class _DesktopFeeItemState extends ConsumerState { (child) => MaterialButton( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () { + ref.read(feeRateTypeDesktopStateProvider.state).state = + widget.feeRateType; Navigator.of( context, ).pop((widget.feeRateType, feeString, timeString)); @@ -366,7 +369,7 @@ class _DesktopFeeItemState extends ConsumerState { ); if ((coin is Firo) && ref.watch(publicPrivateBalanceStateProvider.state).state == - "Private") { + FiroType.lelantus) { return Text( "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( diff --git a/lib/widgets/eth_fee_form.dart b/lib/widgets/eth_fee_form.dart index df5851acf..a0f819028 100644 --- a/lib/widgets/eth_fee_form.dart +++ b/lib/widgets/eth_fee_form.dart @@ -18,11 +18,16 @@ class EthEIP1559Fee { required this.gasLimit, }); + BigInt get maxBaseFeeWei => maxBaseFeeGwei.shift(9).toBigInt(); + BigInt get priorityFeeWei => priorityFeeGwei.shift(9).toBigInt(); + @override String toString() => "EthEIP1559Fee(" "maxBaseFeeGwei: $maxBaseFeeGwei, " "priorityFeeGwei: $priorityFeeGwei, " + "maxBaseFeeWei: $maxBaseFeeWei, " + "priorityFeeWei: $priorityFeeWei, " "gasLimit: $gasLimit)"; } @@ -69,7 +74,6 @@ class _EthFeeFormState extends State { widget.initialState?.priorityFeeGwei.toString() ?? ""; gasLimit = widget.initialState?.gasLimit ?? widget.minGasLimit; - print("asgLimit: $gasLimit"); } @override @@ -87,10 +91,7 @@ class _EthFeeFormState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Max base fee (GWEI)", - style: STextStyles.smallMed12(context) - ), + Text("Max base fee (GWEI)", style: STextStyles.smallMed12(context)), const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( @@ -139,10 +140,7 @@ class _EthFeeFormState extends State { ), ), const SizedBox(height: 20), - Text( - "Max base fee (GWEI)", - style: STextStyles.smallMed12(context) - ), + Text("Priority fee (GWEI)", style: STextStyles.smallMed12(context)), const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( From 566afd65ec32017e9a2f0682b69f5936e10d184c Mon Sep 17 00:00:00 2001 From: Julian Date: Tue, 8 Apr 2025 19:35:41 -0600 Subject: [PATCH 024/206] updated eth server --- lib/services/ethereum/ethereum_api.dart | 2 +- lib/wallets/crypto_currency/coins/ethereum.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index c9e405cba..dd815e80d 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -55,7 +55,7 @@ abstract class EthereumAPI { try { final response = await client.get( url: Uri.parse( - "$stackBaseServer/export?addrs=$address&firstBlock=$firstBlock", + "$stackBaseServer/export?addrs=$address&firstBlock=$firstBlock&unripe=true", ), proxyInfo: Prefs.instance.useTor diff --git a/lib/wallets/crypto_currency/coins/ethereum.dart b/lib/wallets/crypto_currency/coins/ethereum.dart index 0c727de28..cd908b9e6 100644 --- a/lib/wallets/crypto_currency/coins/ethereum.dart +++ b/lib/wallets/crypto_currency/coins/ethereum.dart @@ -49,7 +49,7 @@ class Ethereum extends Bip39Currency { @override NodeModel get defaultNode => NodeModel( - host: "https://eth.stackwallet.com", + host: "https://eth2.stackwallet.com", port: 443, name: DefaultNodes.defaultName, id: DefaultNodes.buildId(this), From 6c68f21cd96fc5657810b4956bdf1b119c5da1e4 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 9 Apr 2025 15:22:43 -0600 Subject: [PATCH 025/206] always log everything to console in debug mode --- lib/main.dart | 1 + lib/utilities/logger.dart | 218 ++++++++++++++++++-------------------- 2 files changed, 102 insertions(+), 117 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ccf2ecf6e..ba3583668 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -200,6 +200,7 @@ void main(List args) async { await Logging.instance.initialize( (await StackFileSystem.applicationLogsDirectory(Prefs.instance)).path, level: Prefs.instance.logLevel, + debugConsoleLevel: kDebugMode ? Level.trace : null, ); await xelis_api.setUpRustLogger(); diff --git a/lib/utilities/logger.dart b/lib/utilities/logger.dart index f62b1ea4e..d4cc03dcf 100644 --- a/lib/utilities/logger.dart +++ b/lib/utilities/logger.dart @@ -53,87 +53,79 @@ class Logging { SendPort get _sendPort { final port = IsolateNameServer.lookupPortByName(_kLoggerPortName); if (port == null) { - throw Exception( - "Did you forget to call Logging.initialize()?", - ); + throw Exception("Did you forget to call Logging.initialize()?"); } return port; } - Future initialize(String logsPath, {required Level level}) async { + Future initialize( + String logsPath, { + required Level level, + Level? debugConsoleLevel, + }) async { if (Isolate.current.debugName != "main") { throw Exception( "Logging.initialize() must be called on the main isolate.", ); } if (IsolateNameServer.lookupPortByName(_kLoggerPortName) != null) { - throw Exception( - "Logging was already initialized", - ); + throw Exception("Logging was already initialized"); } logsDirPath = logsPath; final receivePort = ReceivePort(); - await Isolate.spawn( - (sendPort) { - final ReceivePort receivePort = ReceivePort(); - sendPort.send(receivePort.sendPort); + await Isolate.spawn((sendPort) { + final ReceivePort receivePort = ReceivePort(); + sendPort.send(receivePort.sendPort); + + PrettyPrinter prettyPrinter(bool toFile) => PrettyPrinter( + printEmojis: false, + methodCount: 0, + dateTimeFormat: + toFile ? DateTimeFormat.none : DateTimeFormat.dateAndTime, + colors: !toFile, + noBoxingByDefault: toFile, + ); - PrettyPrinter prettyPrinter(bool toFile) => PrettyPrinter( - printEmojis: false, - methodCount: 0, - dateTimeFormat: - toFile ? DateTimeFormat.none : DateTimeFormat.dateAndTime, - colors: !toFile, - noBoxingByDefault: toFile, - ); + final consoleLogger = Logger( + printer: PrefixPrinter(prettyPrinter(false)), + filter: ProductionFilter(), + level: debugConsoleLevel ?? level, + ); - final consoleLogger = Logger( - printer: PrefixPrinter(prettyPrinter(false)), - filter: ProductionFilter(), - level: level, - ); + final fileLogger = Logger( + printer: PrefixPrinter(prettyPrinter(true)), + filter: ProductionFilter(), + level: level, + output: AdvancedFileOutput( + path: logsDirPath, + overrideExisting: false, + latestFileName: "latest.txt", + writeImmediately: [Level.error, Level.fatal, Level.warning], + ), + ); - final fileLogger = Logger( - printer: PrefixPrinter(prettyPrinter(true)), - filter: ProductionFilter(), - level: level, - output: AdvancedFileOutput( - path: logsDirPath, - overrideExisting: false, - latestFileName: "latest.txt", - writeImmediately: [ - Level.error, - Level.fatal, - Level.warning, - Level.trace, // mainly for spark debugging. TODO: Remove later - ], - ), + receivePort.listen((message) { + final event = (message as (LogEvent, bool)).$1; + consoleLogger.log( + event.level, + event.message, + stackTrace: event.stackTrace, + error: event.error, + time: event.time.toUtc(), ); - - receivePort.listen((message) { - final event = (message as (LogEvent, bool)).$1; - consoleLogger.log( + if (message.$2) { + fileLogger.log( event.level, - event.message, + "${event.time.toUtc().toIso8601String()} ${event.message}", stackTrace: event.stackTrace, error: event.error, - time: event.time.toUtc(), + time: event.time, ); - if (message.$2) { - fileLogger.log( - event.level, - "${event.time.toUtc().toIso8601String()} ${event.message}", - stackTrace: event.stackTrace, - error: event.error, - time: event.time, - ); - } - }); - }, - receivePort.sendPort, - ); + } + }); + }, receivePort.sendPort); final loggerPort = await receivePort.first as SendPort; IsolateNameServer.registerPortWithName(loggerPort, _kLoggerPortName); } @@ -155,18 +147,16 @@ class Logging { toFile = false; } try { - _sendPort.send( - ( - LogEvent( - level, - _stringifyMessage(message), - time: time, - error: error, - stackTrace: stackTrace, - ), - toFile + _sendPort.send(( + LogEvent( + level, + _stringifyMessage(message), + time: time, + error: error, + stackTrace: stackTrace, ), - ); + toFile, + )); } catch (e, s) { t("Isolates suck", error: e, stackTrace: s); } @@ -177,82 +167,76 @@ class Logging { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.trace, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.trace, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); void d( dynamic message, { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.debug, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.debug, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); void i( dynamic message, { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.info, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.info, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); void w( dynamic message, { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.warning, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.warning, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); void e( dynamic message, { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.error, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.error, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); void f( dynamic message, { DateTime? time, Object? error, StackTrace? stackTrace, - }) => - log( - Level.fatal, - message, - time: time, - error: error, - stackTrace: stackTrace, - ); + }) => log( + Level.fatal, + message, + time: time, + error: error, + stackTrace: stackTrace, + ); } From 626b7d6e6cc90898cb8361465853277423d21417 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 9 Apr 2025 15:27:18 -0600 Subject: [PATCH 026/206] fix eth token balance response parsing --- lib/services/ethereum/ethereum_api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index dd815e80d..2f44c03a2 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -176,7 +176,7 @@ abstract class EthereumAPI { final map = json["data"].first as Map; final balance = - BigInt.tryParse(map["units"].toString()) ?? BigInt.zero; + BigInt.tryParse(map["balance"].toString()) ?? BigInt.zero; return EthereumResponse( Amount(rawValue: balance, fractionDigits: map["decimals"] as int), From 3614b1b19ee17179fa9dc3dc0c8889d51c76bb25 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 10 Apr 2025 11:55:34 -0600 Subject: [PATCH 027/206] rough mobile custom eth fees ui --- lib/pages/send_view/send_view.dart | 268 ++++++++---------- .../transaction_fee_selection_sheet.dart | 4 +- lib/pages/send_view/token_send_view.dart | 66 +++-- lib/services/ethereum/ethereum_api.dart | 4 +- lib/widgets/eth_fee_form.dart | 229 ++++++++++----- 5 files changed, 326 insertions(+), 245 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 43d600ea6..65d1dc5a5 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -39,6 +39,7 @@ import '../../utilities/barcode_scanner_interface.dart'; import '../../utilities/clipboard_interface.dart'; import '../../utilities/constants.dart'; import '../../utilities/enums/fee_rate_type_enum.dart'; +import '../../utilities/eth_commons.dart'; import '../../utilities/extensions/extensions.dart'; import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; @@ -57,6 +58,7 @@ import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_buttons/blue_text_button.dart'; import '../../widgets/dialogs/firo_exchange_address_dialog.dart'; +import '../../widgets/eth_fee_form.dart'; import '../../widgets/fee_slider.dart'; import '../../widgets/icon_widgets/addressbook_icon.dart'; import '../../widgets/icon_widgets/clipboard_icon.dart'; @@ -98,6 +100,13 @@ class SendView extends ConsumerStatefulWidget { } class _SendViewState extends ConsumerState { + static const stringsToLoopThrough = [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ]; + late final String walletId; late final CryptoCurrency coin; late final ClipboardInterface clipboard; @@ -122,6 +131,7 @@ class _SendViewState extends ConsumerState { late final bool isStellar; late final bool isFiro; + late final bool isEth; Amount? _cachedAmountToSend; String? _address; @@ -652,7 +662,7 @@ class _SendViewState extends ConsumerState { isChange: false, ), ], - satsPerVByte: isCustomFee ? customFeeRate : null, + satsPerVByte: isCustomFee.value ? customFeeRate : null, feeRateType: feeRate, utxos: (wallet is CoinControlInterface && @@ -677,7 +687,7 @@ class _SendViewState extends ConsumerState { ), ], feeRateType: ref.read(feeRateTypeMobileStateProvider), - satsPerVByte: isCustomFee ? customFeeRate : null, + satsPerVByte: isCustomFee.value ? customFeeRate : null, utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) ? selectedUTXOs @@ -691,7 +701,7 @@ class _SendViewState extends ConsumerState { (address: _address!, amount: amount, isChange: false), ], feeRateType: ref.read(feeRateTypeMobileStateProvider), - satsPerVByte: isCustomFee ? customFeeRate : null, + satsPerVByte: isCustomFee.value ? customFeeRate : null, utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) ? selectedUTXOs @@ -742,7 +752,8 @@ class _SendViewState extends ConsumerState { recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, feeRateType: ref.read(feeRateTypeMobileStateProvider), - satsPerVByte: isCustomFee ? customFeeRate : null, + satsPerVByte: isCustomFee.value ? customFeeRate : null, + ethEIP1559Fee: ethFee, utxos: (wallet is CoinControlInterface && coinControlEnabled && @@ -889,9 +900,80 @@ class _SendViewState extends ConsumerState { bool get isPaynymSend => widget.accountLite != null; - bool isCustomFee = false; - + final isCustomFee = ValueNotifier(false); int customFeeRate = 1; + EthEIP1559Fee? ethFee; + + late final bool hasFees; + + void _onSendToAddressPasteButtonPressed() async { + final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); + if (data?.text != null && data!.text!.isNotEmpty) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring(0, content.indexOf("\n")); + } + + if (coin is Epiccash) { + // strip http:// and https:// if content contains @ + content = AddressUtils().formatAddress(content); + } + + final trimmed = content.trim(); + final parsed = AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + sendToController.text = content; + _address = content; + + _setValidAddressProviders(_address); + + setState(() { + _addressToggleFlag = sendToController.text.isNotEmpty; + }); + } + } + } + + void _onFeeSelectPressed() { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: + (_) => TransactionFeeSelectionSheet( + walletId: walletId, + amount: (Decimal.tryParse(cryptoAmountController.text) ?? + ref.watch(pSendAmount)?.decimal ?? + Decimal.zero) + .toAmount(fractionDigits: coin.fractionDigits), + updateChosen: (String fee) { + if (fee == "custom") { + if (!isCustomFee.value) { + setState(() { + isCustomFee.value = true; + }); + } + return; + } + + _setCurrentFee(fee, true); + setState(() { + _calculateFeesFuture = Future(() => fee); + if (isCustomFee.value) { + isCustomFee.value = false; + } + }); + }, + ), + ); + } @override void initState() { @@ -900,6 +982,10 @@ class _SendViewState extends ConsumerState { ref.refresh(feeSheetSessionCacheProvider); ref.refresh(pIsExchangeAddress); }); + isCustomFee.addListener(() { + if (!isCustomFee.value) ethFee = null; + }); + hasFees = coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos; _currentFee = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); _calculateFeesFuture = calculateFees( @@ -911,6 +997,7 @@ class _SendViewState extends ConsumerState { scanner = widget.barcodeScanner; isStellar = coin is Stellar; isFiro = coin is Firo; + isEth = coin is Ethereum; sendToController = TextEditingController(); cryptoAmountController = TextEditingController(); @@ -1008,6 +1095,7 @@ class _SendViewState extends ConsumerState { _cryptoFocus.dispose(); _baseFocus.dispose(); _memoFocus.dispose(); + isCustomFee.dispose(); super.dispose(); } @@ -1398,63 +1486,8 @@ class _SendViewState extends ConsumerState { key: const Key( "sendViewPasteAddressFieldButtonKey", ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = - data.text!.trim(); - if (content.contains( - "\n", - )) { - content = content - .substring( - 0, - content.indexOf( - "\n", - ), - ); - } - - if (coin is Epiccash) { - // strip http:// and https:// if content contains @ - content = AddressUtils() - .formatAddress( - content, - ); - } - - final trimmed = - content.trim(); - final parsed = - AddressUtils.parsePaymentUri( - trimmed, - logging: - Logging.instance, - ); - if (parsed != null) { - _applyUri(parsed); - } else { - sendToController.text = - content; - _address = content; - - _setValidAddressProviders( - _address, - ); - - setState(() { - _addressToggleFlag = - sendToController - .text - .isNotEmpty; - }); - } - } - }, + onTap: + _onSendToAddressPasteButtonPressed, child: sendToController .text @@ -2131,21 +2164,18 @@ class _SendViewState extends ConsumerState { ), ), const SizedBox(height: 12), - if (coin is! Epiccash && - coin is! NanoCurrency && - coin is! Tezos) + if (hasFees) Text( - "Transaction fee (estimated)", + "Transaction fee ${isEth + ? isCustomFee.value + ? "" + : "(max)" + : "(estimated)"}", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is! Epiccash && - coin is! NanoCurrency && - coin is! Tezos) - const SizedBox(height: 8), - if (coin is! Epiccash && - coin is! NanoCurrency && - coin is! Tezos) + if (hasFees) const SizedBox(height: 8), + if (hasFees) Stack( children: [ TextField( @@ -2180,68 +2210,7 @@ class _SendViewState extends ConsumerState { .state != FiroType.public ? null - : () { - showModalBottomSheet( - backgroundColor: - Colors.transparent, - context: context, - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius.vertical( - top: - Radius.circular( - 20, - ), - ), - ), - builder: - ( - _, - ) => TransactionFeeSelectionSheet( - walletId: walletId, - amount: (Decimal.tryParse( - cryptoAmountController - .text, - ) ?? - ref - .watch( - pSendAmount, - ) - ?.decimal ?? - Decimal.zero) - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - updateChosen: ( - String fee, - ) { - if (fee == "custom") { - if (!isCustomFee) { - setState(() { - isCustomFee = - true; - }); - } - return; - } - - _setCurrentFee( - fee, - true, - ); - setState(() { - _calculateFeesFuture = - Future(() => fee); - if (isCustomFee) { - isCustomFee = false; - } - }); - }, - ), - ); - }, + : _onFeeSelectPressed, child: (isFiro && ref @@ -2274,12 +2243,7 @@ class _SendViewState extends ConsumerState { } else { return AnimatedText( stringsToLoopThrough: - const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], + stringsToLoopThrough, style: STextStyles.itemSubtitle( context, @@ -2327,7 +2291,7 @@ class _SendViewState extends ConsumerState { false, ); return Text( - isCustomFee + isCustomFee.value ? "" : "~${snapshot.data!}", style: @@ -2338,12 +2302,7 @@ class _SendViewState extends ConsumerState { } else { return AnimatedText( stringsToLoopThrough: - const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], + stringsToLoopThrough, style: STextStyles.itemSubtitle( context, @@ -2371,7 +2330,7 @@ class _SendViewState extends ConsumerState { ), ], ), - if (isCustomFee) + if (isCustomFee.value && !isEth) Padding( padding: const EdgeInsets.only( bottom: 12, @@ -2384,6 +2343,13 @@ class _SendViewState extends ConsumerState { }, ), ), + if (isCustomFee.value && isEth) + const SizedBox(height: 12), + if (isCustomFee.value && isEth) + EthFeeForm( + minGasLimit: kEthereumMinGasLimit, + stateChanged: (fee) => ethFee = fee, + ), const Spacer(), const SizedBox(height: 12), TextButton( @@ -2404,7 +2370,7 @@ class _SendViewState extends ConsumerState { style: STextStyles.button(context), ), ), - const SizedBox(height: 4), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index 145a5e3ee..41cdac17e 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -703,7 +703,7 @@ class _TransactionFeeSelectionSheetState ), ), const SizedBox(height: 24), - if (wallet is ElectrumXInterface) + if (wallet is ElectrumXInterface || coin is Ethereum) GestureDetector( onTap: () { final state = @@ -779,7 +779,7 @@ class _TransactionFeeSelectionSheetState ), ), ), - if (wallet is ElectrumXInterface) + if (wallet is ElectrumXInterface || coin is Ethereum) const SizedBox(height: 24), ], ); diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 1fa048dfd..2cb873951 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -33,6 +33,7 @@ import '../../utilities/barcode_scanner_interface.dart'; import '../../utilities/clipboard_interface.dart'; import '../../utilities/constants.dart'; import '../../utilities/enums/fee_rate_type_enum.dart'; +import '../../utilities/eth_commons.dart'; import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../utilities/text_styles.dart'; @@ -45,6 +46,7 @@ import '../../wallets/models/tx_data.dart'; import '../../widgets/animated_text.dart'; import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/eth_fee_form.dart'; import '../../widgets/icon_widgets/addressbook_icon.dart'; import '../../widgets/icon_widgets/clipboard_icon.dart'; import '../../widgets/icon_widgets/eth_token_icon.dart'; @@ -119,6 +121,10 @@ class _TokenSendViewState extends ConsumerState { late Future _calculateFeesFuture; String cachedFees = ""; + final isCustomFee = ValueNotifier(false); + + EthEIP1559Fee? ethFee; + void _onTokenSendViewPasteAddressFieldButtonPressed() async { final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); if (data?.text != null && data!.text!.isNotEmpty) { @@ -332,7 +338,7 @@ class _TokenSendViewState extends ConsumerState { } String? _updateInvalidAddressText(String address) { - if (_data != null && _data!.contactLabel == address) { + if (_data != null && _data.contactLabel == address) { return null; } if (address.isNotEmpty && @@ -478,6 +484,7 @@ class _TokenSendViewState extends ConsumerState { recipients: [(address: _address!, amount: amount, isChange: false)], feeRateType: ref.read(feeRateTypeMobileStateProvider), note: noteController.text, + ethEIP1559Fee: ethFee, ), ); @@ -564,6 +571,9 @@ class _TokenSendViewState extends ConsumerState { @override void initState() { ref.refresh(feeSheetSessionCacheProvider); + isCustomFee.addListener(() { + if (!isCustomFee.value) ethFee = null; + }); _calculateFeesFuture = calculateFees(); _data = widget.autoFillData; @@ -584,11 +594,11 @@ class _TokenSendViewState extends ConsumerState { baseAmountController.addListener(_baseAmountChanged); if (_data != null) { - if (_data!.amount != null) { - cryptoAmountController.text = _data!.amount!.toString(); + if (_data.amount != null) { + cryptoAmountController.text = _data.amount!.toString(); } - sendToController.text = _data!.contactLabel; - _address = _data!.address.trim(); + sendToController.text = _data.contactLabel; + _address = _data.address.trim(); _addressToggleFlag = true; } @@ -613,6 +623,7 @@ class _TokenSendViewState extends ConsumerState { _addressFocusNode.dispose(); _cryptoFocus.dispose(); _baseFocus.dispose(); + isCustomFee.dispose(); super.dispose(); } @@ -1128,12 +1139,11 @@ class _TokenSendViewState extends ConsumerState { ), ), const SizedBox(height: 12), - if (coin is! Epiccash) - Text( - "Transaction fee (estimated)", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), + Text( + "Transaction fee ${isCustomFee.value ? "" : "(max)"}", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), const SizedBox(height: 8), Stack( children: [ @@ -1182,10 +1192,22 @@ class _TokenSendViewState extends ConsumerState { tokenContract.decimals, ), updateChosen: (String fee) { + if (fee == "custom") { + if (!isCustomFee.value) { + setState(() { + isCustomFee.value = true; + }); + } + return; + } + setState(() { _calculateFeesFuture = Future( () => fee, ); + if (isCustomFee.value) { + isCustomFee.value = false; + } }); }, ), @@ -1217,7 +1239,9 @@ class _TokenSendViewState extends ConsumerState { ConnectionState.done && snapshot.hasData) { return Text( - "~${snapshot.data!}", + isCustomFee.value + ? "" + : "~${snapshot.data!}", style: STextStyles.itemSubtitle( context, @@ -1245,10 +1269,12 @@ class _TokenSendViewState extends ConsumerState { Assets.svg.chevronDown, width: 8, height: 4, - color: - Theme.of(context) - .extension()! - .textSubtitle2, + colorFilter: ColorFilter.mode( + Theme.of(context) + .extension()! + .textSubtitle2, + BlendMode.srcIn, + ), ), ], ), @@ -1256,6 +1282,12 @@ class _TokenSendViewState extends ConsumerState { ), ], ), + if (isCustomFee.value) const SizedBox(height: 12), + if (isCustomFee.value) + EthFeeForm( + minGasLimit: kEthereumTokenMinGasLimit, + stateChanged: (value) => ethFee = value, + ), const Spacer(), const SizedBox(height: 12), TextButton( @@ -1286,7 +1318,7 @@ class _TokenSendViewState extends ConsumerState { style: STextStyles.button(context), ), ), - const SizedBox(height: 4), + const SizedBox(height: 16), ], ), ), diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 2f44c03a2..091165b30 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -199,7 +199,7 @@ abstract class EthereumAPI { } } - static Future> _getGasOracle() async { + static Future> getGasOracle() async { try { final response = await client.get( url: Uri.parse("$stackBaseServer/gas-prices"), @@ -246,7 +246,7 @@ abstract class EthereumAPI { } static Future getFees() async { - final response = await _getGasOracle(); + final response = await getGasOracle(); if (response.exception != null) { throw response.exception!; } diff --git a/lib/widgets/eth_fee_form.dart b/lib/widgets/eth_fee_form.dart index a0f819028..b7554a1df 100644 --- a/lib/widgets/eth_fee_form.dart +++ b/lib/widgets/eth_fee_form.dart @@ -1,9 +1,13 @@ +import 'dart:async'; + import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; +import '../services/ethereum/ethereum_api.dart'; import '../themes/stack_colors.dart'; import '../utilities/constants.dart'; import '../utilities/text_styles.dart'; +import '../utilities/util.dart'; import 'stack_text_field.dart'; @immutable @@ -56,32 +60,72 @@ class EthFeeForm extends StatefulWidget { } class _EthFeeFormState extends State { + static const _textFadeDuration = Duration(milliseconds: 300); + final maxBaseController = TextEditingController(); final priorityFeeController = TextEditingController(); + final gasLimitController = TextEditingController(); final maxBaseFocus = FocusNode(); final priorityFeeFocus = FocusNode(); + final gasLimitFocus = FocusNode(); + + late int _gasLimitCache; + + EthEIP1559Fee get _current => EthEIP1559Fee( + maxBaseFeeGwei: Decimal.tryParse(maxBaseController.text) ?? Decimal.zero, + priorityFeeGwei: + Decimal.tryParse(priorityFeeController.text) ?? Decimal.zero, + gasLimit: int.parse(gasLimitController.text), + ); + + String _currentBase = "Current: "; + String _currentPriority = "Current: "; - late int gasLimit; - double _sliderValue = 0; + void _checkNetworkGas() async { + final gas = await EthereumAPI.getGasOracle(); + + if (mounted) { + setState(() { + _currentBase = + "Current: ${gas.value!.suggestBaseFee.toStringAsFixed(3)} GWEI"; + _currentPriority = + "Current: ${gas.value!.lowPriority.toStringAsFixed(3)} - ${gas.value!.highPriority.toStringAsFixed(3)} GWEI"; + }); + } + } + + Timer? _gasTimer; @override void initState() { super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _checkNetworkGas(); + _gasTimer = Timer.periodic( + const Duration(seconds: 5), + (_) => _checkNetworkGas(), + ); + }); maxBaseController.text = widget.initialState?.maxBaseFeeGwei.toString() ?? ""; priorityFeeController.text = widget.initialState?.priorityFeeGwei.toString() ?? ""; - gasLimit = widget.initialState?.gasLimit ?? widget.minGasLimit; + _gasLimitCache = widget.initialState?.gasLimit ?? widget.minGasLimit; + gasLimitController.text = _gasLimitCache.toString(); } @override void dispose() { + _gasTimer?.cancel(); + _gasTimer = null; maxBaseController.dispose(); priorityFeeController.dispose(); + gasLimitController.dispose(); maxBaseFocus.dispose(); priorityFeeFocus.dispose(); + gasLimitFocus.dispose(); super.dispose(); } @@ -107,38 +151,47 @@ class _EthFeeFormState extends State { keyboardType: const TextInputType.numberWithOptions(decimal: true), focusNode: maxBaseFocus, onChanged: (value) { - widget.stateChanged( - EthEIP1559Fee( - maxBaseFeeGwei: Decimal.tryParse(value) ?? Decimal.zero, - priorityFeeGwei: - Decimal.tryParse(priorityFeeController.text) ?? - Decimal.zero, - gasLimit: gasLimit, - ), - ); + widget.stateChanged(_current); }, - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveText, - height: 1.8, - ), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( - "Leave empty to auto select nonce", + null, maxBaseFocus, context, - desktopMed: true, + desktopMed: Util.isDesktop, ).copyWith( - contentPadding: const EdgeInsets.only( + contentPadding: EdgeInsets.only( left: 16, - top: 11, - bottom: 12, + top: Util.isDesktop ? 11 : 6, + bottom: Util.isDesktop ? 12 : 8, right: 5, ), ), ), ), + const SizedBox(height: 6), + AnimatedSwitcher( + duration: _textFadeDuration, + transitionBuilder: + (child, animation) => + FadeTransition(opacity: animation, child: child), + child: Text( + _currentBase, + key: ValueKey( + _currentBase, + ), // Important: ensures AnimatedSwitcher sees the text change + style: STextStyles.smallMed12(context), + ), + ), const SizedBox(height: 20), Text("Priority fee (GWEI)", style: STextStyles.smallMed12(context)), const SizedBox(height: 10), @@ -156,68 +209,98 @@ class _EthFeeFormState extends State { keyboardType: const TextInputType.numberWithOptions(decimal: true), focusNode: priorityFeeFocus, onChanged: (value) { - widget.stateChanged( - EthEIP1559Fee( - maxBaseFeeGwei: - Decimal.tryParse(maxBaseController.text) ?? Decimal.zero, - priorityFeeGwei: Decimal.tryParse(value) ?? Decimal.zero, - gasLimit: gasLimit, - ), - ); + widget.stateChanged(_current); }, - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveText, - height: 1.8, - ), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( - "Leave empty to auto select nonce", + null, priorityFeeFocus, context, - desktopMed: true, + desktopMed: Util.isDesktop, ).copyWith( - contentPadding: const EdgeInsets.only( + contentPadding: EdgeInsets.only( left: 16, - top: 11, - bottom: 12, + top: Util.isDesktop ? 11 : 6, + bottom: Util.isDesktop ? 12 : 8, right: 5, ), ), ), ), - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Gas limit", style: STextStyles.smallMed12(context)), - Text("$gasLimit", style: STextStyles.smallMed12(context)), - ], + const SizedBox(height: 6), + AnimatedSwitcher( + duration: _textFadeDuration, + transitionBuilder: + (child, animation) => + FadeTransition(opacity: animation, child: child), + child: Text( + _currentPriority, + key: ValueKey( + _currentPriority, + ), // Important: ensures AnimatedSwitcher sees the text change + style: STextStyles.smallMed12(context), + ), ), - Slider( - value: _sliderValue, - onChanged: (value) { - setState(() { - _sliderValue = value; - final number = - (_sliderValue * (widget.maxGasLimit - widget.minGasLimit) + - widget.minGasLimit) - .toDouble(); - - gasLimit = number.toInt(); - }); - widget.stateChanged( - EthEIP1559Fee( - maxBaseFeeGwei: - Decimal.tryParse(maxBaseController.text) ?? Decimal.zero, - priorityFeeGwei: - Decimal.tryParse(priorityFeeController.text) ?? - Decimal.zero, - gasLimit: gasLimit, + const SizedBox(height: 20), + Text("Gas limit", style: STextStyles.smallMed12(context)), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 1, + controller: gasLimitController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + focusNode: gasLimitFocus, + onChanged: (value) { + final intValue = int.tryParse(value); + if (intValue == null) { + gasLimitController.text = _gasLimitCache.toString(); + return; + } + + _gasLimitCache = intValue; + + widget.stateChanged(_current); + }, + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), + decoration: standardInputDecoration( + null, + gasLimitFocus, + context, + desktopMed: Util.isDesktop, + ).copyWith( + contentPadding: EdgeInsets.only( + left: 16, + top: Util.isDesktop ? 11 : 6, + bottom: Util.isDesktop ? 12 : 8, + right: 5, ), - ); - }, + ), + ), ), ], ); From 54bb20f811b3b06217f34db8c9e8bd830a8095db Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 08:19:35 -0600 Subject: [PATCH 028/206] check range --- lib/widgets/eth_fee_form.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/widgets/eth_fee_form.dart b/lib/widgets/eth_fee_form.dart index b7554a1df..2f4e2889e 100644 --- a/lib/widgets/eth_fee_form.dart +++ b/lib/widgets/eth_fee_form.dart @@ -268,7 +268,9 @@ class _EthFeeFormState extends State { focusNode: gasLimitFocus, onChanged: (value) { final intValue = int.tryParse(value); - if (intValue == null) { + if (intValue == null || + intValue < widget.minGasLimit || + intValue > widget.maxGasLimit) { gasLimitController.text = _gasLimitCache.toString(); return; } From 634439047697dbfd53db3c9f1dacb3e5f89dd83f Mon Sep 17 00:00:00 2001 From: dethe <76167420+detherminal@users.noreply.github.com> Date: Fri, 25 Apr 2025 19:50:09 +0300 Subject: [PATCH 029/206] refactor: states and views of restore options --- .../name_your_wallet_view.dart | 2 +- .../restore_options_view.dart | 164 ++++++++++-------- 2 files changed, 92 insertions(+), 74 deletions(-) diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index 7f867d505..91aa555f6 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -322,7 +322,7 @@ class _NameYourWalletViewState extends ConsumerState { ) : Semantics( label: - "Clear Block Height Field Button. Clears the block height field.", + "Clear Wallet Name Field Button. Clears the wallet name field.", excludeSemantics: true, child: XIcon( width: isDesktop ? 21 : 18, diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index b4a7d3231..a7fe47d6e 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -10,6 +10,7 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:logger/logger.dart'; @@ -476,44 +477,52 @@ class _SeedRestoreOptionState extends ConsumerState { onTap: widget.dateChooserFunction, controller: widget.dateController, ) : - TextField( - focusNode: widget.blockHeightFocusNode, - controller: widget.blockHeightController, - keyboardType: TextInputType.number, - textInputAction: TextInputAction.done, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), - onChanged: (value) { - setState(() { - _blockFieldEmpty = value.isEmpty; - }); - }, - decoration: standardInputDecoration( - "Start scanning from...", - widget.blockHeightFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: TextFieldIconButton(child: - Semantics( + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + focusNode: widget.blockHeightFocusNode, + controller: widget.blockHeightController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + textInputAction: TextInputAction.done, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + onChanged: (value) { + setState(() { + _blockFieldEmpty = value.isEmpty; + }); + }, + decoration: standardInputDecoration( + "Start scanning from...", + widget.blockHeightFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: TextFieldIconButton(child: + Semantics( label: "Clear Block Height Field Button. Clears the block height field", excludeSemantics: true, child: !_blockFieldEmpty ? XIcon( - width: Util.isDesktop ? 24 : 16, - height: Util.isDesktop ? 24 : 16, - ) + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) : const SizedBox.shrink(), ), - onTap: () { - widget.blockHeightController.text = ""; - setState(() { - _blockFieldEmpty = true; - }); - }, + onTap: () { + widget.blockHeightController.text = ""; + setState(() { + _blockFieldEmpty = true; + }); + }, + ), ), ), ), @@ -778,9 +787,7 @@ class _SeedRestoreOptionState extends ConsumerState { void initState() { super.initState(); - setState(() { - _blockFieldEmpty = widget.blockHeightController.text.isEmpty; - }); + _blockFieldEmpty = widget.blockHeightController.text.isEmpty; } } @@ -854,44 +861,57 @@ class _ViewOnlyRestoreOptionState extends State { onTap: widget.dateChooserFunction, controller: widget.dateController, ) - : TextField( - focusNode: widget.blockHeightFocusNode, - controller: widget.blockHeightController, - keyboardType: TextInputType.number, - textInputAction: TextInputAction.done, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), - decoration: standardInputDecoration( - "Start scanning from...", - widget.blockHeightFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: TextFieldIconButton( - child: Semantics( - label: - "Clear Block Height Field Button. Clears the block height field", - excludeSemantics: true, - child: !_blockFieldEmpty - ? XIcon( - width: Util.isDesktop ? 24 : 16, - height: Util.isDesktop ? 24 : 16, - ) - : const SizedBox.shrink(), - ), - onTap: () { - widget.blockHeightController.text = ""; - setState(() { - _blockFieldEmpty = true; - }); - }, - ), + : ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + focusNode: widget.blockHeightFocusNode, + controller: widget.blockHeightController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + textInputAction: TextInputAction.done, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + onChanged: (value) { + setState(() { + _blockFieldEmpty = value.isEmpty; + }); + }, + decoration: standardInputDecoration( + "Start scanning from...", + widget.blockHeightFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: TextFieldIconButton( + child: Semantics( + label: + "Clear Block Height Field Button. Clears the block height field", + excludeSemantics: true, + child: !_blockFieldEmpty + ? XIcon( + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) + : const SizedBox.shrink(), ), + onTap: () { + widget.blockHeightController.text = ""; + setState(() { + _blockFieldEmpty = true; + }); + }, ), ), + ), + ), + ), if (showDateOption) const SizedBox( height: 8, @@ -927,8 +947,6 @@ class _ViewOnlyRestoreOptionState extends State { void initState() { super.initState(); - setState(() { - _blockFieldEmpty = widget.blockHeightController.text.isEmpty; - }); + _blockFieldEmpty = widget.blockHeightController.text.isEmpty; } } From c88dbbc5c860c5b0b0169235cd936fae493b1bc4 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 11:17:26 -0600 Subject: [PATCH 030/206] fix https://github.com/cypherstack/stack_wallet/issues/1121 --- .../send_view/confirm_transaction_view.dart | 788 +++++++++--------- 1 file changed, 376 insertions(+), 412 deletions(-) diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 5090645e3..6d40734b0 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -118,11 +118,7 @@ class _ConfirmTransactionViewState ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); final List txids = []; Future txDataFuture; @@ -131,11 +127,13 @@ class _ConfirmTransactionViewState try { if (widget.isTokenTx) { - txDataFuture = - ref.read(pCurrentTokenWallet)!.confirmSend(txData: widget.txData); + txDataFuture = ref + .read(pCurrentTokenWallet)! + .confirmSend(txData: widget.txData); } else if (widget.isPaynymNotificationTransaction) { - txDataFuture = (wallet as PaynymInterface) - .broadcastNotificationTx(txData: widget.txData); + txDataFuture = (wallet as PaynymInterface).broadcastNotificationTx( + txData: widget.txData, + ); } else if (widget.isPaynymTransaction) { txDataFuture = wallet.confirmSend(txData: widget.txData); } else { @@ -145,8 +143,9 @@ class _ConfirmTransactionViewState if (widget.txData.sparkMints == null) { txDataFuture = wallet.confirmSend(txData: widget.txData); } else { - txDataFuture = - wallet.confirmSparkMintTransactions(txData: widget.txData); + txDataFuture = wallet.confirmSparkMintTransactions( + txData: widget.txData, + ); } break; @@ -171,10 +170,7 @@ class _ConfirmTransactionViewState } } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); sendProgressController.triggerSuccess?.call(); await Future.delayed(const Duration(seconds: 5)); @@ -189,12 +185,10 @@ class _ConfirmTransactionViewState // save note for (final txid in txids) { - await ref.read(mainDBProvider).putTransactionNote( - TransactionNote( - walletId: walletId, - txid: txid, - value: note, - ), + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), ); } @@ -209,8 +203,9 @@ class _ConfirmTransactionViewState // pop back to wallet if (mounted) { if (widget.onSuccessInsteadOfRouteOnSuccess == null) { - Navigator.of(context) - .popUntil(ModalRoute.withName(routeOnSuccessName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(routeOnSuccessName)); } else { widget.onSuccessInsteadOfRouteOnSuccess!.call(); } @@ -253,9 +248,7 @@ class _ConfirmTransactionViewState "Broadcast transaction failed", style: STextStyles.desktopH3(context), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Flexible( child: SingleChildScrollView( child: SelectableText( @@ -264,9 +257,7 @@ class _ConfirmTransactionViewState ), ), ), - const SizedBox( - height: 56, - ), + const SizedBox(height: 56), Row( children: [ const Spacer(), @@ -294,9 +285,10 @@ class _ConfirmTransactionViewState child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -377,7 +369,8 @@ class _ConfirmTransactionViewState case FiroType.spark: fee = widget.txData.fee; - amountWithoutChange = (widget.txData.amountWithoutChange ?? + amountWithoutChange = + (widget.txData.amountWithoutChange ?? Amount.zeroWith( fractionDigits: wallet.cryptoCurrency.fractionDigits, )) + @@ -394,82 +387,79 @@ class _ConfirmTransactionViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - // if (FocusScope.of(context).hasFocus) { - // FocusScope.of(context).unfocus(); - // await Future.delayed(Duration(milliseconds: 50)); - // } - Navigator.of(context).pop(); - }, - ), - title: Text( - "Confirm transaction", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed(Duration(milliseconds: 50)); + // } + Navigator.of(context).pop(); + }, + ), + title: Text( + "Confirm transaction", + style: STextStyles.navBarTitle(context), ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, + ), + body: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.min, - children: [ - Row( + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, children: [ - AppBarBackButton( - size: 40, - iconSize: 24, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(), - ), - Text( - "Confirm $unit transaction", - style: STextStyles.desktopH3(context), + Row( + children: [ + AppBarBackButton( + size: 40, + iconSize: 24, + onPressed: + () => + Navigator.of(context, rootNavigator: true).pop(), + ), + Text( + "Confirm $unit transaction", + style: STextStyles.desktopH3(context), + ), + ], ), + Flexible(child: SingleChildScrollView(child: child)), ], ), - Flexible( - child: SingleChildScrollView( - child: child, - ), - ), - ], - ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, @@ -478,13 +468,8 @@ class _ConfirmTransactionViewState Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Send $unit", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 12, - ), + Text("Send $unit", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -495,9 +480,7 @@ class _ConfirmTransactionViewState : "Recipient", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( widget.isPaynymTransaction ? widget.txData.paynymAccountLite!.nymName @@ -508,25 +491,23 @@ class _ConfirmTransactionViewState ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - ), + Text("Amount", style: STextStyles.smallMed12(context)), SelectableText( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( amountWithoutChange, - ethContract: widget.isTokenTx - ? ref - .watch(pCurrentTokenWallet)! - .tokenContract - : null, + ethContract: + widget.isTokenTx + ? ref + .watch(pCurrentTokenWallet)! + .tokenContract + : null, ), style: STextStyles.itemSubtitle12(context), textAlign: TextAlign.right, @@ -534,10 +515,7 @@ class _ConfirmTransactionViewState ], ), ), - if (coin is! NanoCurrency) - const SizedBox( - height: 12, - ), + if (coin is! NanoCurrency) const SizedBox(height: 12), if (coin is! NanoCurrency) RoundedWhiteContainer( child: Row( @@ -556,9 +534,7 @@ class _ConfirmTransactionViewState ), ), if (widget.txData.fee != null && widget.txData.vSize != null) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.fee != null && widget.txData.vSize != null) RoundedWhiteContainer( child: Row( @@ -568,9 +544,7 @@ class _ConfirmTransactionViewState "sats/vByte", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle12(context), @@ -579,9 +553,7 @@ class _ConfirmTransactionViewState ), ), if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty) RoundedWhiteContainer( child: Column( @@ -591,9 +563,7 @@ class _ConfirmTransactionViewState "On chain note", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( widget.txData.noteOnChain!, style: STextStyles.itemSubtitle12(context), @@ -602,9 +572,7 @@ class _ConfirmTransactionViewState ), ), if (widget.txData.note!.isNotEmpty) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (widget.txData.note!.isNotEmpty) RoundedWhiteContainer( child: Column( @@ -614,9 +582,7 @@ class _ConfirmTransactionViewState (coin is Epiccash) ? "Local Note" : "Note", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( widget.txData.note!, style: STextStyles.itemSubtitle12(context), @@ -644,9 +610,10 @@ class _ConfirmTransactionViewState children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, borderRadius: BorderRadius.only( topLeft: Radius.circular( Constants.size.circularBorderRadius, @@ -674,9 +641,7 @@ class _ConfirmTransactionViewState width: 32, height: 32, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Text( "Send $unit", style: STextStyles.desktopTextMedium(context), @@ -697,9 +662,7 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Builder( builder: (context) { final externalCalls = ref.watch( @@ -710,77 +673,81 @@ class _ConfirmTransactionViewState String fiatAmount = "N/A"; if (externalCalls) { - final price = widget.isTokenTx - ? ref - .read( - priceAnd24hChangeNotifierProvider, - ) - .getTokenPrice( - ref - .read(pCurrentTokenWallet)! - .tokenContract - .address, - ) - .item1 - : ref - .read( - priceAnd24hChangeNotifierProvider, - ) - .getPrice(coin) - .item1; + final price = + widget.isTokenTx + ? ref + .read( + priceAnd24hChangeNotifierProvider, + ) + .getTokenPrice( + ref + .read(pCurrentTokenWallet)! + .tokenContract + .address, + ) + .item1 + : ref + .read( + priceAnd24hChangeNotifierProvider, + ) + .getPrice(coin) + .item1; if (price > Decimal.zero) { - fiatAmount = - (amountWithoutChange.decimal * price) - .toAmount(fractionDigits: 2) - .fiatString( - locale: ref + fiatAmount = (amountWithoutChange.decimal * + price) + .toAmount(fractionDigits: 2) + .fiatString( + locale: + ref .read( localeServiceChangeNotifierProvider, ) .locale, - ); + ); } } return Row( children: [ SelectableText( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( amountWithoutChange, - ethContract: widget.isTokenTx - ? ref - .watch(pCurrentTokenWallet)! - .tokenContract - : null, + ethContract: + widget.isTokenTx + ? ref + .watch( + pCurrentTokenWallet, + )! + .tokenContract + : null, + ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, ), - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), ), if (externalCalls) Text( " | ", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (externalCalls) SelectableText( - "~$fiatAmount ${ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - )}", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + "~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ); @@ -791,9 +758,10 @@ class _ConfirmTransactionViewState ), Container( height: 1, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ), Padding( padding: const EdgeInsets.all(12), @@ -809,22 +777,24 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( // TODO: [prio=med] spark transaction specifics - better handling widget.isPaynymTransaction ? widget.txData.paynymAccountLite!.nymName : widget.txData.recipients?.first.address ?? - widget.txData.sparkRecipients!.first + widget + .txData + .sparkRecipients! + .first .address, style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -833,9 +803,10 @@ class _ConfirmTransactionViewState if (widget.isPaynymTransaction) Container( height: 1, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ), if (widget.isPaynymTransaction) Padding( @@ -850,17 +821,16 @@ class _ConfirmTransactionViewState context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( ref.watch(pAmountFormatter(coin)).format(fee!), style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -905,10 +875,7 @@ class _ConfirmTransactionViewState ), if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(left: 32, right: 32), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -919,10 +886,7 @@ class _ConfirmTransactionViewState style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) - const SizedBox( - height: 8, - ), + if (coin is Epiccash) const SizedBox(height: 8), if (coin is Epiccash) ClipRRect( borderRadius: BorderRadius.circular( @@ -941,47 +905,46 @@ class _ConfirmTransactionViewState _onChainNoteFocusNode, context, ).copyWith( - suffixIcon: onChainNoteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - onChainNoteController.text = ""; - }); - }, - ), - ], + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController.text = + ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - if (coin is Epiccash) - const SizedBox( - height: 12, - ), + if (coin is Epiccash) const SizedBox(height: 12), SelectableText( (coin is Epiccash) ? "Local Note (optional)" : "Note (optional)", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -993,11 +956,13 @@ class _ConfirmTransactionViewState enableSuggestions: isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), onChanged: (_) => setState(() {}), @@ -1013,39 +978,36 @@ class _ConfirmTransactionViewState bottom: 12, right: 5, ), - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState( - () => noteController.text = "", - ); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState( + () => noteController.text = "", + ); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ], ), ), if (isDesktop && !widget.isPaynymTransaction) Padding( - padding: const EdgeInsets.only( - left: 32, - ), + padding: const EdgeInsets.only(left: 32), child: Text( "Transaction fee", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -1053,19 +1015,16 @@ class _ConfirmTransactionViewState ), if (isDesktop && !widget.isPaynymTransaction) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( ref.watch(pAmountFormatter(coin)).format(fee!), style: STextStyles.itemSubtitle(context), @@ -1077,9 +1036,7 @@ class _ConfirmTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - left: 32, - ), + padding: const EdgeInsets.only(left: 32), child: Text( "sats/vByte", style: STextStyles.desktopTextExtraExtraSmall(context), @@ -1090,19 +1047,16 @@ class _ConfirmTransactionViewState widget.txData.fee != null && widget.txData.vSize != null) Padding( - padding: const EdgeInsets.only( - top: 10, - left: 32, - right: 32, - ), + padding: const EdgeInsets.only(top: 10, left: 32, right: 32), child: RoundedContainer( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 18, ), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: SelectableText( "~${fee!.raw.toInt() ~/ widget.txData.vSize!}", style: STextStyles.itemSubtitle(context), @@ -1110,154 +1064,164 @@ class _ConfirmTransactionViewState ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 23 : 12, - ), + SizedBox(height: isDesktop ? 23 : 12), if (!widget.isTokenTx) Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: RoundedContainer( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 16, - vertical: 18, - ) - : const EdgeInsets.all(12), - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, + padding: + isDesktop + ? const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ) + : const EdgeInsets.all(12), + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( isDesktop ? "Total amount to send" : "Total amount", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.titleBold12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), ), SelectableText( ref .watch(pAmountFormatter(coin)) .format(amountWithoutChange + fee!), - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ) - : STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ) + : STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), textAlign: TextAlign.right, ), ], ), ), ), - SizedBox( - height: isDesktop ? 28 : 16, - ), + SizedBox(height: isDesktop ? 28 : 16), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: PrimaryButton( label: "Send", buttonHeight: isDesktop ? ButtonHeight.l : null, onPressed: () async { - final dynamic unlocked; - if (isDesktop) { - unlocked = await showDialog( + final unlocked = await showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - DesktopDialogCloseButton(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: DesktopAuthSend( - coin: coin, - ), - ), - ], - ), - ), + ), ); + if (context.mounted && unlocked is bool) { + if (unlocked) { + unawaited(_attemptSend(context)); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Invalid passphrase", + context: context, + ), + ); + } + } } else { - unlocked = await Navigator.push( + final unlocked = await Navigator.push( context, RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - popOnSuccess: true, - routeOnSuccessArguments: true, - routeOnSuccess: "", - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to send transaction", - biometricsAuthenticationTitle: "Confirm Transaction", + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: + "Confirm Transaction", + ), + settings: const RouteSettings( + name: "/confirmsendlockscreen", ), - settings: - const RouteSettings(name: "/confirmsendlockscreen"), ), ); - } - if (mounted) { - if (unlocked == true) { - unawaited(_attemptSend(context)); - } else { - unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: Util.isDesktop - ? "Invalid passphrase" - : "Invalid PIN", - context: context, - ), - ); + if (context.mounted) { + if (unlocked == true) { + unawaited(_attemptSend(context)); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Invalid PIN", + context: context, + ), + ); + } } } }, ), ), - if (isDesktop) - const SizedBox( - height: 32, - ), + if (isDesktop) const SizedBox(height: 32), ], ), ), From 04631ac3b8556d2f7d9766d6163202abd6cae254 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 12:28:03 -0600 Subject: [PATCH 031/206] fix https://github.com/cypherstack/stack_wallet/issues/1108 --- .../confirm_change_now_send.dart | 640 ++++++++---------- 1 file changed, 301 insertions(+), 339 deletions(-) diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index 999fca764..239b56db4 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -17,6 +17,7 @@ import 'package:uuid/uuid.dart'; import '../../models/exchange/response_objects/trade.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/trade_wallet_lookup.dart'; +import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; @@ -98,11 +99,7 @@ class _ConfirmChangeNowSendViewState ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); late String txid; Future txidFuture; @@ -118,10 +115,7 @@ class _ConfirmChangeNowSendViewState unawaited(wallet.refresh()); - final results = await Future.wait([ - txidFuture, - time, - ]); + final results = await Future.wait([txidFuture, time]); sendProgressController.triggerSuccess?.call(); await Future.delayed(const Duration(seconds: 5)); @@ -129,15 +123,15 @@ class _ConfirmChangeNowSendViewState txid = (results.first as TxData).txid!; // save note - await ref.read(mainDBProvider).putTransactionNote( - TransactionNote( - walletId: walletId, - txid: txid, - value: note, - ), + await ref + .read(mainDBProvider) + .putTransactionNote( + TransactionNote(walletId: walletId, txid: txid, value: note), ); - await ref.read(tradeSentFromStackLookupProvider).save( + await ref + .read(tradeSentFromStackLookupProvider) + .save( tradeWalletLookup: TradeWalletLookup( uuid: const Uuid().v1(), txid: txid, @@ -162,7 +156,11 @@ class _ConfirmChangeNowSendViewState Navigator.of(context).popUntil(ModalRoute.withName(routeOnSuccessName)); } } catch (e, s) { - Logging.instance.e("Broadcast transaction failed: ", error: e, stackTrace: s); + Logging.instance.e( + "Broadcast transaction failed: ", + error: e, + stackTrace: s, + ); // pop sending dialog Navigator.of(context).pop(); @@ -182,9 +180,10 @@ class _ConfirmChangeNowSendViewState child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), ), onPressed: () { @@ -205,53 +204,61 @@ class _ConfirmChangeNowSendViewState if (Util.isDesktop) { unlocked = await showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, + builder: + (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - DesktopDialogCloseButton(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [DesktopDialogCloseButton()], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(coin: coin), + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: DesktopAuthSend( - coin: coin, - ), - ), - ], - ), - ), + ), ); } else { unlocked = await Navigator.push( context, RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - popOnSuccess: true, - routeOnSuccessArguments: true, - routeOnSuccess: "", - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: "Authenticate to send transaction", - biometricsAuthenticationTitle: "Confirm Transaction", - ), + builder: + (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: "Authenticate to send transaction", + biometricsAuthenticationTitle: "Confirm Transaction", + ), settings: const RouteSettings(name: "/confirmsendlockscreen"), ), ); } - if (unlocked is bool && unlocked && mounted) { - await _attemptSend(context); + if (unlocked is bool && mounted) { + if (unlocked) { + await _attemptSend(context); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Invalid passphrase", + context: context, + ), + ); + } } } @@ -292,11 +299,7 @@ class _ConfirmChangeNowSendViewState body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -318,205 +321,195 @@ class _ConfirmChangeNowSendViewState }, child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxHeight: double.infinity, - maxWidth: 580, - child: Column( - children: [ - Row( + builder: + (child) => DesktopDialog( + maxHeight: double.infinity, + maxWidth: 580, + child: Column( children: [ - const SizedBox( - width: 6, - ), - const AppBarBackButton( - isCompact: true, - iconSize: 23, - ), - const SizedBox( - width: 12, - ), - Text( - "Confirm ${ref.watch(pWalletCoin(walletId)).ticker} transaction", - style: STextStyles.desktopH3(context), + Row( + children: [ + const SizedBox(width: 6), + const AppBarBackButton(isCompact: true, iconSize: 23), + const SizedBox(width: 12), + Text( + "Confirm ${ref.watch(pWalletCoin(walletId)).ticker} transaction", + style: STextStyles.desktopH3(context), + ), + ], ), - ], - ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Column( - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - borderColor: Theme.of(context) - .extension()! - .background, - child: child, + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, ), - const SizedBox( - height: 16, - ), - Row( + child: Column( children: [ - Text( - "Transaction fee", - style: - STextStyles.desktopTextExtraExtraSmall(context), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: child, ), - ], - ), - const SizedBox( - height: 10, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - ref - .watch( - pAmountFormatter( - ref.watch(pWalletCoin(walletId)), - ), - ) - .format(widget.txData.fee!), - style: - STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - ], - ), - ), - const SizedBox( - height: 16, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Total amount", - style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + const SizedBox(height: 16), + Row( + children: [ + Text( + "Transaction fee", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), - ), - Builder( - builder: (context) { - final coin = ref.read(pWalletCoin(walletId)); - final fee = widget.txData.fee!; - final amount = widget.txData.amountWithoutChange!; - final total = amount + fee; - - return Text( - ref.watch(pAmountFormatter(coin)).format(total), - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + ], + ), + const SizedBox(height: 10), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + ref + .watch( + pAmountFormatter( + ref.watch(pWalletCoin(walletId)), + ), + ) + .format(widget.txData.fee!), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), - textAlign: TextAlign.right, - ); - }, - ), - ], - ), - ), - const SizedBox( - height: 16, - ), - Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: ButtonHeight.l, - onPressed: Navigator.of(context).pop, + ), + ], ), ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Send", - buttonHeight: isDesktop ? ButtonHeight.l : null, - onPressed: _confirmSend, + const SizedBox(height: 16), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Total amount", + style: STextStyles.titleBold12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + ), + Builder( + builder: (context) { + final coin = ref.read(pWalletCoin(walletId)); + final fee = widget.txData.fee!; + final amount = + widget.txData.amountWithoutChange!; + final total = amount + fee; + + return Text( + ref + .watch(pAmountFormatter(coin)) + .format(total), + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, + ), + textAlign: TextAlign.right, + ); + }, + ), + ], ), ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: Navigator.of(context).pop, + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Send", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: _confirmSend, + ), + ), + ], + ), ], ), - ], - ), + ), + ], ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Container( - decoration: BoxDecoration( - color: Theme.of(context).extension()!.background, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, + builder: + (child) => Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.background, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Row(children: [child]), ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - child, - ], - ), - ), - ), child: Text( "Send ${ref.watch(pWalletCoin(walletId)).ticker}", - style: isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.pageTitleH1(context), + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.pageTitleH1(context), ), ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Send from", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Send from", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( ref.watch(pWalletName(walletId)), style: STextStyles.itemSubtitle12(context), @@ -526,13 +519,10 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -541,9 +531,7 @@ class _ConfirmChangeNowSendViewState "${trade.exchangeName} address", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( widget.txData.recipients!.first.address, style: STextStyles.itemSubtitle12(context), @@ -553,68 +541,64 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - ), + Text("Amount", style: STextStyles.smallMed12(context)), ConditionalParent( condition: isDesktop, - builder: (child) => Row( - children: [ - child, - Builder( - builder: (context) { - final coin = ref.watch(pWalletCoin(walletId)); - final price = ref.watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin)), - ); - final amountWithoutChange = - widget.txData.amountWithoutChange!; - final value = - (price.item1 * amountWithoutChange.decimal) + builder: + (child) => Row( + children: [ + child, + Builder( + builder: (context) { + final coin = ref.watch(pWalletCoin(walletId)); + final price = ref.watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ); + final amountWithoutChange = + widget.txData.amountWithoutChange!; + final value = (price.item1 * + amountWithoutChange.decimal) .toAmount(fractionDigits: 2); - final currency = ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), - ); - final locale = ref.watch( - localeServiceChangeNotifierProvider.select( - (value) => value.locale, - ), - ); - - return Text( - " | ${value.fiatString(locale: locale)} $currency", - style: STextStyles.desktopTextExtraExtraSmall( - context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - ); - }, + final currency = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), + ); + final locale = ref.watch( + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), + ); + + return Text( + " | ${value.fiatString(locale: locale)} $currency", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle2, + ), + ); + }, + ), + ], ), - ], - ), child: Text( ref .watch( - pAmountFormatter( - ref.watch(pWalletCoin(walletId)), - ), + pAmountFormatter(ref.watch(pWalletCoin(walletId))), ) .format((widget.txData.amountWithoutChange!)), style: STextStyles.itemSubtitle12(context), @@ -626,13 +610,10 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -646,9 +627,7 @@ class _ConfirmChangeNowSendViewState .watch( pAmountFormatter(ref.read(pWalletCoin(walletId))), ) - .format( - widget.txData.fee!, - ), + .format(widget.txData.fee!), style: STextStyles.itemSubtitle12(context), textAlign: TextAlign.right, ), @@ -657,24 +636,16 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Note", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 4, - ), + Text("Note", style: STextStyles.smallMed12(context)), + const SizedBox(height: 4), Text( widget.txData.note ?? "", style: STextStyles.itemSubtitle12(context), @@ -684,21 +655,15 @@ class _ConfirmChangeNowSendViewState ), isDesktop ? Container( - color: - Theme.of(context).extension()!.background, - height: 1, - ) - : const SizedBox( - height: 12, - ), + color: Theme.of(context).extension()!.background, + height: 1, + ) + : const SizedBox(height: 12), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Trade ID", - style: STextStyles.smallMed12(context), - ), + Text("Trade ID", style: STextStyles.smallMed12(context)), Text( trade.tradeId, style: STextStyles.itemSubtitle12(context), @@ -707,24 +672,23 @@ class _ConfirmChangeNowSendViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), if (!isDesktop) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackSuccess, + color: + Theme.of( + context, + ).extension()!.snackBarBackSuccess, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Total amount", style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + color: + Theme.of( + context, + ).extension()!.textConfirmTotalAmount, ), ), Builder( @@ -737,9 +701,10 @@ class _ConfirmChangeNowSendViewState return Text( ref.watch(pAmountFormatter(coin)).format(total), style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textConfirmTotalAmount, + color: + Theme.of(context) + .extension()! + .textConfirmTotalAmount, ), textAlign: TextAlign.right, ); @@ -748,10 +713,7 @@ class _ConfirmChangeNowSendViewState ], ), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), if (!isDesktop) const Spacer(), if (!isDesktop) PrimaryButton( From b40daff8425cd4402c2dc77c07eecfc1002e4614 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 14:29:00 -0600 Subject: [PATCH 032/206] use state provider and autoformatting --- .../restore_options_view.dart | 619 +++++++++--------- 1 file changed, 294 insertions(+), 325 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index a7fe47d6e..6d424a2c8 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -8,6 +8,8 @@ * */ +import 'package:cs_monero/src/deprecated/get_height_by_date.dart' + as cs_monero_deprecated; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -50,7 +52,7 @@ import 'sub_widgets/restore_from_date_picker.dart'; import 'sub_widgets/restore_options_next_button.dart'; import 'sub_widgets/restore_options_platform_layout.dart'; -import 'package:cs_monero/src/deprecated/get_height_by_date.dart' as cs_monero_deprecated; +final _pIsUsingDate = StateProvider.autoDispose((_) => true); class RestoreOptionsView extends ConsumerStatefulWidget { const RestoreOptionsView({ @@ -76,12 +78,11 @@ class _RestoreOptionsViewState extends ConsumerState { late TextEditingController _dateController; late TextEditingController _blockHeightController; late FocusNode _blockHeightFocusNode; - final ValueNotifier _isUsingDateNotifier = ValueNotifier(true); late FocusNode textFieldFocusNode; late final FocusNode passwordFocusNode; late final TextEditingController passwordController; - final bool _nextEnabled = true; + bool _hasBlockHeight = false; DateTime? _restoreFromDate; bool hidePassword = true; @@ -92,6 +93,7 @@ class _RestoreOptionsViewState extends ConsumerState { @override void initState() { + super.initState(); walletName = widget.walletName; coin = widget.coin; isDesktop = Util.isDesktop; @@ -102,9 +104,18 @@ class _RestoreOptionsViewState extends ConsumerState { passwordFocusNode = FocusNode(); _blockHeightController = TextEditingController(); _blockHeightFocusNode = FocusNode(); - _isUsingDateNotifier.value = true; - super.initState(); + _blockHeightController.addListener(() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + if (!ref.read(_pIsUsingDate)) { + setState(() { + _hasBlockHeight = _blockHeightController.text.isNotEmpty; + }); + } + } + }); + }); } @override @@ -132,7 +143,7 @@ class _RestoreOptionsViewState extends ConsumerState { if (mounted) { int height = 0; - if (_isUsingDateNotifier.value) { + if (ref.read(_pIsUsingDate)) { height = getBlockHeightFromDate(_restoreFromDate); } else { height = int.tryParse(_blockHeightController.text) ?? 0; @@ -195,9 +206,7 @@ class _RestoreOptionsViewState extends ConsumerState { backgroundColor: Colors.transparent, context: context, shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (_) { return MnemonicWordCountSelectSheet( @@ -212,22 +221,17 @@ class _RestoreOptionsViewState extends ConsumerState { int height = 0; if (date != null) { if (widget.coin is Monero) { - height = cs_monero_deprecated.getMoneroHeightByDate( - date: date, - ); + height = cs_monero_deprecated.getMoneroHeightByDate(date: date); } if (widget.coin is Wownero) { - height = cs_monero_deprecated.getWowneroHeightByDate( - date: date, - ); + height = cs_monero_deprecated.getWowneroHeightByDate(date: date); } if (height < 0) { height = 0; } if (widget.coin is Epiccash) { - final int secondsSinceEpoch = - date.millisecondsSinceEpoch ~/ 1000; + final int secondsSinceEpoch = date.millisecondsSinceEpoch ~/ 1000; const int epicCashFirstBlock = 1565370278; const double overestimateSecondsPerBlock = 61; final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock; @@ -235,7 +239,7 @@ class _RestoreOptionsViewState extends ConsumerState { chosenSeconds ~/ overestimateSecondsPerBlock; height = approximateHeight; - if (height < 0) { + if (height < 0) { height = 0; } } @@ -244,7 +248,10 @@ class _RestoreOptionsViewState extends ConsumerState { } return height; } catch (e) { - Logging.instance.log(Level.info, "Error getting block height from date: $e"); + Logging.instance.log( + Level.info, + "Error getting block height from date: $e", + ); return 0; } } @@ -257,25 +264,27 @@ class _RestoreOptionsViewState extends ConsumerState { return MasterScaffold( isDesktop: isDesktop, - appBar: isDesktop - ? const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ) - : AppBar( - leading: AppBarBackButton( - onPressed: () { - if (textFieldFocusNode.hasFocus) { - textFieldFocusNode.unfocus(); - Future.delayed(const Duration(milliseconds: 100)) - .then((value) => Navigator.of(context).pop()); - } else { - Navigator.of(context).pop(); - } - }, + appBar: + isDesktop + ? const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () { + if (textFieldFocusNode.hasFocus) { + textFieldFocusNode.unfocus(); + Future.delayed( + const Duration(milliseconds: 100), + ).then((value) => Navigator.of(context).pop()); + } else { + Navigator.of(context).pop(); + } + }, + ), ), - ), body: RestoreOptionsPlatformLayout( isDesktop: isDesktop, child: ConstrainedBox( @@ -285,28 +294,18 @@ class _RestoreOptionsViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Spacer( - flex: isDesktop ? 10 : 1, - ), - if (!isDesktop) - CoinImage( - coin: coin, - height: 100, - width: 100, - ), - SizedBox( - height: isDesktop ? 0 : 16, - ), + Spacer(flex: isDesktop ? 10 : 1), + if (!isDesktop) CoinImage(coin: coin, height: 100, width: 100), + SizedBox(height: isDesktop ? 0 : 16), Text( "Restore options", textAlign: TextAlign.center, - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 40 : 24, + style: + isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), ), + SizedBox(height: isDesktop ? 40 : 24), if (coin is ViewOnlyOptionCurrencyInterface) SizedBox( height: isDesktop ? 56 : 48, @@ -317,9 +316,10 @@ class _RestoreOptionsViewState extends ConsumerState { offText: "View Only", onColor: Theme.of(context).extension()!.popupBG, - offColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + offColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, isOn: _showViewOnlyOption, onValueChanged: (value) { setState(() { @@ -335,51 +335,41 @@ class _RestoreOptionsViewState extends ConsumerState { ), ), if (coin is ViewOnlyOptionCurrencyInterface) - SizedBox( - height: isDesktop ? 40 : 24, - ), + SizedBox(height: isDesktop ? 40 : 24), _showViewOnlyOption ? ViewOnlyRestoreOption( - coin: coin, - dateController: _dateController, - dateChooserFunction: - isDesktop ? chooseDesktopDate : chooseDate, - blockHeightController: _blockHeightController, - blockHeightFocusNode: _blockHeightFocusNode, - isUsingDateNotifier: _isUsingDateNotifier, - ) + coin: coin, + dateController: _dateController, + dateChooserFunction: + isDesktop ? chooseDesktopDate : chooseDate, + blockHeightController: _blockHeightController, + blockHeightFocusNode: _blockHeightFocusNode, + ) : SeedRestoreOption( - coin: coin, - dateController: _dateController, - blockHeightController: _blockHeightController, - blockHeightFocusNode: _blockHeightFocusNode, - isUsingDateNotifier: _isUsingDateNotifier, - pwController: passwordController, - pwFocusNode: passwordFocusNode, - supportsMnemonicPassphrase: supportsMnemonicPassphrase, - dateChooserFunction: - isDesktop ? chooseDesktopDate : chooseDate, - chooseMnemonicLength: chooseMnemonicLength, - lelScanChanged: (value) { - enableLelantusScanning = value; - }, - ), - if (!isDesktop) - const Spacer( - flex: 3, - ), - if (isDesktop) - const SizedBox( - height: 32, - ), + coin: coin, + dateController: _dateController, + blockHeightController: _blockHeightController, + blockHeightFocusNode: _blockHeightFocusNode, + pwController: passwordController, + pwFocusNode: passwordFocusNode, + supportsMnemonicPassphrase: supportsMnemonicPassphrase, + dateChooserFunction: + isDesktop ? chooseDesktopDate : chooseDate, + chooseMnemonicLength: chooseMnemonicLength, + lelScanChanged: (value) { + enableLelantusScanning = value; + }, + ), + if (!isDesktop) const Spacer(flex: 3), + SizedBox(height: isDesktop ? 32 : 12), RestoreOptionsNextButton( isDesktop: isDesktop, - onPressed: _nextEnabled ? nextPressed : null, + onPressed: + ref.watch(_pIsUsingDate) || _hasBlockHeight + ? nextPressed + : null, ), - if (isDesktop) - const Spacer( - flex: 15, - ), + if (isDesktop) const Spacer(flex: 15), ], ), ), @@ -395,7 +385,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { required this.dateController, required this.blockHeightController, required this.blockHeightFocusNode, - required this.isUsingDateNotifier, required this.pwController, required this.pwFocusNode, required this.supportsMnemonicPassphrase, @@ -408,7 +397,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { final TextEditingController dateController; final TextEditingController blockHeightController; final FocusNode blockHeightFocusNode; - final ValueNotifier isUsingDateNotifier; final TextEditingController pwController; final FocusNode pwFocusNode; final bool supportsMnemonicPassphrase; @@ -431,9 +419,11 @@ class _SeedRestoreOptionState extends ConsumerState { Widget build(BuildContext context) { final lengths = widget.coin.possibleMnemonicLengths; - final isMoneroAnd25 = widget.coin is Monero && + final isMoneroAnd25 = + widget.coin is Monero && ref.watch(mnemonicWordCountStateProvider.state).state == 25; - final isWowneroAnd25 = widget.coin is Wownero && + final isWowneroAnd25 = + widget.coin is Wownero && ref.watch(mnemonicWordCountStateProvider.state).state == 25; return Column( @@ -443,41 +433,37 @@ class _SeedRestoreOptionState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - widget.isUsingDateNotifier.value - ? "Choose start date" - : "Block height", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), + ref.watch(_pIsUsingDate) ? "Choose start date" : "Block height", + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), CustomTextButton( - text: widget.isUsingDateNotifier.value - ? "Use block height" - : "Use date", - onTap: () { - setState(() { - widget.isUsingDateNotifier.value = - !widget.isUsingDateNotifier.value; - }); - }, + text: + ref.watch(_pIsUsingDate) ? "Use block height" : "Use date", + onTap: + () => + ref.read(_pIsUsingDate.notifier).state = + !ref.read(_pIsUsingDate), ), ], ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - SizedBox( - height: Util.isDesktop ? 16 : 8, - ), + SizedBox(height: Util.isDesktop ? 16 : 8), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - widget.isUsingDateNotifier.value ? - RestoreFromDatePicker( - onTap: widget.dateChooserFunction, - controller: widget.dateController, - ) : - ClipRRect( + ref.watch(_pIsUsingDate) + ? RestoreFromDatePicker( + onTap: widget.dateChooserFunction, + controller: widget.dateController, + ) + : ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -485,15 +471,14 @@ class _SeedRestoreOptionState extends ConsumerState { focusNode: widget.blockHeightFocusNode, controller: widget.blockHeightController, keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], + inputFormatters: [FilteringTextInputFormatter.digitsOnly], textInputAction: TextInputAction.done, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), + style: + Util.isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2) + : STextStyles.field(context), onChanged: (value) { setState(() { _blockFieldEmpty = value.isEmpty; @@ -505,17 +490,19 @@ class _SeedRestoreOptionState extends ConsumerState { context, ).copyWith( suffixIcon: UnconstrainedBox( - child: TextFieldIconButton(child: - Semantics( - label: "Clear Block Height Field Button. Clears the block height field", - excludeSemantics: true, - child: !_blockFieldEmpty - ? XIcon( - width: Util.isDesktop ? 24 : 16, - height: Util.isDesktop ? 24 : 16, - ) - : const SizedBox.shrink(), - ), + child: TextFieldIconButton( + child: Semantics( + label: + "Clear Block Height Field Button. Clears the block height field", + excludeSemantics: true, + child: + !_blockFieldEmpty + ? XIcon( + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) + : const SizedBox.shrink(), + ), onTap: () { widget.blockHeightController.text = ""; setState(() { @@ -528,44 +515,42 @@ class _SeedRestoreOptionState extends ConsumerState { ), ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) RoundedWhiteContainer( child: Center( child: Text( - widget.isUsingDateNotifier.value + ref.watch(_pIsUsingDate) ? "Choose the date you made the wallet (approximate is fine)" : "Enter the initial block height of the wallet", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ) - : STextStyles.smallMed12(context).copyWith( - fontSize: 10, - ), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ) + : STextStyles.smallMed12( + context, + ).copyWith(fontSize: 10), ), ), ), if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), Text( "Choose recovery phrase length", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - SizedBox( - height: Util.isDesktop ? 16 : 8, - ), + SizedBox(height: Util.isDesktop ? 16 : 8), if (Util.isDesktop) DropdownButtonHideUnderline( child: DropdownButton2( @@ -592,28 +577,27 @@ class _SeedRestoreOptionState extends ConsumerState { Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), dropdownStyleData: DropdownStyleData( offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), ), ), @@ -622,9 +606,7 @@ class _SeedRestoreOptionState extends ConsumerState { chooseMnemonicLength: widget.chooseMnemonicLength, ), if (widget.supportsMnemonicPassphrase) - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), if (widget.supportsMnemonicPassphrase) Expandable( onExpandChanged: (state) { @@ -645,15 +627,17 @@ class _SeedRestoreOptionState extends ConsumerState { children: [ Text( "Advanced", - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ) - : STextStyles.smallMed12(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), SvgPicture.asset( @@ -662,9 +646,10 @@ class _SeedRestoreOptionState extends ConsumerState { : Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ], ), @@ -685,10 +670,7 @@ class _SeedRestoreOptionState extends ConsumerState { widget.lelScanChanged(_enableLelantusScanning); }, ), - if (widget.coin is Firo) - const SizedBox( - height: 8, - ), + if (widget.coin is Firo) const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -697,11 +679,12 @@ class _SeedRestoreOptionState extends ConsumerState { key: const Key("mnemonicPassphraseFieldKey1"), focusNode: widget.pwFocusNode, controller: widget.pwController, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), + style: + Util.isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2) + : STextStyles.field(context), obscureText: _hidePassword, enableSuggestions: false, autocorrect: false, @@ -713,15 +696,11 @@ class _SeedRestoreOptionState extends ConsumerState { suffixIcon: UnconstrainedBox( child: ConditionalParent( condition: Util.isDesktop, - builder: (child) => SizedBox( - height: 70, - child: child, - ), + builder: + (child) => SizedBox(height: 70, child: child), child: Row( children: [ - SizedBox( - width: Util.isDesktop ? 24 : 16, - ), + SizedBox(width: Util.isDesktop ? 24 : 16), GestureDetector( key: const Key( "mnemonicPassphraseFieldShowPasswordButtonKey", @@ -735,16 +714,15 @@ class _SeedRestoreOptionState extends ConsumerState { _hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: Util.isDesktop ? 24 : 16, height: Util.isDesktop ? 24 : 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -752,29 +730,28 @@ class _SeedRestoreOptionState extends ConsumerState { ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Center( child: Text( "If the recovery phrase you are about to restore " "was created with an optional BIP39 passphrase " "you can enter it here.", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ) - : STextStyles.itemSubtitle(context), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ) + : STextStyles.itemSubtitle(context), ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ), ), @@ -791,7 +768,7 @@ class _SeedRestoreOptionState extends ConsumerState { } } -class ViewOnlyRestoreOption extends StatefulWidget { +class ViewOnlyRestoreOption extends ConsumerStatefulWidget { const ViewOnlyRestoreOption({ super.key, required this.coin, @@ -799,22 +776,21 @@ class ViewOnlyRestoreOption extends StatefulWidget { required this.dateChooserFunction, required this.blockHeightController, required this.blockHeightFocusNode, - required this.isUsingDateNotifier, }); final CryptoCurrency coin; final TextEditingController dateController; final TextEditingController blockHeightController; final FocusNode blockHeightFocusNode; - final ValueNotifier isUsingDateNotifier; final Future Function() dateChooserFunction; @override - State createState() => _ViewOnlyRestoreOptionState(); + ConsumerState createState() => + _ViewOnlyRestoreOptionState(); } -class _ViewOnlyRestoreOptionState extends State { +class _ViewOnlyRestoreOptionState extends ConsumerState { bool _blockFieldEmpty = true; @override @@ -827,118 +803,111 @@ class _ViewOnlyRestoreOptionState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - widget.isUsingDateNotifier.value - ? "Choose start date" - : "Block height", - style: Util.isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), + ref.watch(_pIsUsingDate) ? "Choose start date" : "Block height", + style: + Util.isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), CustomTextButton( - text: widget.isUsingDateNotifier.value - ? "Use block height" - : "Use date", + text: + ref.watch(_pIsUsingDate) ? "Use block height" : "Use date", onTap: () { - setState(() { - widget.isUsingDateNotifier.value = - !widget.isUsingDateNotifier.value; - }); + ref.read(_pIsUsingDate.notifier).state = + !ref.read(_pIsUsingDate); }, ), ], ), + if (showDateOption) SizedBox(height: Util.isDesktop ? 16 : 8), if (showDateOption) - SizedBox( - height: Util.isDesktop ? 16 : 8, - ), - if (showDateOption) - widget.isUsingDateNotifier.value + ref.watch(_pIsUsingDate) ? RestoreFromDatePicker( - onTap: widget.dateChooserFunction, - controller: widget.dateController, - ) - : ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - focusNode: widget.blockHeightFocusNode, - controller: widget.blockHeightController, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - textInputAction: TextInputAction.done, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, + onTap: widget.dateChooserFunction, + controller: widget.dateController, ) - : STextStyles.field(context), - onChanged: (value) { - setState(() { - _blockFieldEmpty = value.isEmpty; - }); - }, - decoration: standardInputDecoration( - "Start scanning from...", - widget.blockHeightFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: TextFieldIconButton( - child: Semantics( - label: - "Clear Block Height Field Button. Clears the block height field", - excludeSemantics: true, - child: !_blockFieldEmpty - ? XIcon( - width: Util.isDesktop ? 24 : 16, - height: Util.isDesktop ? 24 : 16, - ) - : const SizedBox.shrink(), + : ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + focusNode: widget.blockHeightFocusNode, + controller: widget.blockHeightController, + keyboardType: TextInputType.number, + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + textInputAction: TextInputAction.done, + style: + Util.isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2) + : STextStyles.field(context), + onChanged: (value) { + setState(() { + _blockFieldEmpty = value.isEmpty; + }); + }, + decoration: standardInputDecoration( + "Start scanning from...", + widget.blockHeightFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: TextFieldIconButton( + child: Semantics( + label: + "Clear Block Height Field Button. Clears the block height field", + excludeSemantics: true, + child: + !_blockFieldEmpty + ? XIcon( + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ) + : const SizedBox.shrink(), + ), + onTap: () { + widget.blockHeightController.text = ""; + setState(() { + _blockFieldEmpty = true; + }); + }, + ), ), - onTap: () { - widget.blockHeightController.text = ""; - setState(() { - _blockFieldEmpty = true; - }); - }, ), ), ), - ), - ), - if (showDateOption) - const SizedBox( - height: 8, - ), + if (showDateOption) const SizedBox(height: 8), if (showDateOption) RoundedWhiteContainer( child: Center( child: Text( - widget.isUsingDateNotifier.value + ref.watch(_pIsUsingDate) ? "Choose the date you made the wallet (approximate is fine)" : "Enter the initial block height of the wallet", - style: Util.isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ) - : STextStyles.smallMed12(context).copyWith( - fontSize: 10, - ), + style: + Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ) + : STextStyles.smallMed12( + context, + ).copyWith(fontSize: 10), ), ), ), - if (showDateOption) - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + if (showDateOption) SizedBox(height: Util.isDesktop ? 24 : 16), ], ); } From 64eea6a236b11499608cb838b1cb0dede33be4d0 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 16:59:50 -0600 Subject: [PATCH 033/206] monero/wownero seed offset option on restore --- .../restore_options_view.dart | 73 ++-- lib/wallets/wallet/impl/monero_wallet.dart | 41 +- lib/wallets/wallet/impl/wownero_wallet.dart | 41 +- .../intermediate/lib_monero_wallet.dart | 382 +++++++++--------- pubspec.lock | 4 +- scripts/app_config/templates/pubspec.template | 2 +- 6 files changed, 275 insertions(+), 268 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index 6d424a2c8..40607b103 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -86,8 +86,6 @@ class _RestoreOptionsViewState extends ConsumerState { DateTime? _restoreFromDate; bool hidePassword = true; - bool get supportsMnemonicPassphrase => coin.hasMnemonicPassphraseSupport; - bool enableLelantusScanning = false; bool get supportsLelantus => coin is Firo; @@ -352,7 +350,6 @@ class _RestoreOptionsViewState extends ConsumerState { blockHeightFocusNode: _blockHeightFocusNode, pwController: passwordController, pwFocusNode: passwordFocusNode, - supportsMnemonicPassphrase: supportsMnemonicPassphrase, dateChooserFunction: isDesktop ? chooseDesktopDate : chooseDate, chooseMnemonicLength: chooseMnemonicLength, @@ -387,7 +384,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { required this.blockHeightFocusNode, required this.pwController, required this.pwFocusNode, - required this.supportsMnemonicPassphrase, required this.dateChooserFunction, required this.chooseMnemonicLength, required this.lelScanChanged, @@ -399,7 +395,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { final FocusNode blockHeightFocusNode; final TextEditingController pwController; final FocusNode pwFocusNode; - final bool supportsMnemonicPassphrase; final Future Function() dateChooserFunction; final Future Function() chooseMnemonicLength; @@ -419,12 +414,21 @@ class _SeedRestoreOptionState extends ConsumerState { Widget build(BuildContext context) { final lengths = widget.coin.possibleMnemonicLengths; - final isMoneroAnd25 = - widget.coin is Monero && - ref.watch(mnemonicWordCountStateProvider.state).state == 25; - final isWowneroAnd25 = - widget.coin is Wownero && - ref.watch(mnemonicWordCountStateProvider.state).state == 25; + final currentLength = ref.watch(mnemonicWordCountStateProvider); + + final isMoneroAnd25 = widget.coin is Monero && currentLength == 25; + final isWowneroAnd25 = widget.coin is Wownero && currentLength == 25; + + final bool supportsPassphrase; + if (widget.coin.hasMnemonicPassphraseSupport) { + supportsPassphrase = true; + } else if (widget.coin is CryptonoteCurrency) { + // partial see offset support. Currently only on restore + // and not wownero 14 word seeds + supportsPassphrase = currentLength == 16 || currentLength == 25; + } else { + supportsPassphrase = false; + } return Column( children: [ @@ -573,14 +577,22 @@ class _SeedRestoreOptionState extends ConsumerState { }, isExpanded: true, iconStyleData: IconStyleData( - icon: SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - height: 6, - color: - Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + icon: ConditionalParent( + condition: Util.isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.only(right: 10), + child: child, + ), + child: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), ), ), dropdownStyleData: DropdownStyleData( @@ -605,9 +617,8 @@ class _SeedRestoreOptionState extends ConsumerState { MobileMnemonicLengthSelector( chooseMnemonicLength: widget.chooseMnemonicLength, ), - if (widget.supportsMnemonicPassphrase) - SizedBox(height: Util.isDesktop ? 24 : 16), - if (widget.supportsMnemonicPassphrase) + if (supportsPassphrase) SizedBox(height: Util.isDesktop ? 24 : 16), + if (supportsPassphrase) Expandable( onExpandChanged: (state) { setState(() { @@ -617,10 +628,11 @@ class _SeedRestoreOptionState extends ConsumerState { header: Container( color: Colors.transparent, child: Padding( - padding: const EdgeInsets.only( + padding: EdgeInsets.only( top: 8.0, bottom: 8.0, right: 10, + left: Util.isDesktop ? 16 : 0, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -689,7 +701,9 @@ class _SeedRestoreOptionState extends ConsumerState { enableSuggestions: false, autocorrect: false, decoration: standardInputDecoration( - "BIP39 passphrase", + widget.coin is CryptonoteCurrency + ? "Seed Offset" + : "BIP39 passphrase", widget.pwFocusNode, context, ).copyWith( @@ -734,9 +748,14 @@ class _SeedRestoreOptionState extends ConsumerState { RoundedWhiteContainer( child: Center( child: Text( - "If the recovery phrase you are about to restore " - "was created with an optional BIP39 passphrase " - "you can enter it here.", + widget.coin is CryptonoteCurrency + ? "(Optional) An offset used to derive a different " + "wallet from the given mnemonic, allowing recovery " + "of a hidden or alternate wallet based on the same " + "seed phrase." + : "If the recovery phrase you are about to restore " + "was created with an optional BIP39 passphrase " + "you can enter it here.", style: Util.isDesktop ? STextStyles.desktopTextExtraSmall( diff --git a/lib/wallets/wallet/impl/monero_wallet.dart b/lib/wallets/wallet/impl/monero_wallet.dart index f1de036aa..a99cf30a3 100644 --- a/lib/wallets/wallet/impl/monero_wallet.dart +++ b/lib/wallets/wallet/impl/monero_wallet.dart @@ -9,18 +9,13 @@ import '../intermediate/lib_monero_wallet.dart'; class MoneroWallet extends LibMoneroWallet { MoneroWallet(CryptoCurrencyNetwork network) - : super( - Monero(network), - lib_monero_compat.WalletType.monero, - ); + : super(Monero(network), lib_monero_compat.WalletType.monero); @override Future estimateFeeFor(Amount amount, int feeRate) async { if (libMoneroWallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) { - return Amount.zeroWith( - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } lib_monero.TransactionPriority priority; @@ -76,6 +71,7 @@ class MoneroWallet extends LibMoneroWallet { required String path, required String password, required int wordCount, + required String seedOffset, }) async { final lib_monero.MoneroSeedType type; switch (wordCount) { @@ -95,6 +91,7 @@ class MoneroWallet extends LibMoneroWallet { path: path, password: password, seedType: type, + seedOffset: seedOffset, ); } @@ -103,14 +100,15 @@ class MoneroWallet extends LibMoneroWallet { required String path, required String password, required String mnemonic, + required String seedOffset, int height = 0, - }) async => - await lib_monero.MoneroWallet.restoreWalletFromSeed( - path: path, - password: password, - seed: mnemonic, - restoreHeight: height, - ); + }) async => await lib_monero.MoneroWallet.restoreWalletFromSeed( + path: path, + password: password, + seed: mnemonic, + restoreHeight: height, + seedOffset: seedOffset, + ); @override Future getRestoredFromViewKeyWallet({ @@ -119,14 +117,13 @@ class MoneroWallet extends LibMoneroWallet { required String address, required String privateViewKey, int height = 0, - }) async => - lib_monero.MoneroWallet.createViewOnlyWallet( - path: path, - password: password, - address: address, - viewKey: privateViewKey, - restoreHeight: height, - ); + }) async => lib_monero.MoneroWallet.createViewOnlyWallet( + path: path, + password: password, + address: address, + viewKey: privateViewKey, + restoreHeight: height, + ); @override void invalidSeedLengthCheck(int length) { diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart index 81407f837..73b1c4f7b 100644 --- a/lib/wallets/wallet/impl/wownero_wallet.dart +++ b/lib/wallets/wallet/impl/wownero_wallet.dart @@ -11,18 +11,13 @@ import '../intermediate/lib_monero_wallet.dart'; class WowneroWallet extends LibMoneroWallet { WowneroWallet(CryptoCurrencyNetwork network) - : super( - Wownero(network), - lib_monero_compat.WalletType.wownero, - ); + : super(Wownero(network), lib_monero_compat.WalletType.wownero); @override Future estimateFeeFor(Amount amount, int feeRate) async { if (libMoneroWallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) { - return Amount.zeroWith( - fractionDigits: cryptoCurrency.fractionDigits, - ); + return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } lib_monero.TransactionPriority priority; @@ -112,6 +107,7 @@ class WowneroWallet extends LibMoneroWallet { required String path, required String password, required int wordCount, + required String seedOffset, }) async { final lib_monero.WowneroSeedType type; switch (wordCount) { @@ -132,6 +128,7 @@ class WowneroWallet extends LibMoneroWallet { password: password, seedType: type, overrideDeprecated14WordSeedException: true, + seedOffset: seedOffset, ); } @@ -140,14 +137,15 @@ class WowneroWallet extends LibMoneroWallet { required String path, required String password, required String mnemonic, + required String seedOffset, int height = 0, - }) async => - await lib_monero.WowneroWallet.restoreWalletFromSeed( - path: path, - password: password, - seed: mnemonic, - restoreHeight: height, - ); + }) async => await lib_monero.WowneroWallet.restoreWalletFromSeed( + path: path, + password: password, + seed: mnemonic, + restoreHeight: height, + seedOffset: seedOffset, + ); @override Future getRestoredFromViewKeyWallet({ @@ -156,14 +154,13 @@ class WowneroWallet extends LibMoneroWallet { required String address, required String privateViewKey, int height = 0, - }) async => - lib_monero.WowneroWallet.createViewOnlyWallet( - path: path, - password: password, - address: address, - viewKey: privateViewKey, - restoreHeight: height, - ); + }) async => lib_monero.WowneroWallet.createViewOnlyWallet( + path: path, + password: password, + address: address, + viewKey: privateViewKey, + restoreHeight: height, + ); @override void invalidSeedLengthCheck(int length) { diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index b6b30de34..55812fe19 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -51,33 +51,33 @@ abstract class LibMoneroWallet final bus = GlobalEventBus.instance; // Listen for tor status changes. - _torStatusListener = bus.on().listen( - (event) async { - switch (event.newStatus) { - case TorConnectionStatus.connecting: - if (!_torConnectingLock.isLocked) { - await _torConnectingLock.acquire(); - } - _requireMutex = true; - break; + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + if (!_torConnectingLock.isLocked) { + await _torConnectingLock.acquire(); + } + _requireMutex = true; + break; - case TorConnectionStatus.connected: - case TorConnectionStatus.disconnected: - if (_torConnectingLock.isLocked) { - _torConnectingLock.release(); - } - _requireMutex = false; - break; - } - }, - ); + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + _requireMutex = false; + break; + } + }); // Listen for tor preference changes. - _torPreferenceListener = bus.on().listen( - (event) async { - await updateNode(); - }, - ); + _torPreferenceListener = bus.on().listen(( + event, + ) async { + await updateNode(); + }); // Potentially dangerous hack. See comments in _startInit() _startInit(); @@ -93,17 +93,13 @@ abstract class LibMoneroWallet .walletIdEqualTo(walletId) .watch(fireImmediately: true) .listen((utxos) async { - try { - await onUTXOsChanged(utxos); - await updateBalance(shouldUpdateUtxos: false); - } catch (e, s) { - lib_monero.Logging.log?.i( - "_startInit", - error: e, - stackTrace: s, - ); - } - }); + try { + await onUTXOsChanged(utxos); + await updateBalance(shouldUpdateUtxos: false); + } catch (e, s) { + lib_monero.Logging.log?.i("_startInit", error: e, stackTrace: s); + } + }); }); } @@ -143,12 +139,14 @@ abstract class LibMoneroWallet required String path, required String password, required int wordCount, + required String seedOffset, }); Future getRestoredWallet({ required String path, required String password, required String mnemonic, + required String seedOffset, int height = 0, }); @@ -179,11 +177,7 @@ abstract class LibMoneroWallet onNewBlock: onNewBlock, onBalancesChanged: onBalancesChanged, onError: (e, s) { - Logging.instance.w( - "$e\n$s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); }, ), ); @@ -197,16 +191,14 @@ abstract class LibMoneroWallet if (libMoneroWallet == null) { wasNull = true; // libMoneroWalletT?.close(); - final path = await pathForWallet( - name: walletId, - type: compatType, - ); + final path = await pathForWallet(name: walletId, type: compatType); final String password; try { - password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), - ))!; + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); } @@ -247,9 +239,7 @@ abstract class LibMoneroWallet } @Deprecated("Only used in the case of older wallets") - lib_monero_compat.WalletInfo? getLibMoneroWalletInfo( - String walletId, - ) { + lib_monero_compat.WalletInfo? getLibMoneroWalletInfo(String walletId) { try { return DB.instance.moneroWalletInfoBox.values.firstWhere( (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), @@ -297,9 +287,7 @@ abstract class LibMoneroWallet Future getKeys() async { final base = libMoneroWallet; - final oldInfo = getLibMoneroWalletInfo( - walletId, - ); + final oldInfo = getLibMoneroWalletInfo(walletId); if (base == null || (oldInfo != null && oldInfo.name != walletId)) { return null; } @@ -324,13 +312,14 @@ abstract class LibMoneroWallet } Future<(String, String)> - hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { + hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { final path = await pathForWallet(name: walletId, type: compatType); final String password; try { - password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), - ))!; + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); } @@ -341,10 +330,7 @@ abstract class LibMoneroWallet @override Future init({bool? isRestore, int? wordCount}) async { - final path = await pathForWallet( - name: walletId, - type: compatType, - ); + final path = await pathForWallet(name: walletId, type: compatType); if (!(walletExists(path)) && isRestore != true) { if (wordCount == null) { throw Exception("Missing word count for new xmr/wow wallet!"); @@ -359,6 +345,7 @@ abstract class LibMoneroWallet path: path, password: password, wordCount: wordCount, + seedOffset: "", // default for non restored wallets for now ); final height = wallet.getRefreshFromBlockHeight(); @@ -410,6 +397,7 @@ abstract class LibMoneroWallet await refreshMutex.protect(() async { final mnemonic = await getMnemonic(); + final seedOffset = await getMnemonicPassphrase(); final seedLength = mnemonic.trim().split(" ").length; invalidSeedLengthCheck(seedLength); @@ -424,10 +412,7 @@ abstract class LibMoneroWallet final String name = walletId; - final path = await pathForWallet( - name: name, - type: compatType, - ); + final path = await pathForWallet(name: name, type: compatType); try { final password = generatePassword(); @@ -440,6 +425,7 @@ abstract class LibMoneroWallet password: password, mnemonic: mnemonic, height: height, + seedOffset: seedOffset, ); if (libMoneroWallet != null) { @@ -450,7 +436,8 @@ abstract class LibMoneroWallet _setListener(); - final newReceivingAddress = await getCurrentReceivingAddress() ?? + final newReceivingAddress = + await getCurrentReceivingAddress() ?? Address( walletId: walletId, derivationIndex: 0, @@ -481,8 +468,11 @@ abstract class LibMoneroWallet libMoneroWallet?.startListeners(); libMoneroWallet?.startAutoSaving(); } catch (e, s) { - Logging.instance.e("Exception rethrown from recoverFromMnemonic(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from recoverFromMnemonic(): ", + error: e, + stackTrace: s, + ); rethrow; } }); @@ -551,8 +541,11 @@ abstract class LibMoneroWallet _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); } catch (e, s) { _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - Logging.instance.e("Exception caught in $runtimeType.updateNode(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception caught in $runtimeType.updateNode(): ", + error: e, + stackTrace: s, + ); } return; @@ -566,13 +559,14 @@ abstract class LibMoneroWallet return; } - final localTxids = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .heightGreaterThan(0) - .txidProperty() - .findAll(); + final localTxids = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .heightGreaterThan(0) + .txidProperty() + .findAll(); final allTxids = await base.getAllTxids(refresh: true); @@ -582,10 +576,7 @@ abstract class LibMoneroWallet return; } - final transactions = await base.getTxs( - txids: txidsToFetch, - refresh: false, - ); + final transactions = await base.getTxs(txids: txidsToFetch, refresh: false); final allOutputs = await base.getOutputs(includeSpent: true, refresh: true); @@ -673,14 +664,16 @@ abstract class LibMoneroWallet type: type, subType: TransactionSubType.none, otherData: jsonEncode({ - TxV2OdKeys.overrideFee: Amount( - rawValue: tx.fee, - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), - TxV2OdKeys.moneroAmount: Amount( - rawValue: tx.amount, - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), + TxV2OdKeys.overrideFee: + Amount( + rawValue: tx.fee, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), + TxV2OdKeys.moneroAmount: + Amount( + rawValue: tx.amount, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), TxV2OdKeys.moneroAccountIndex: tx.accountIndex, TxV2OdKeys.isMoneroTransaction: true, }), @@ -756,9 +749,10 @@ abstract class LibMoneroWallet Future pathForWallet({ required String name, required lib_monero_compat.WalletType type, - }) async => - await pathForWalletDir(name: name, type: type) - .then((path) => '$path/$name'); + }) async => await pathForWalletDir( + name: name, + type: type, + ).then((path) => '$path/$name'); void onSyncingUpdate({ required int syncHeight, @@ -903,16 +897,10 @@ abstract class LibMoneroWallet } GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highest, - walletId, - ), + RefreshPercentChangedEvent(highest, walletId), ); GlobalEventBus.instance.fire( - BlocksRemainingEvent( - blocksLeft, - walletId, - ), + BlocksRemainingEvent(blocksLeft, walletId), ); } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { status = WalletSyncStatus.synced; @@ -922,10 +910,7 @@ abstract class LibMoneroWallet } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { status = WalletSyncStatus.unableToSync; @@ -933,18 +918,12 @@ abstract class LibMoneroWallet } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { status = WalletSyncStatus.syncing; GlobalEventBus.instance.fire( - RefreshPercentChangedEvent( - highestPercentCached, - walletId, - ), + RefreshPercentChangedEvent(highestPercentCached, walletId), ); } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { status = WalletSyncStatus.unableToSync; @@ -953,11 +932,7 @@ abstract class LibMoneroWallet if (status != null) { GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - status, - walletId, - info.coin, - ), + WalletSyncStatusChangedEvent(status, walletId, info.coin), ); } } @@ -1019,24 +994,27 @@ abstract class LibMoneroWallet @override Future updateUTXOs() async { final List outputArray = []; - final utxos = await libMoneroWallet?.getOutputs(refresh: true) ?? + final utxos = + await libMoneroWallet?.getOutputs(refresh: true) ?? []; for (final rawUTXO in utxos) { if (!rawUTXO.spent) { - final current = await mainDB.isar.utxos - .where() - .walletIdEqualTo(walletId) - .filter() - .voutEqualTo(rawUTXO.vout) - .and() - .txidEqualTo(rawUTXO.hash) - .findFirst(); - final tx = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .txidEqualTo(rawUTXO.hash) - .findFirst(); + final current = + await mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .voutEqualTo(rawUTXO.vout) + .and() + .txidEqualTo(rawUTXO.hash) + .findFirst(); + final tx = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(rawUTXO.hash) + .findFirst(); final otherDataMap = { UTXOOtherDataKeys.keyImage: rawUTXO.keyImage, @@ -1161,8 +1139,11 @@ abstract class LibMoneroWallet isar: mainDB.isar, ); } catch (e, s) { - Logging.instance - .e("Exception in generateNewAddress(): ", error: e, stackTrace: s); + Logging.instance.e( + "Exception in generateNewAddress(): ", + error: e, + stackTrace: s, + ); } } @@ -1173,9 +1154,10 @@ abstract class LibMoneroWallet throw Exception(); } catch (_, s) { Logging.instance.e( - "checkReceivingAddressForTransactions called but reuse address flag set: $s", - error: e, - stackTrace: s); + "checkReceivingAddressForTransactions called but reuse address flag set: $s", + error: e, + stackTrace: s, + ); } } @@ -1185,9 +1167,10 @@ abstract class LibMoneroWallet if (entries != null) { for (final element in entries) { if (!element.isSpend) { - final int curAddressIndex = element.addressIndexes.isEmpty - ? 0 - : element.addressIndexes.reduce(max); + final int curAddressIndex = + element.addressIndexes.isEmpty + ? 0 + : element.addressIndexes.reduce(max); if (curAddressIndex > highestIndex) { highestIndex = curAddressIndex; } @@ -1206,11 +1189,12 @@ abstract class LibMoneroWallet // Use new index to derive a new receiving address final newReceivingAddress = addressFor(index: newReceivingIndex); - final existing = await mainDB - .getAddresses(walletId) - .filter() - .valueEqualTo(newReceivingAddress.value) - .findFirst(); + final existing = + await mainDB + .getAddresses(walletId) + .filter() + .valueEqualTo(newReceivingAddress.value) + .findFirst(); if (existing == null) { // Add that new change address await mainDB.putAddress(newReceivingAddress); @@ -1225,15 +1209,17 @@ abstract class LibMoneroWallet } } on SocketException catch (se, s) { Logging.instance.e( - "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s", - error: e, - stackTrace: s); + "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s", + error: e, + stackTrace: s, + ); return; } catch (e, s) { Logging.instance.e( - "Exception rethrown from _checkReceivingAddressForTransactions(): ", - error: e, - stackTrace: s); + "Exception rethrown from _checkReceivingAddressForTransactions(): ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -1241,13 +1227,13 @@ abstract class LibMoneroWallet // TODO: this needs some work. Prio's may need to be changed as well as estimated blocks @override Future get fees async => FeeObject( - numberOfBlocksFast: 10, - numberOfBlocksAverage: 15, - numberOfBlocksSlow: 20, - fast: lib_monero.TransactionPriority.high.value, - medium: lib_monero.TransactionPriority.medium.value, - slow: lib_monero.TransactionPriority.normal.value, - ); + numberOfBlocksFast: 10, + numberOfBlocksAverage: 15, + numberOfBlocksSlow: 20, + fast: lib_monero.TransactionPriority.high.value, + medium: lib_monero.TransactionPriority.medium.value, + slow: lib_monero.TransactionPriority.normal.value, + ); @override Future updateChainHeight() async { @@ -1321,25 +1307,27 @@ abstract class LibMoneroWallet } final height = await chainHeight; - final inputs = txData.utxos - ?.map( - (e) => lib_monero.Output( - address: e.address!, - hash: e.txid, - keyImage: e.keyImage!, - value: BigInt.from(e.value), - isFrozen: e.isBlocked, - isUnlocked: e.blockHeight != null && - (height - (e.blockHeight ?? 0)) >= - cryptoCurrency.minConfirms, - height: e.blockHeight ?? 0, - vout: e.vout, - spent: e.used ?? false, - spentHeight: null, // doesn't matter here - coinbase: e.isCoinbase, - ), - ) - .toList(); + final inputs = + txData.utxos + ?.map( + (e) => lib_monero.Output( + address: e.address!, + hash: e.txid, + keyImage: e.keyImage!, + value: BigInt.from(e.value), + isFrozen: e.isBlocked, + isUnlocked: + e.blockHeight != null && + (height - (e.blockHeight ?? 0)) >= + cryptoCurrency.minConfirms, + height: e.blockHeight ?? 0, + vout: e.vout, + spent: e.used ?? false, + spentHeight: null, // doesn't matter here + coinbase: e.isCoinbase, + ), + ) + .toList(); return await prepareSendMutex.protect(() async { final lib_monero.PendingTransaction pendingTransaction; @@ -1380,8 +1368,11 @@ abstract class LibMoneroWallet throw ArgumentError("Invalid fee rate argument provided!"); } } catch (e, s) { - Logging.instance.i("Exception rethrown from prepare send(): ", - error: e, stackTrace: s); + Logging.instance.i( + "Exception rethrown from prepare send(): ", + error: e, + stackTrace: s, + ); if (e.toString().contains("Incorrect unlocked balance")) { throw Exception("Insufficient balance!"); @@ -1395,9 +1386,7 @@ abstract class LibMoneroWallet Future confirmSend({required TxData txData}) async { try { try { - await libMoneroWallet!.commitTx( - txData.pendingTransaction!, - ); + await libMoneroWallet!.commitTx(txData.pendingTransaction!); Logging.instance.d( "transaction ${txData.pendingTransaction!.txid} has been sent", @@ -1405,14 +1394,18 @@ abstract class LibMoneroWallet return txData.copyWith(txid: txData.pendingTransaction!.txid); } catch (e, s) { Logging.instance.e( - "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", - error: e, - stackTrace: s); + "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", + error: e, + stackTrace: s, + ); rethrow; } } catch (e, s) { - Logging.instance.e("Exception rethrown from confirmSend(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from confirmSend(): ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -1435,10 +1428,7 @@ abstract class LibMoneroWallet final String name = walletId; - final path = await pathForWallet( - name: name, - type: compatType, - ); + final path = await pathForWallet(name: name, type: compatType); final password = generatePassword(); await secureStorageInterface.write( @@ -1461,7 +1451,8 @@ abstract class LibMoneroWallet _setListener(); - final newReceivingAddress = await getCurrentReceivingAddress() ?? + final newReceivingAddress = + await getCurrentReceivingAddress() ?? Address( walletId: walletId, derivationIndex: 0, @@ -1488,8 +1479,11 @@ abstract class LibMoneroWallet libMoneroWallet?.startListeners(); libMoneroWallet?.startAutoSaving(); } catch (e, s) { - Logging.instance.e("Exception rethrown from recoverViewOnly(): ", - error: e, stackTrace: s); + Logging.instance.e( + "Exception rethrown from recoverViewOnly(): ", + error: e, + stackTrace: s, + ); rethrow; } }); diff --git a/pubspec.lock b/pubspec.lock index ffcc7e9a8..9d65621e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -444,10 +444,10 @@ packages: dependency: "direct main" description: name: cs_monero - sha256: ed81d9e74ea71a8b8b0bfed07a284e14b6e5f4d0dbde774735f9f0a9ab60b7fb + sha256: f48495ed6744a47598b36eaf28adc1e9e55f0d4ea3c18fe42eda0d3d8f714206 url: "https://pub.dev" source: hosted - version: "1.0.0-pre.2" + version: "1.0.0-pre.3" cs_monero_flutter_libs: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 9c6c48cb4..86b62194d 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -205,7 +205,7 @@ dependencies: blockchain_utils: ^3.3.0 on_chain: ^4.0.1 cbor: ^6.3.3 - cs_monero: 1.0.0-pre.2 + cs_monero: 1.0.0-pre.3 cs_monero_flutter_libs: 1.0.0-pre.0 monero_rpc: ^2.0.0 digest_auth: ^1.0.1 From e765175d81aa328f050a0046ebc69b41f7b6e8dc Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 18:31:19 -0600 Subject: [PATCH 034/206] parse port hack --- .../add_edit_node_view.dart | 1091 ++++++++--------- 1 file changed, 542 insertions(+), 549 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 0f00f75db..4fdeec183 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -109,111 +109,107 @@ class _AddEditNodeViewState extends ConsumerState { context: context, useSafeArea: true, barrierDismissible: true, - builder: (_) => isDesktop - ? DesktopDialog( - maxWidth: 440, - maxHeight: 300, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 32, - ), - child: Row( + builder: + (_) => + isDesktop + ? DesktopDialog( + maxWidth: 440, + maxHeight: 300, + child: Column( children: [ - const SizedBox( - width: 32, - ), - Text( - "Server currently unreachable", - style: STextStyles.desktopH3(context), - ), - ], - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - top: 16, - bottom: 32, - ), - child: Column( - children: [ - const Spacer(), - Text( - "Would you like to save this node anyways?", - style: STextStyles.desktopTextMedium(context), - ), - const Spacer( - flex: 2, - ), - Row( + Padding( + padding: const EdgeInsets.only(top: 32), + child: Row( children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: - isDesktop ? ButtonHeight.l : null, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(false), - ), - ), - const SizedBox( - width: 16, + const SizedBox(width: 32), + Text( + "Server currently unreachable", + style: STextStyles.desktopH3(context), ), - Expanded( - child: PrimaryButton( - label: "Save", - buttonHeight: - isDesktop ? ButtonHeight.l : null, - onPressed: () => Navigator.of( + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: Column( + children: [ + const Spacer(), + Text( + "Would you like to save this node anyways?", + style: STextStyles.desktopTextMedium( context, - rootNavigator: true, - ).pop(true), + ), ), - ), - ], + const Spacer(flex: 2), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: + isDesktop ? ButtonHeight.l : null, + onPressed: + () => Navigator.of( + context, + rootNavigator: true, + ).pop(false), + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Save", + buttonHeight: + isDesktop ? ButtonHeight.l : null, + onPressed: + () => Navigator.of( + context, + rootNavigator: true, + ).pop(true), + ), + ), + ], + ), + ], + ), ), - ], + ), + ], + ), + ) + : StackDialog( + title: "Server currently unreachable", + message: "Would you like to save this node anyways?", + leftButton: TextButton( + onPressed: () async { + Navigator.of(context).pop(false); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), ), ), + rightButton: TextButton( + onPressed: () async { + Navigator.of(context).pop(true); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text("Save", style: STextStyles.button(context)), + ), ), - ], - ), - ) - : StackDialog( - title: "Server currently unreachable", - message: "Would you like to save this node anyways?", - leftButton: TextButton( - onPressed: () async { - Navigator.of(context).pop(false); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - onPressed: () async { - Navigator.of(context).pop(true); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), - ), - ), - ), ).then((value) { if (value is bool && value) { shouldSave = true; @@ -239,9 +235,11 @@ class _AddEditNodeViewState extends ConsumerState { } } - final torEnabled = formData.netOption == TorPlainNetworkOption.tor || + final torEnabled = + formData.netOption == TorPlainNetworkOption.tor || formData.netOption == TorPlainNetworkOption.both; - final plainEnabled = formData.netOption == TorPlainNetworkOption.clear || + final plainEnabled = + formData.netOption == TorPlainNetworkOption.clear || formData.netOption == TorPlainNetworkOption.both; switch (viewType) { @@ -262,15 +260,14 @@ class _AddEditNodeViewState extends ConsumerState { clearnetEnabled: plainEnabled, ); - await ref.read(nodeServiceChangeNotifierProvider).add( - node, - formData.password, - true, - ); + await ref + .read(nodeServiceChangeNotifierProvider) + .add(node, formData.password, true); await _notifyWalletsOfUpdatedNode(); if (mounted) { - Navigator.of(context) - .popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); } break; case AddEditNodeViewType.edit: @@ -290,23 +287,24 @@ class _AddEditNodeViewState extends ConsumerState { clearnetEnabled: plainEnabled, ); - await ref.read(nodeServiceChangeNotifierProvider).add( - node, - formData.password, - true, - ); + await ref + .read(nodeServiceChangeNotifierProvider) + .add(node, formData.password, true); await _notifyWalletsOfUpdatedNode(); if (mounted) { - Navigator.of(context) - .popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); } break; } } Future _notifyWalletsOfUpdatedNode() async { - final wallets = - ref.read(pWallets).wallets.where((e) => e.info.coin == widget.coin); + final wallets = ref + .read(pWallets) + .wallets + .where((e) => e.info.coin == widget.coin); final prefs = ref.read(prefsChangeNotifierProvider); switch (prefs.syncType) { @@ -356,24 +354,26 @@ class _AddEditNodeViewState extends ConsumerState { try { await _processQrData(qrResult); } catch (e, s) { - Logging.instance.e("Error processing QR code data: ", - error: e, stackTrace: s); + Logging.instance.e( + "Error processing QR code data: ", + error: e, + stackTrace: s, + ); } } } catch (e, s) { - Logging.instance.e("Error opening QR code scanner dialog: ", - error: e, stackTrace: s); + Logging.instance.e( + "Error opening QR code scanner dialog: ", + error: e, + stackTrace: s, + ); } } else { try { final result = await BarcodeScanner.scan(); await _processQrData(result.rawContent); } catch (e, s) { - Logging.instance.e( - "$runtimeType._scanQr()", - error: e, - stackTrace: s, - ); + Logging.instance.e("$runtimeType._scanQr()", error: e, stackTrace: s); } } } finally { @@ -401,16 +401,12 @@ class _AddEditNodeViewState extends ConsumerState { clearnetEnabled: !nodeQrData.host.endsWith(".onion"), loginName: (nodeQrData as LibMoneroNodeQrData?)?.user, ), - (nodeQrData as LibMoneroNodeQrData?)?.password ?? "" + (nodeQrData as LibMoneroNodeQrData?)?.password ?? "", ); }); } } catch (e, s) { - Logging.instance.w( - "$e\n$s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); } } @@ -446,201 +442,202 @@ class _AddEditNodeViewState extends ConsumerState { final NodeModel? node = viewType == AddEditNodeViewType.edit && nodeId != null ? ref.watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodeById(id: nodeId!)), - ) + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodeById(id: nodeId!), + ), + ) : null; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - viewType == AddEditNodeViewType.edit ? "Edit node" : "Add node", - style: STextStyles.navBarTitle(context), - ), - actions: [ - if (viewType == AddEditNodeViewType.add && - coin - is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("qrNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: QrCodeIcon( - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .accentColorDark, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + viewType == AddEditNodeViewType.edit + ? "Edit node" + : "Add node", + style: STextStyles.navBarTitle(context), + ), + actions: [ + if (viewType == AddEditNodeViewType.add && + coin + is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("qrNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: QrCodeIcon( + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + onPressed: _scanQr, + ), ), - onPressed: _scanQr, ), - ), - ), - if (viewType == AddEditNodeViewType.edit && - ref - .watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin)), - ) - .length > - 1) - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("deleteNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: SvgPicture.asset( - Assets.svg.trash, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + if (viewType == AddEditNodeViewType.edit && + ref + .watch( + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodesFor(coin), + ), + ) + .length > + 1) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, ), - onPressed: () async { - Navigator.popUntil( - context, - ModalRoute.withName(widget.routeOnSuccessOrDelete), - ); - - await ref - .read(nodeServiceChangeNotifierProvider) - .delete( - nodeId!, - true, + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("deleteNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.trash, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + width: 20, + height: 20, + ), + onPressed: () async { + Navigator.popUntil( + context, + ModalRoute.withName( + widget.routeOnSuccessOrDelete, + ), ); - }, + + await ref + .read(nodeServiceChangeNotifierProvider) + .delete(nodeId!, true); + }, + ), + ), ), - ), + ], + ), + body: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + bottom: 12, ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - bottom: 12, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight - 8), - child: IntrinsicHeight( - child: child, + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 8, + ), + child: IntrinsicHeight(child: child), + ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox( - height: 8, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ + const SizedBox(height: 8), Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const SizedBox( - width: 8, - ), - const AppBarBackButton( - iconSize: 24, - size: 40, - ), - Text( - "Add new node", - style: STextStyles.desktopH3(context), + Row( + children: [ + const SizedBox(width: 8), + const AppBarBackButton(iconSize: 24, size: 40), + Text( + "Add new node", + style: STextStyles.desktopH3(context), + ), + ], ), + if (coin + is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future + Padding( + padding: const EdgeInsets.only(right: 32), + child: AppBarIconButton( + size: 40, + color: + isDesktop + ? Theme.of(context) + .extension()! + .textFieldDefaultBG + : Theme.of( + context, + ).extension()!.background, + icon: const QrCodeIcon(width: 21, height: 21), + onPressed: _scanQr, + ), + ), ], ), - if (coin - is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future - Padding( - padding: const EdgeInsets.only(right: 32), - child: AppBarIconButton( - size: 40, - color: isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : Theme.of(context) - .extension()! - .background, - icon: const QrCodeIcon( - width: 21, - height: 21, - ), - onPressed: _scanQr, - ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, ), + child: child, + ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - top: 16, - bottom: 32, - ), - child: child, - ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -670,10 +667,7 @@ class _AddEditNodeViewState extends ConsumerState { }, ), if (!isDesktop) const Spacer(), - if (isDesktop) - const SizedBox( - height: 78, - ), + if (isDesktop) const SizedBox(height: 78), Row( children: [ Expanded( @@ -681,42 +675,40 @@ class _AddEditNodeViewState extends ConsumerState { label: "Test connection", enabled: testConnectionEnabled, buttonHeight: isDesktop ? ButtonHeight.l : null, - onPressed: testConnectionEnabled - ? () async { - 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, - ), - ); + onPressed: + testConnectionEnabled + ? () async { + 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, + : null, ), ), - if (isDesktop) - const SizedBox( - width: 16, - ), + if (isDesktop) const SizedBox(width: 16), if (isDesktop) Expanded( child: PrimaryButton( @@ -728,24 +720,19 @@ class _AddEditNodeViewState extends ConsumerState { ), ], ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), if (!isDesktop) TextButton( - style: saveEnabled - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + style: + saveEnabled + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), onPressed: saveEnabled ? attemptSave : null, - child: Text( - "Save", - style: STextStyles.button(context), - ), + child: Text("Save", style: STextStyles.button(context)), ), ], ), @@ -965,24 +952,25 @@ class _NodeFormState extends ConsumerState { _nameFocusNode, context, ).copyWith( - suffixIcon: !shouldBeReadOnly && _nameController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - _nameController.text = ""; - _updateState(); - }, - ), - ], + suffixIcon: + !shouldBeReadOnly && _nameController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + _nameController.text = ""; + _updateState(); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), onChanged: (newValue) { _updateState(); @@ -990,9 +978,7 @@ class _NodeFormState extends ConsumerState { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1011,26 +997,59 @@ class _NodeFormState extends ConsumerState { _hostFocusNode, context, ).copyWith( - suffixIcon: !shouldBeReadOnly && _hostController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - _hostController.text = ""; - _updateState(); - }, - ), - ], + suffixIcon: + !shouldBeReadOnly && _hostController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + _hostController.text = ""; + _updateState(); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), onChanged: (newValue) { + // parse port hack + try { + final uri = Uri.parse(newValue); + final port = uri.hasPort ? uri.port : 0; + if (port != 0) { + _portController.text = port.toString(); + final noPortUri = Uri( + scheme: uri.scheme, + userInfo: uri.userInfo, + host: uri.host, + path: uri.path, + query: uri.hasQuery ? uri.query : null, + fragment: uri.fragment.isNotEmpty ? uri.fragment : null, + ); + _hostController.text = noPortUri.toString(); + } + } catch (_) { + if (newValue.contains(":")) { + final parts = newValue.split(":"); + if (parts.isNotEmpty) { + final maybePort = int.tryParse(parts.last); + if (maybePort != null) { + _portController.text = maybePort.toString(); + _hostController.text = newValue.substring( + 0, + newValue.lastIndexOf(":"), + ); + } + } + } + } + if (widget.coin is Epiccash) { if (newValue.startsWith("https://")) { _useSSL = true; @@ -1055,9 +1074,7 @@ class _NodeFormState extends ConsumerState { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1078,24 +1095,25 @@ class _NodeFormState extends ConsumerState { _portFocusNode, context, ).copyWith( - suffixIcon: !shouldBeReadOnly && _portController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - _portController.text = ""; - _updateState(); - }, - ), - ], + suffixIcon: + !shouldBeReadOnly && _portController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + _portController.text = ""; + _updateState(); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), onChanged: (newValue) { _updateState(); @@ -1103,9 +1121,7 @@ class _NodeFormState extends ConsumerState { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (enableAuthFields) ClipRRect( borderRadius: BorderRadius.circular( @@ -1127,21 +1143,21 @@ class _NodeFormState extends ConsumerState { suffixIcon: !shouldBeReadOnly && _usernameController.text.isNotEmpty ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - _usernameController.text = ""; - _updateState(); - }, - ), - ], - ), + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + _usernameController.text = ""; + _updateState(); + }, + ), + ], ), - ) + ), + ) : null, ), onChanged: (newValue) { @@ -1150,10 +1166,7 @@ class _NodeFormState extends ConsumerState { }, ), ), - if (enableAuthFields) - const SizedBox( - height: 8, - ), + if (enableAuthFields) const SizedBox(height: 8), if (enableAuthFields) ClipRRect( borderRadius: BorderRadius.circular( @@ -1176,21 +1189,21 @@ class _NodeFormState extends ConsumerState { suffixIcon: !shouldBeReadOnly && _passwordController.text.isNotEmpty ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - _passwordController.text = ""; - _updateState(); - }, - ), - ], - ), + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + _passwordController.text = ""; + _updateState(); + }, + ), + ], ), - ) + ), + ) : null, ), onChanged: (newValue) { @@ -1199,22 +1212,20 @@ class _NodeFormState extends ConsumerState { }, ), ), - if (enableAuthFields) - const SizedBox( - height: 8, - ), + if (enableAuthFields) const SizedBox(height: 8), if (widget.coin is! CryptonoteCurrency) Row( children: [ GestureDetector( - onTap: !shouldBeReadOnly && enableSSLCheckbox - ? () { - setState(() { - _useSSL = !_useSSL; - }); - _updateState(); - } - : null, + onTap: + !shouldBeReadOnly && enableSSLCheckbox + ? () { + setState(() { + _useSSL = !_useSSL; + }); + _updateState(); + } + : null, child: Container( color: Colors.transparent, child: Row( @@ -1223,29 +1234,29 @@ class _NodeFormState extends ConsumerState { width: 20, height: 20, child: Checkbox( - fillColor: !shouldBeReadOnly && enableSSLCheckbox - ? null - : MaterialStateProperty.all( - Theme.of(context) - .extension()! - .checkboxBGDisabled, - ), + fillColor: + !shouldBeReadOnly && enableSSLCheckbox + ? null + : MaterialStateProperty.all( + Theme.of(context) + .extension()! + .checkboxBGDisabled, + ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: _useSSL, - onChanged: !shouldBeReadOnly && enableSSLCheckbox - ? (newValue) { - setState(() { - _useSSL = newValue!; - }); - _updateState(); - } - : null, + onChanged: + !shouldBeReadOnly && enableSSLCheckbox + ? (newValue) { + setState(() { + _useSSL = newValue!; + }); + _updateState(); + } + : null, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( "Use SSL", style: STextStyles.itemSubtitle12(context), @@ -1260,14 +1271,15 @@ class _NodeFormState extends ConsumerState { Row( children: [ GestureDetector( - onTap: !widget.readOnly /*&& trustedCheckbox*/ - ? () { - setState(() { - _trusted = !_trusted; - }); - _updateState(); - } - : null, + onTap: + !widget.readOnly /*&& trustedCheckbox*/ + ? () { + setState(() { + _trusted = !_trusted; + }); + _updateState(); + } + : null, child: Container( color: Colors.transparent, child: Row( @@ -1276,29 +1288,29 @@ class _NodeFormState extends ConsumerState { width: 20, height: 20, child: Checkbox( - fillColor: !widget.readOnly - ? null - : MaterialStateProperty.all( - Theme.of(context) - .extension()! - .checkboxBGDisabled, - ), + fillColor: + !widget.readOnly + ? null + : MaterialStateProperty.all( + Theme.of(context) + .extension()! + .checkboxBGDisabled, + ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: _trusted, - onChanged: !widget.readOnly - ? (newValue) { - setState(() { - _trusted = newValue!; - }); - _updateState(); - } - : null, + onChanged: + !widget.readOnly + ? (newValue) { + setState(() { + _trusted = newValue!; + }); + _updateState(); + } + : null, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( "Trusted", style: STextStyles.itemSubtitle12(context), @@ -1310,9 +1322,7 @@ class _NodeFormState extends ConsumerState { ], ), if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash) Row( children: [ @@ -1322,7 +1332,9 @@ class _NodeFormState extends ConsumerState { _isFailover = !_isFailover; }); if (widget.readOnly) { - ref.read(nodeServiceChangeNotifierProvider).edit( + ref + .read(nodeServiceChangeNotifierProvider) + .edit( widget.node!.copyWith( isFailover: _isFailover, loginName: widget.node!.loginName, @@ -1351,7 +1363,9 @@ class _NodeFormState extends ConsumerState { _isFailover = newValue!; }); if (widget.readOnly) { - ref.read(nodeServiceChangeNotifierProvider).edit( + ref + .read(nodeServiceChangeNotifierProvider) + .edit( widget.node!.copyWith( isFailover: _isFailover, loginName: widget.node!.loginName, @@ -1366,9 +1380,7 @@ class _NodeFormState extends ConsumerState { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( "Use as failover", style: STextStyles.itemSubtitle12(context), @@ -1379,10 +1391,7 @@ class _NodeFormState extends ConsumerState { ), ], ), - if (widget.coin is! Ethereum) - const SizedBox( - height: 16, - ), + if (widget.coin is! Ethereum) const SizedBox(height: 16), if (widget.coin is! Ethereum) Row( children: [ @@ -1393,19 +1402,14 @@ class _NodeFormState extends ConsumerState { groupValue: netOption, onChanged: (value) { if (!widget.readOnly) { - setState( - () => netOption = TorPlainNetworkOption.tor, - ); + setState(() => netOption = TorPlainNetworkOption.tor); _updateState(); } }, ), ], ), - if (widget.coin is! Ethereum) - const SizedBox( - height: 8, - ), + if (widget.coin is! Ethereum) const SizedBox(height: 8), if (widget.coin is! Ethereum) Row( children: [ @@ -1416,19 +1420,14 @@ class _NodeFormState extends ConsumerState { groupValue: netOption, onChanged: (value) { if (!widget.readOnly) { - setState( - () => netOption = TorPlainNetworkOption.clear, - ); + setState(() => netOption = TorPlainNetworkOption.clear); _updateState(); } }, ), ], ), - if (widget.coin is! Ethereum) - const SizedBox( - height: 8, - ), + if (widget.coin is! Ethereum) const SizedBox(height: 8), if (widget.coin is! Ethereum) Row( children: [ @@ -1439,9 +1438,7 @@ class _NodeFormState extends ConsumerState { groupValue: netOption, onChanged: (value) { if (!widget.readOnly) { - setState( - () => netOption = TorPlainNetworkOption.both, - ); + setState(() => netOption = TorPlainNetworkOption.both); _updateState(); } }, @@ -1473,10 +1470,9 @@ class RadioTextButton extends StatelessWidget { Widget build(BuildContext context) { return ConditionalParent( condition: Util.isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: () { if (value != groupValue) { @@ -1493,27 +1489,24 @@ class RadioTextButton extends StatelessWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, value: value, groupValue: groupValue, - onChanged: !enabled - ? null - : (_) { - if (value != groupValue) { - onChanged.call(value); - } - }, + onChanged: + !enabled + ? null + : (_) { + if (value != groupValue) { + onChanged.call(value); + } + }, ), ), - const SizedBox( - width: 14, - ), - Text( - label, - style: STextStyles.w500_14(context), - ), + const SizedBox(width: 14), + Text(label, style: STextStyles.w500_14(context)), ], ), ), From 50ff74ee5303620ddd53f1835549160fe558ce0f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Apr 2025 18:37:26 -0600 Subject: [PATCH 035/206] add option to node model --- lib/models/node_model.dart | 6 ++++++ lib/models/type_adaptors/node_model.g.dart | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/models/node_model.dart b/lib/models/node_model.dart index 1a27d1345..530c2a0c2 100644 --- a/lib/models/node_model.dart +++ b/lib/models/node_model.dart @@ -43,6 +43,8 @@ class NodeModel { final bool torEnabled; // @HiveField(12) final bool clearnetEnabled; + // @HiveField(13) + final bool forceNoTor; NodeModel({ required this.host, @@ -56,6 +58,7 @@ class NodeModel { required this.isDown, required this.torEnabled, required this.clearnetEnabled, + this.forceNoTor = false, this.loginName, this.trusted, }); @@ -72,6 +75,7 @@ class NodeModel { bool? isDown, required bool? trusted, bool? torEnabled, + bool? forceNoTor, bool? clearnetEnabled, }) { return NodeModel( @@ -88,6 +92,7 @@ class NodeModel { trusted: trusted, torEnabled: torEnabled ?? this.torEnabled, clearnetEnabled: clearnetEnabled ?? this.clearnetEnabled, + forceNoTor: forceNoTor ?? this.forceNoTor, ); } @@ -111,6 +116,7 @@ class NodeModel { map['trusted'] = trusted; map['torEnabled'] = torEnabled; map['clearEnabled'] = clearnetEnabled; + map['forceNoTor'] = forceNoTor; return map; } diff --git a/lib/models/type_adaptors/node_model.g.dart b/lib/models/type_adaptors/node_model.g.dart index 32490fd50..381091edd 100644 --- a/lib/models/type_adaptors/node_model.g.dart +++ b/lib/models/type_adaptors/node_model.g.dart @@ -30,13 +30,14 @@ class NodeModelAdapter extends TypeAdapter { trusted: fields[10] as bool?, torEnabled: fields[11] as bool? ?? true, clearnetEnabled: fields[12] as bool? ?? true, + forceNoTor: fields[13] as bool? ?? false, ); } @override void write(BinaryWriter writer, NodeModel obj) { writer - ..writeByte(13) + ..writeByte(14) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -62,7 +63,9 @@ class NodeModelAdapter extends TypeAdapter { ..writeByte(11) ..write(obj.torEnabled) ..writeByte(12) - ..write(obj.clearnetEnabled); + ..write(obj.clearnetEnabled) + ..writeByte(13) + ..write(obj.forceNoTor); } @override From 9e73ce24734d9288571be45835d5630c7e5a46b6 Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 26 Apr 2025 15:14:44 -0600 Subject: [PATCH 036/206] Use changenow v2 api only and update swap to be able to use coin+network rather than just coin ticker. A couple other bug fixes. And special shoutout to the autoformat of the flutter/dart android studio plugin for making a mess of this commit --- lib/models/exchange/aggregate_currency.dart | 5 +- .../change_now/cn_exchange_transaction.dart | 174 +++ .../cn_exchange_transaction_status.dart | 172 +++ .../change_now/estimated_exchange_amount.dart | 188 +-- .../change_now/exchange_transaction.dart | 20 +- .../exchange_transaction_status.dart | 63 +- lib/models/exchange/incomplete_exchange.dart | 7 +- .../exchange/response_objects/trade.dart | 44 +- .../sub_widgets/add_token_list_element.dart | 123 +- .../sub_widgets/coin_select_item.dart | 99 +- .../exchange_currency_selection_view.dart | 277 ++--- lib/pages/exchange_view/exchange_form.dart | 493 ++++---- .../exchange_step_views/step_3_view.dart | 119 +- .../exchange_provider_options.dart | 50 +- .../exchange_view/trade_details_view.dart | 1099 ++++++++--------- .../helpers/restore_create_backup.dart | 382 +++--- .../desktop_all_trades_view.dart | 409 +++--- .../exchange_steps/step_scaffold.dart | 180 ++- .../subwidgets/desktop_step_2.dart | 421 +++---- .../exchange/change_now/change_now_api.dart | 1017 ++++----------- .../change_now/change_now_exchange.dart | 227 ++-- lib/services/exchange/exchange.dart | 35 +- .../majestic_bank/majestic_bank_api.dart | 65 +- .../majestic_bank/majestic_bank_exchange.dart | 112 +- .../exchange/nanswap/nanswap_exchange.dart | 190 ++- .../simpleswap/simpleswap_exchange.dart | 72 +- .../response_objects/trocador_trade.dart | 55 +- .../exchange/trocador/trocador_exchange.dart | 206 +-- lib/services/trade_service.dart | 7 +- lib/utilities/assets.dart | 8 +- lib/widgets/trade_card.dart | 23 +- .../wallet_info_row_coin_icon.dart | 40 +- .../exchange/exchange_view_test.mocks.dart | 439 ++----- test/services/change_now/change_now_test.dart | 1005 +++++++-------- 34 files changed, 3555 insertions(+), 4271 deletions(-) create mode 100644 lib/models/exchange/change_now/cn_exchange_transaction.dart create mode 100644 lib/models/exchange/change_now/cn_exchange_transaction_status.dart diff --git a/lib/models/exchange/aggregate_currency.dart b/lib/models/exchange/aggregate_currency.dart index 841262c1d..ffaccd3c0 100644 --- a/lib/models/exchange/aggregate_currency.dart +++ b/lib/models/exchange/aggregate_currency.dart @@ -8,9 +8,10 @@ * */ +import 'package:tuple/tuple.dart'; + import '../isar/exchange_cache/currency.dart'; import '../isar/exchange_cache/pair.dart'; -import 'package:tuple/tuple.dart'; class AggregateCurrency { final Map _map = {}; @@ -29,6 +30,8 @@ class AggregateCurrency { return _map[exchangeName]; } + String? networkFor(String exchangeName) => forExchange(exchangeName)?.network; + String get ticker => _map.values.first!.ticker; String get name => _map.values.first!.name; diff --git a/lib/models/exchange/change_now/cn_exchange_transaction.dart b/lib/models/exchange/change_now/cn_exchange_transaction.dart new file mode 100644 index 000000000..5063df995 --- /dev/null +++ b/lib/models/exchange/change_now/cn_exchange_transaction.dart @@ -0,0 +1,174 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2025 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2025-04-26 + * + */ + +import 'package:decimal/decimal.dart'; +import 'package:uuid/uuid.dart'; + +import 'cn_exchange_transaction_status.dart'; + +class CNExchangeTransaction { + /// The amount being sent from the user. + final Decimal fromAmount; + + /// The amount the user will receive. + final Decimal toAmount; + + /// The type of exchange flow. Either "standard" or "fixed-rate". + final String flow; + + /// Direction of the exchange: "direct" or "reverse". + final String type; + + /// The address to which the user sends the input currency. + final String payinAddress; + + /// The address where the exchanged currency will be sent. + final String payoutAddress; + + /// Extra ID for payout address (e.g., memo, tag). Empty string if not used. + final String payoutExtraId; + + /// Currency ticker being exchanged from (e.g., "btc"). + final String fromCurrency; + + /// Currency ticker being exchanged to (e.g., "xmr"). + final String toCurrency; + + /// Refund address in case of failure or timeout. + final String refundAddress; + + /// Extra ID for the refund address (if needed). Empty string if not used. + final String refundExtraId; + + /// Deadline until which the estimated rate or transaction is valid. + final DateTime validUntil; + + /// Date when transaction was created. + final DateTime date; + + /// Unique transaction identifier. + final String id; + + /// The user-defined or system-determined amount in a "directed" flow. + final Decimal? directedAmount; + + /// Network of the currency being sent. + final String fromNetwork; + + /// Network of the currency being received. + final String toNetwork; + + final String uuid; + + final CNExchangeTransactionStatus? statusObject; + + const CNExchangeTransaction({ + required this.fromAmount, + required this.toAmount, + required this.flow, + required this.type, + required this.payinAddress, + required this.payoutAddress, + required this.payoutExtraId, + required this.fromCurrency, + required this.toCurrency, + required this.refundAddress, + required this.refundExtraId, + required this.validUntil, + required this.date, + required this.id, + required this.directedAmount, + required this.fromNetwork, + required this.toNetwork, + required this.uuid, + this.statusObject, + }); + + factory CNExchangeTransaction.fromJson(Map json) { + return CNExchangeTransaction( + fromAmount: Decimal.parse(json["fromAmount"].toString()), + toAmount: Decimal.parse(json["toAmount"].toString()), + flow: json["flow"] as String, + type: json["type"] as String, + payinAddress: json["payinAddress"] as String, + payoutAddress: json["payoutAddress"] as String, + payoutExtraId: json["payoutExtraId"] as String? ?? "", + fromCurrency: json["fromCurrency"] as String, + toCurrency: json["toCurrency"] as String, + refundAddress: json["refundAddress"] as String, + refundExtraId: json["refundExtraId"] as String, + validUntil: DateTime.parse(json["validUntil"] as String), + date: DateTime.parse(json["date"] as String), + id: json["id"] as String, + directedAmount: Decimal.tryParse(json["directedAmount"].toString()), + fromNetwork: json["fromNetwork"] as String? ?? "", + toNetwork: json["toNetwork"] as String? ?? "", + uuid: json["uuid"] as String? ?? const Uuid().v1(), + statusObject: + json["statusObject"] is Map + ? CNExchangeTransactionStatus.fromMap( + json["statusObject"] as Map, + ) + : null, + ); + } + + Map toMap() { + return { + "fromAmount": fromAmount, + "toAmount": toAmount, + "flow": flow, + "type": type, + "payinAddress": payinAddress, + "payoutAddress": payoutAddress, + "payoutExtraId": payoutExtraId, + "fromCurrency": fromCurrency, + "toCurrency": toCurrency, + "refundAddress": refundAddress, + "refundExtraId": refundExtraId, + "validUntil": validUntil.toIso8601String(), + "date": date.toIso8601String(), + "id": id, + "directedAmount": directedAmount, + "fromNetwork": fromNetwork, + "uuid": uuid, + "statusObject": statusObject?.toMap(), + }; + } + + CNExchangeTransaction copyWithStatus(CNExchangeTransactionStatus? status) { + return CNExchangeTransaction( + fromAmount: fromAmount, + toAmount: toAmount, + flow: flow, + type: type, + payinAddress: payinAddress, + payoutAddress: payoutAddress, + payoutExtraId: payoutExtraId, + fromCurrency: fromCurrency, + toCurrency: toCurrency, + refundAddress: refundAddress, + refundExtraId: refundExtraId, + validUntil: validUntil, + date: date, + id: id, + directedAmount: directedAmount, + fromNetwork: fromNetwork, + toNetwork: toNetwork, + uuid: uuid, + statusObject: status, + ); + } + + @override + String toString() { + return "CNExchangeTransaction: ${toMap()}"; + } +} diff --git a/lib/models/exchange/change_now/cn_exchange_transaction_status.dart b/lib/models/exchange/change_now/cn_exchange_transaction_status.dart new file mode 100644 index 000000000..14d7c03e5 --- /dev/null +++ b/lib/models/exchange/change_now/cn_exchange_transaction_status.dart @@ -0,0 +1,172 @@ +import 'package:decimal/decimal.dart'; + +enum ChangeNowTransactionStatus { + New, + Waiting, + Confirming, + Exchanging, + Sending, + Finished, + Failed, + Refunded, + Verifying, +} + +extension ChangeNowTransactionStatusExt on ChangeNowTransactionStatus { + String get lowerCaseName => name.toLowerCase(); +} + +ChangeNowTransactionStatus changeNowTransactionStatusFromStringIgnoreCase( + String string, +) { + for (final value in ChangeNowTransactionStatus.values) { + if (value.lowerCaseName == string.toLowerCase()) { + return value; + } + } + throw ArgumentError( + "String value does not match any known ChangeNowTransactionStatus", + ); +} + +class CNExchangeTransactionStatus { + final String id; + final ChangeNowTransactionStatus status; + final bool actionsAvailable; + final String fromCurrency; + final String fromNetwork; + final String toCurrency; + final String toNetwork; + final String? expectedAmountFrom; + final String? expectedAmountTo; + final String? amountFrom; + final String? amountTo; + final String payinAddress; + final String payoutAddress; + final String? payinExtraId; + final String? payoutExtraId; + final String? refundAddress; + final String? refundExtraId; + final String createdAt; + final String updatedAt; + final String? depositReceivedAt; + final String? payinHash; + final String? payoutHash; + final String fromLegacyTicker; + final String toLegacyTicker; + final String? refundHash; + final String? refundAmount; + final int? userId; + final String? validUntil; + + const CNExchangeTransactionStatus({ + required this.id, + required this.status, + required this.actionsAvailable, + required this.fromCurrency, + required this.fromNetwork, + required this.toCurrency, + required this.toNetwork, + this.expectedAmountFrom, + this.expectedAmountTo, + this.amountFrom, + this.amountTo, + required this.payinAddress, + required this.payoutAddress, + this.payinExtraId, + this.payoutExtraId, + this.refundAddress, + this.refundExtraId, + required this.createdAt, + required this.updatedAt, + this.depositReceivedAt, + this.payinHash, + this.payoutHash, + required this.fromLegacyTicker, + required this.toLegacyTicker, + this.refundHash, + this.refundAmount, + this.userId, + this.validUntil, + }); + + factory CNExchangeTransactionStatus.fromMap(Map map) { + return CNExchangeTransactionStatus( + id: map["id"] as String, + status: changeNowTransactionStatusFromStringIgnoreCase( + map["status"] as String, + ), + actionsAvailable: map["actionsAvailable"] as bool, + fromCurrency: map["fromCurrency"] as String? ?? "", + fromNetwork: map["fromNetwork"] as String? ?? "", + toCurrency: map["toCurrency"] as String? ?? "", + toNetwork: map["toNetwork"] as String? ?? "", + expectedAmountFrom: _get(map["expectedAmountFrom"]), + expectedAmountTo: _get(map["expectedAmountTo"]), + amountFrom: _get(map["amountFrom"]), + amountTo: _get(map["amountTo"]), + payinAddress: map["payinAddress"] as String? ?? "", + payoutAddress: map["payoutAddress"] as String? ?? "", + payinExtraId: map["payinExtraId"] as String?, + payoutExtraId: map["payoutExtraId"] as String?, + refundAddress: map["refundAddress"] as String?, + refundExtraId: map["refundExtraId"] as String?, + createdAt: map["createdAt"] as String? ?? "", + updatedAt: map["updatedAt"] as String? ?? "", + depositReceivedAt: map["depositReceivedAt"] as String?, + payinHash: map["payinHash"] as String?, + payoutHash: map["payoutHash"] as String?, + fromLegacyTicker: map["fromLegacyTicker"] as String? ?? "", + toLegacyTicker: map["toLegacyTicker"] as String? ?? "", + refundHash: map["refundHash"] as String?, + refundAmount: _get(map["refundAmount"]), + userId: + map["userId"] is int + ? map["userId"] as int + : int.tryParse(map["userId"].toString()), + validUntil: map["validUntil"] as String?, + ); + } + + Map toMap() { + return { + "id": id, + "status": status, + "actionsAvailable": actionsAvailable, + "fromCurrency": fromCurrency, + "fromNetwork": fromNetwork, + "toCurrency": toCurrency, + "toNetwork": toNetwork, + "expectedAmountFrom": expectedAmountFrom, + "expectedAmountTo": expectedAmountTo, + "amountFrom": amountFrom, + "amountTo": amountTo, + "payinAddress": payinAddress, + "payoutAddress": payoutAddress, + "payinExtraId": payinExtraId, + "payoutExtraId": payoutExtraId, + "refundAddress": refundAddress, + "refundExtraId": refundExtraId, + "createdAt": createdAt, + "updatedAt": updatedAt, + "depositReceivedAt": depositReceivedAt, + "payinHash": payinHash, + "payoutHash": payoutHash, + "fromLegacyTicker": fromLegacyTicker, + "toLegacyTicker": toLegacyTicker, + "refundHash": refundHash, + "refundAmount": refundAmount, + "userId": userId, + "validUntil": validUntil, + }; + } + + static String? _get(dynamic value) { + if (value is String) return value; + if (value is num) return Decimal.tryParse(value.toString())?.toString(); + return null; + } + + @override + String toString() => "CNExchangeTransactionStatus: ${toMap()}"; +} diff --git a/lib/models/exchange/change_now/estimated_exchange_amount.dart b/lib/models/exchange/change_now/estimated_exchange_amount.dart index 62eee2f60..7648cdacb 100644 --- a/lib/models/exchange/change_now/estimated_exchange_amount.dart +++ b/lib/models/exchange/change_now/estimated_exchange_amount.dart @@ -1,96 +1,142 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ +import "package:decimal/decimal.dart"; -import 'package:decimal/decimal.dart'; - -import '../../../utilities/logger.dart'; +import "../../../services/exchange/change_now/change_now_api.dart"; +/// Immutable model representing exchange rate information. class EstimatedExchangeAmount { - /// Estimated exchange amount - final Decimal estimatedAmount; + /// Ticker of the currency you want to exchange. + final String fromCurrency; - /// Dash-separated min and max estimated time in minutes - final String transactionSpeedForecast; + /// Network of the currency you want to exchange. + final String fromNetwork; - /// Some warnings like warnings that transactions on this network - /// take longer or that the currency has moved to another network - final String? warningMessage; + /// Ticker of the currency you want to receive. + final String toCurrency; + + /// Network of the currency you want to receive. + final String toNetwork; - /// (Optional) Use rateId for fixed-rate flow. If this field is true, you - /// could use returned field "rateId" in next method for creating transaction - /// to freeze estimated amount that you got in this method. Current estimated - /// amount would be valid until time in field "validUntil" + /// Type of exchange flow. Either `standard` or `fixed-rate`. + final CNFlow flow; + + /// Direction of exchange flow. Either `direct` or `reverse`. + /// + /// - `direct`: set amount for `fromCurrency`, get amount of `toCurrency`. + /// - `reverse`: set amount for `toCurrency`, get amount of `fromCurrency`. + final CNExchangeType type; + + /// RateId is needed for fixed-rate flow. Used to freeze estimated amount. final String? rateId; - /// ONLY for fixed rate. - /// Network fee for transferring funds between wallets, it should be deducted - /// from the result. Formula for calculating the estimated amount is given below - /// estimatedAmount = (rate * amount) - networkFee - final Decimal? networkFee; + /// Date and time before which the estimated amount is valid if using `rateId`. + final DateTime validUntil; + + /// Dash-separated min and max estimated time in minutes. + final String? transactionSpeedForecast; + + /// Some warnings, such as if a currency has moved to another network or transactions take longer. + final String? warningMessage; + + /// Deposit fee in the selected currency. + final Decimal depositFee; + + /// Withdrawal fee in the selected currency. + final Decimal withdrawalFee; + + /// A personal and permanent identifier under which information is stored in the database. + /// + /// Only enabled for special partners. + final String? userId; + + /// Exchange amount of `fromCurrency`. + /// + /// If `type=reverse`, this is an estimated value. + final Decimal fromAmount; - EstimatedExchangeAmount({ - required this.estimatedAmount, - required this.transactionSpeedForecast, - required this.warningMessage, + /// Exchange amount of `toCurrency`. + /// + /// If `type=direct`, this is an estimated value. + final Decimal toAmount; + + /// Creates an immutable [EstimatedExchangeAmount] instance. + const EstimatedExchangeAmount({ + required this.fromCurrency, + required this.fromNetwork, + required this.toCurrency, + required this.toNetwork, + required this.flow, + required this.type, required this.rateId, - this.networkFee, + required this.validUntil, + this.transactionSpeedForecast, + this.warningMessage, + required this.depositFee, + required this.withdrawalFee, + this.userId, + required this.fromAmount, + required this.toAmount, }); + /// Creates an instance of [EstimatedExchangeAmount] from a JSON map. factory EstimatedExchangeAmount.fromJson(Map json) { - try { - return EstimatedExchangeAmount( - estimatedAmount: Decimal.parse( - json["estimatedAmount"]?.toString() ?? - json["estimatedDeposit"].toString(), - ), - transactionSpeedForecast: - json["transactionSpeedForecast"] as String? ?? "", - warningMessage: json["warningMessage"] as String?, - rateId: json["rateId"] as String?, - networkFee: Decimal.tryParse(json["networkFee"].toString()), - ); - } catch (e, s) { - Logging.instance.e( - "Failed to parse: $json", - error: e, - stackTrace: s, - ); - rethrow; - } + return EstimatedExchangeAmount( + fromCurrency: json["fromCurrency"] as String, + fromNetwork: json["fromNetwork"] as String, + toCurrency: json["toCurrency"] as String, + toNetwork: json["toNetwork"] as String, + flow: _parseFlow(json["flow"] as String), + type: _parseType(json["type"] as String), + rateId: json["rateId"] as String?, + validUntil: DateTime.parse(json["validUntil"] as String), + transactionSpeedForecast: json["transactionSpeedForecast"] as String?, + warningMessage: json["warningMessage"] as String?, + depositFee: Decimal.parse(json["depositFee"].toString()), + withdrawalFee: Decimal.parse(json["withdrawalFee"].toString()), + userId: json["userId"]?.toString(), + fromAmount: Decimal.parse(json["fromAmount"].toString()), + toAmount: Decimal.parse(json["toAmount"].toString()), + ); } + /// Converts this [EstimatedExchangeAmount] instance to a JSON map. Map toJson() { return { - "estimatedAmount": estimatedAmount, + "fromCurrency": fromCurrency, + "fromNetwork": fromNetwork, + "toCurrency": toCurrency, + "toNetwork": toNetwork, + "flow": flow.name.replaceAll("fixedRate", "fixed-rate"), + "type": type.name, + "rateId": rateId, + "validUntil": validUntil.toIso8601String(), "transactionSpeedForecast": transactionSpeedForecast, "warningMessage": warningMessage, - "rateId": rateId, - "networkFee": networkFee, + "depositFee": depositFee.toString(), + "withdrawalFee": withdrawalFee.toString(), + "userId": userId, + "fromAmount": fromAmount.toString(), + "toAmount": toAmount.toString(), }; } - EstimatedExchangeAmount copyWith({ - Decimal? estimatedAmount, - String? transactionSpeedForecast, - String? warningMessage, - String? rateId, - Decimal? networkFee, - }) { - return EstimatedExchangeAmount( - estimatedAmount: estimatedAmount ?? this.estimatedAmount, - transactionSpeedForecast: - transactionSpeedForecast ?? this.transactionSpeedForecast, - warningMessage: warningMessage ?? this.warningMessage, - rateId: rateId ?? this.rateId, - networkFee: networkFee ?? this.networkFee, - ); + static CNFlow _parseFlow(String value) { + switch (value) { + case "fixed-rate": + return CNFlow.fixedRate; + case "standard": + default: + return CNFlow.standard; + } + } + + static CNExchangeType _parseType(String value) { + switch (value) { + case "reverse": + return CNExchangeType.reverse; + case "direct": + default: + return CNExchangeType.direct; + } } @override diff --git a/lib/models/exchange/change_now/exchange_transaction.dart b/lib/models/exchange/change_now/exchange_transaction.dart index 6bd514546..1de49bfd0 100644 --- a/lib/models/exchange/change_now/exchange_transaction.dart +++ b/lib/models/exchange/change_now/exchange_transaction.dart @@ -1,6 +1,6 @@ -/* +/* * This file is part of Stack Wallet. - * + * * Copyright (c) 2023 Cypher Stack * All Rights Reserved. * The code is distributed under GPLv3 license, see LICENSE file for details. @@ -77,6 +77,7 @@ class ExchangeTransaction { // @HiveField(14) final ExchangeTransactionStatus? statusObject; + @Deprecated("Only kept for legacy reasons") ExchangeTransaction({ required this.id, required this.payinAddress, @@ -96,6 +97,7 @@ class ExchangeTransaction { }); /// Important to pass a "date": DateTime in or it will default to 1970 + @Deprecated("Only kept for legacy reasons") factory ExchangeTransaction.fromJson(Map json) { try { return ExchangeTransaction( @@ -111,14 +113,16 @@ class ExchangeTransaction { refundExtraId: json["refundExtraId"] as String? ?? "", payoutExtraIdName: json["payoutExtraIdName"] as String? ?? "", uuid: json["uuid"] as String? ?? const Uuid().v1(), - date: DateTime.tryParse(json["date"] as String? ?? "") ?? + date: + DateTime.tryParse(json["date"] as String? ?? "") ?? DateTime.fromMillisecondsSinceEpoch(0), statusString: json["statusString"] as String? ?? "", - statusObject: json["statusObject"] is Map - ? ExchangeTransactionStatus.fromJson( - json["statusObject"] as Map, - ) - : null, + statusObject: + json["statusObject"] is Map + ? ExchangeTransactionStatus.fromJson( + json["statusObject"] as Map, + ) + : null, ); } catch (e) { rethrow; diff --git a/lib/models/exchange/change_now/exchange_transaction_status.dart b/lib/models/exchange/change_now/exchange_transaction_status.dart index 7874b8b80..5a904690f 100644 --- a/lib/models/exchange/change_now/exchange_transaction_status.dart +++ b/lib/models/exchange/change_now/exchange_transaction_status.dart @@ -1,6 +1,6 @@ -/* +/* * This file is part of Stack Wallet. - * + * * Copyright (c) 2023 Cypher Stack * All Rights Reserved. * The code is distributed under GPLv3 license, see LICENSE file for details. @@ -11,38 +11,14 @@ import 'package:hive/hive.dart'; import '../../../utilities/logger.dart'; +import 'cn_exchange_transaction_status.dart' + show + ChangeNowTransactionStatus, + changeNowTransactionStatusFromStringIgnoreCase; part '../../type_adaptors/exchange_transaction_status.g.dart'; -enum ChangeNowTransactionStatus { - New, - Waiting, - Confirming, - Exchanging, - Sending, - Finished, - Failed, - Refunded, - Verifying, -} - -extension ChangeNowTransactionStatusExt on ChangeNowTransactionStatus { - String get lowerCaseName => name.toLowerCase(); -} - -ChangeNowTransactionStatus changeNowTransactionStatusFromStringIgnoreCase( - String string, -) { - for (final value in ChangeNowTransactionStatus.values) { - if (value.lowerCaseName == string.toLowerCase()) { - return value; - } - } - throw ArgumentError( - "String value does not match any known ChangeNowTransactionStatus", - ); -} - +@Deprecated("Only kept for legacy reasons") @HiveType(typeId: 16) class ExchangeTransactionStatus { /// Transaction status @@ -156,6 +132,7 @@ class ExchangeTransactionStatus { @HiveField(26) final bool isPartner; + @Deprecated("Only kept for legacy reasons") ExchangeTransactionStatus({ required this.status, required this.payinAddress, @@ -186,6 +163,7 @@ class ExchangeTransactionStatus { required this.payload, }); + @Deprecated("Only kept for legacy reasons") factory ExchangeTransactionStatus.fromJson(Map json) { Logging.instance.d(json, stackTrace: StackTrace.current); try { @@ -199,12 +177,14 @@ class ExchangeTransactionStatus { toCurrency: json["toCurrency"] as String? ?? "", id: json["id"] as String, updatedAt: json["updatedAt"] as String? ?? "", - expectedSendAmountDecimal: json["expectedSendAmount"] == null - ? "" - : json["expectedSendAmount"].toString(), - expectedReceiveAmountDecimal: json["expectedReceiveAmount"] == null - ? "" - : json["expectedReceiveAmount"].toString(), + expectedSendAmountDecimal: + json["expectedSendAmount"] == null + ? "" + : json["expectedSendAmount"].toString(), + expectedReceiveAmountDecimal: + json["expectedReceiveAmount"] == null + ? "" + : json["expectedReceiveAmount"].toString(), createdAt: json["createdAt"] as String? ?? "", isPartner: json["isPartner"] as bool, depositReceivedAt: json["depositReceivedAt"] as String? ?? "", @@ -216,9 +196,10 @@ class ExchangeTransactionStatus { payoutExtraId: json["payoutExtraId"] as String? ?? "", amountSendDecimal: json["amountSend"] == null ? "" : json["amountSend"].toString(), - amountReceiveDecimal: json["amountReceive"] == null - ? "" - : json["amountReceive"].toString(), + amountReceiveDecimal: + json["amountReceive"] == null + ? "" + : json["amountReceive"].toString(), tokensDestination: json["tokensDestination"] as String? ?? "", refundAddress: json["refundAddress"] as String? ?? "", refundExtraId: json["refundExtraId"] as String? ?? "", @@ -233,6 +214,7 @@ class ExchangeTransactionStatus { } } + @Deprecated("Only kept for legacy reasons") Map toJson() { final map = { "status": status.name, @@ -267,6 +249,7 @@ class ExchangeTransactionStatus { return map; } + @Deprecated("Only kept for legacy reasons") ExchangeTransactionStatus copyWith({ ChangeNowTransactionStatus? status, String? payinAddress, diff --git a/lib/models/exchange/incomplete_exchange.dart b/lib/models/exchange/incomplete_exchange.dart index 1397afb1a..3608b8b05 100644 --- a/lib/models/exchange/incomplete_exchange.dart +++ b/lib/models/exchange/incomplete_exchange.dart @@ -10,13 +10,16 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; + +import '../../utilities/enums/exchange_rate_type_enum.dart'; import 'response_objects/estimate.dart'; import 'response_objects/trade.dart'; -import '../../utilities/enums/exchange_rate_type_enum.dart'; class IncompleteExchangeModel extends ChangeNotifier { final String sendTicker; + final String? sendNetwork; final String receiveTicker; + final String? receiveNetwork; final String rateInfo; @@ -74,7 +77,9 @@ class IncompleteExchangeModel extends ChangeNotifier { IncompleteExchangeModel({ required this.sendTicker, + required this.sendNetwork, required this.receiveTicker, + required this.receiveNetwork, required this.rateInfo, required this.sendAmount, required this.receiveAmount, diff --git a/lib/models/exchange/response_objects/trade.dart b/lib/models/exchange/response_objects/trade.dart index 03685a0ab..e6f996f9b 100644 --- a/lib/models/exchange/response_objects/trade.dart +++ b/lib/models/exchange/response_objects/trade.dart @@ -11,6 +11,7 @@ import 'package:hive/hive.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; +import '../change_now/cn_exchange_transaction.dart'; import '../change_now/exchange_transaction.dart'; part 'trade.g.dart'; @@ -225,9 +226,10 @@ class Trade { timestamp: exTx.date, updatedAt: DateTime.tryParse(exTx.statusObject!.updatedAt) ?? exTx.date, payInCurrency: exTx.fromCurrency, - payInAmount: exTx.statusObject!.amountSendDecimal.isEmpty - ? exTx.statusObject!.expectedSendAmountDecimal - : exTx.statusObject!.amountSendDecimal, + payInAmount: + exTx.statusObject!.amountSendDecimal.isEmpty + ? exTx.statusObject!.expectedSendAmountDecimal + : exTx.statusObject!.amountSendDecimal, payInAddress: exTx.payinAddress, payInNetwork: "", payInExtraId: exTx.payinExtraId, @@ -245,6 +247,42 @@ class Trade { ); } + factory Trade.fromCNExchangeTransaction( + CNExchangeTransaction exTx, + bool reversed, + ) { + return Trade( + uuid: exTx.uuid, + tradeId: exTx.id, + rateType: "", + direction: reversed ? "reverse" : "direct", + timestamp: exTx.date, + updatedAt: DateTime.tryParse(exTx.statusObject!.updatedAt) ?? exTx.date, + payInCurrency: exTx.fromCurrency, + payInAmount: + exTx.statusObject!.amountFrom ?? + exTx.statusObject!.expectedAmountFrom ?? + exTx.fromAmount.toString(), + payInAddress: exTx.payinAddress, + payInNetwork: exTx.fromNetwork, + payInExtraId: "", + payInTxid: exTx.statusObject!.payinHash ?? "", + payOutCurrency: exTx.toCurrency, + payOutAmount: + exTx.statusObject!.amountTo ?? + exTx.statusObject!.expectedAmountTo ?? + exTx.toAmount.toString(), + payOutAddress: exTx.payoutAddress, + payOutNetwork: exTx.toNetwork, + payOutExtraId: exTx.payoutExtraId, + payOutTxid: exTx.statusObject!.payoutHash ?? "", + refundAddress: exTx.refundAddress, + refundExtraId: exTx.refundExtraId, + status: exTx.statusObject!.status.name, + exchangeName: ChangeNowExchange.exchangeName, + ); + } + @override String toString() { return toMap().toString(); diff --git a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart index 89a818529..23035dc8e 100644 --- a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart +++ b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart @@ -48,26 +48,28 @@ class _AddTokenListElementState extends ConsumerState { @override Widget build(BuildContext context) { - final currency = ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - widget.data.token.address, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirstSync(); + final currency = + ExchangeDataLoadingService.instance.isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + widget.data.token.address, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirstSync(); final String mainLabel = widget.data.token.name; final double iconSize = isDesktop ? 32 : 24; return RoundedWhiteContainer( padding: EdgeInsets.all(isDesktop ? 16 : 12), - borderColor: isDesktop - ? Theme.of(context).extension()!.backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.backgroundAppBar + : null, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -75,71 +77,68 @@ class _AddTokenListElementState extends ConsumerState { children: [ currency != null ? SvgPicture.network( - currency.image, - width: iconSize, - height: iconSize, - placeholderBuilder: (_) => AppIcon( - width: iconSize, - height: iconSize, - ), - ) + currency.image, + width: iconSize, + height: iconSize, + placeholderBuilder: + (_) => AppIcon(width: iconSize, height: iconSize), + ) : SvgPicture.asset( - widget.data.token.symbol == "BNB" - ? Assets.svg.bnbIcon - : Assets.svg.ethereum, - width: iconSize, - height: iconSize, - ), - const SizedBox( - width: 12, - ), + widget.data.token.symbol == "BNB" + ? Assets.svg.bnbIcon + : Assets.svg.ethereum, + width: iconSize, + height: iconSize, + ), + const SizedBox(width: 12), ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - const SizedBox( - height: 2, - ), - Text( - widget.data.token.symbol, - style: STextStyles.desktopTextExtraExtraSmall(context), - overflow: TextOverflow.ellipsis, + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + child, + const SizedBox(height: 2), + Text( + widget.data.token.symbol, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + overflow: TextOverflow.ellipsis, + ), + ], ), - ], - ), child: Text( isDesktop ? mainLabel : "$mainLabel (${widget.data.token.symbol})", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.w600_14(context), + style: + isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.w600_14(context), overflow: TextOverflow.ellipsis, ), ), ], ), - const SizedBox( - width: 4, - ), + const SizedBox(width: 4), isDesktop ? Checkbox( - value: widget.data.selected, - onChanged: (newValue) => - setState(() => widget.data.selected = newValue!), - ) + value: widget.data.selected, + onChanged: + (newValue) => + setState(() => widget.data.selected = newValue!), + ) : SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: widget.data.selected, - onValueChanged: (newValue) { - widget.data.selected = newValue; - }, - ), + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: widget.data.selected, + onValueChanged: (newValue) { + widget.data.selected = newValue; + }, ), + ), ], ), ); diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart index 68527ccaf..80acac3ed 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; + import '../../../../models/add_wallet_list_entity/add_wallet_list_entity.dart'; import '../../../../models/add_wallet_list_entity/sub_classes/eth_token_entity.dart'; import '../../../../models/isar/exchange_cache/currency.dart'; @@ -28,10 +29,7 @@ import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; class CoinSelectItem extends ConsumerWidget { - const CoinSelectItem({ - super.key, - required this.entity, - }); + const CoinSelectItem({super.key, required this.entity}); final AddWalletListEntity entity; @@ -44,82 +42,77 @@ class CoinSelectItem extends ConsumerWidget { String? tokenImageUri; if (entity is EthTokenEntity) { - final currency = ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - (entity as EthTokenEntity).token.address, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirstSync(); + final currency = + ExchangeDataLoadingService.instance.isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + (entity as EthTokenEntity).token.address, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirstSync(); tokenImageUri = currency?.image; } return Container( decoration: BoxDecoration( - color: selectedEntity == entity - ? Theme.of(context).extension()!.textFieldActiveBG - : Theme.of(context).extension()!.popupBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + selectedEntity == entity + ? Theme.of(context).extension()!.textFieldActiveBG + : Theme.of(context).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: MaterialButton( key: Key("coinSelectItemButtonKey_${entity.name}${entity.ticker}"), - padding: isDesktop - ? const EdgeInsets.only(left: 24) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.only(left: 24) + : const EdgeInsets.all(12), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: isDesktop ? 70 : 0, - ), + constraints: BoxConstraints(minHeight: isDesktop ? 70 : 0), child: Row( children: [ tokenImageUri != null - ? SvgPicture.network( - tokenImageUri, - width: 26, - height: 26, - ) + ? SvgPicture.network(tokenImageUri, width: 26, height: 26) : SvgPicture.file( - File( - ref.watch(coinIconProvider(entity.cryptoCurrency)), - ), - width: 26, - height: 26, - ), - SizedBox( - width: isDesktop ? 12 : 10, - ), + File(ref.watch(coinIconProvider(entity.cryptoCurrency))), + width: 26, + height: 26, + ), + SizedBox(width: isDesktop ? 12 : 10), Text( "${entity.name} (${entity.ticker})", - style: isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.subtitle600(context).copyWith( - fontSize: 14, - ), + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.subtitle600( + context, + ).copyWith(fontSize: 14), ), if (isDesktop && selectedEntity == entity) const Spacer(), if (isDesktop && selectedEntity == entity) Padding( - padding: const EdgeInsets.only( - right: 18, - ), + padding: const EdgeInsets.only(right: 18), child: SizedBox( width: 24, height: 24, child: SvgPicture.asset( Assets.svg.check, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index e3ae98acd..5801cf869 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -15,10 +15,8 @@ import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; import '../../../app_config.dart'; -import '../../../exceptions/exchange/unsupported_currency_exception.dart'; import '../../../models/isar/exchange_cache/currency.dart'; import '../../../models/isar/exchange_cache/pair.dart'; -import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange.dart'; import '../../../services/exchange/exchange_data_loading_service.dart'; import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; @@ -34,12 +32,9 @@ import '../../../widgets/background.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_loading_overlay.dart'; -import '../../../widgets/desktop/primary_button.dart'; -import '../../../widgets/desktop/secondary_button.dart'; import '../../../widgets/icon_widgets/x_icon.dart'; import '../../../widgets/loading_indicator.dart'; import '../../../widgets/rounded_white_container.dart'; -import '../../../widgets/stack_dialog.dart'; import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; import '../../buy_view/sub_widgets/crypto_selection_view.dart'; @@ -74,26 +69,24 @@ class _ExchangeCurrencySelectionViewState bool _loaded = false; String _searchString = ""; - Future _showUpdatingCurrencies({ - required Future whileFuture, - }) async { + Future _showUpdatingCurrencies({required Future whileFuture}) async { unawaited( showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: const CustomLoadingOverlay( - message: "Loading currencies", - eventBus: null, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.6), + child: const CustomLoadingOverlay( + message: "Loading currencies", + eventBus: null, + ), + ), ), - ), - ), ), ); @@ -111,85 +104,52 @@ class _ExchangeCurrencySelectionViewState return await _getCurrencies(); } await ExchangeDataLoadingService.instance.initDB(); - final List currencies = await ExchangeDataLoadingService - .instance.isar.currencies - .where() - .filter() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .or() - .exchangeNameStartsWith(TrocadorExchange.exchangeName) - .or() - .exchangeNameStartsWith(NanswapExchange.exchangeName) - .findAll(); - - final cn = await ChangeNowExchange.instance.getPairedCurrencies( - widget.pairedTicker!, - widget.isFixedRate, - ); - - if (cn.value == null) { - if (cn.exception is UnsupportedCurrencyException) { - return _getDistinctCurrenciesFrom(currencies); - } - - if (mounted) { - await showDialog( - context: context, - builder: (context) => StackDialog( - title: "Exchange Error", - message: "Failed to load currency data: ${cn.exception}", - leftButton: SecondaryButton( - label: "Ok", - onPressed: Navigator.of(context, rootNavigator: isDesktop).pop, - ), - rightButton: PrimaryButton( - label: "Retry", - onPressed: () async { - Navigator.of(context, rootNavigator: isDesktop).pop(); - _currencies = await _showUpdatingCurrencies( - whileFuture: _loadCurrencies(), - ); - setState(() {}); - }, - ), - ), - ); - } - } else { - currencies.addAll(cn.value!); - } + final List currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .where() + .filter() + .exchangeNameEqualTo(MajesticBankExchange.exchangeName) + .or() + .exchangeNameStartsWith(TrocadorExchange.exchangeName) + .or() + .exchangeNameStartsWith(NanswapExchange.exchangeName) + .findAll(); return _getDistinctCurrenciesFrom(currencies); } Future> _getCurrencies() async { await ExchangeDataLoadingService.instance.initDB(); - final currencies = await ExchangeDataLoadingService.instance.isar.currencies - .where() - .filter() - .isFiatEqualTo(false) - .and() - .group( - (q) => widget.isFixedRate - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .sortByIsStackCoin() - .thenByName() - .findAll(); + final currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .where() + .filter() + .isFiatEqualTo(false) + .and() + .group( + (q) => + widget.isFixedRate + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .sortByIsStackCoin() + .thenByName() + .findAll(); // 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), + (element) => + !Exchange.exchangeNamesWithTorSupport.contains( + element.exchangeName, + ), ); } } @@ -262,8 +222,9 @@ class _ExchangeCurrencySelectionViewState if (!_loaded) { _loaded = true; WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - _currencies = - await _showUpdatingCurrencies(whileFuture: _loadCurrencies()); + _currencies = await _showUpdatingCurrencies( + whileFuture: _loadCurrencies(), + ); setState(() {}); }); } @@ -284,7 +245,7 @@ class _ExchangeCurrencySelectionViewState const Duration(milliseconds: 50), ); } - if (mounted) { + if (context.mounted) { Navigator.of(context).pop(); } }, @@ -295,9 +256,7 @@ class _ExchangeCurrencySelectionViewState ), ), body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(horizontal: 16), child: child, ), ), @@ -307,10 +266,7 @@ class _ExchangeCurrencySelectionViewState crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, children: [ - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -340,32 +296,31 @@ class _ExchangeCurrencySelectionViewState height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Flexible( child: Builder( builder: (context) { @@ -377,17 +332,19 @@ class _ExchangeCurrencySelectionViewState final items = filter(_searchString); - final walletCoins = items - .where( - (currency) => coins - .where( - (coin) => - coin.ticker.toLowerCase() == - currency.ticker.toLowerCase(), - ) - .isNotEmpty, - ) - .toList(); + final walletCoins = + items + .where( + (currency) => + coins + .where( + (coin) => + coin.ticker.toLowerCase() == + currency.ticker.toLowerCase(), + ) + .isNotEmpty, + ) + .toList(); // sort alphabetically by name items.sort((a, b) => a.name.compareTo(b.name)); @@ -408,8 +365,9 @@ class _ExchangeCurrencySelectionViewState primary: isDesktop ? false : null, itemCount: items.length, itemBuilder: (builderContext, index) { - final bool hasImageUrl = - items[index].image.startsWith("http"); + final bool hasImageUrl = items[index].image.startsWith( + "http", + ); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( @@ -425,29 +383,27 @@ class _ExchangeCurrencySelectionViewState child: AppConfig.isStackCoin(items[index].ticker) ? CoinIconForTicker( - ticker: items[index].ticker, - size: 24, - ) + ticker: items[index].ticker, + size: 24, + ) // ? getIconForTicker( // items[index].ticker, // size: 24, // ) : hasImageUrl - ? SvgPicture.network( - items[index].image, - width: 24, - height: 24, - placeholderBuilder: (_) => - const LoadingIndicator(), - ) - : const SizedBox( - width: 24, - height: 24, - ), - ), - const SizedBox( - width: 10, + ? SvgPicture.network( + items[index].image, + width: 24, + height: 24, + placeholderBuilder: + (_) => const LoadingIndicator(), + ) + : const SizedBox( + width: 24, + height: 24, + ), ), + const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: @@ -455,19 +411,20 @@ class _ExchangeCurrencySelectionViewState children: [ Text( items[index].name, - style: - STextStyles.largeMedium14(context), - ), - const SizedBox( - height: 2, + style: STextStyles.largeMedium14( + context, + ), ), + const SizedBox(height: 2), Text( items[index].ticker.toUpperCase(), - style: STextStyles.smallMed12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ), ], diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 111d38448..13f334d2a 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -40,6 +40,7 @@ import '../../utilities/amount/amount_unit.dart'; import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/enums/exchange_rate_type_enum.dart'; +import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; @@ -60,12 +61,7 @@ import 'sub_widgets/exchange_provider_options.dart'; import 'sub_widgets/rate_type_toggle.dart'; class ExchangeForm extends ConsumerStatefulWidget { - const ExchangeForm({ - super.key, - this.walletId, - this.coin, - this.contract, - }); + const ExchangeForm({super.key, this.walletId, this.coin, this.contract}); final String? walletId; final CryptoCurrency? coin; @@ -111,19 +107,19 @@ class _ExchangeFormState extends ConsumerState { showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: const CustomLoadingOverlay( - message: "Updating exchange rate", - eventBus: null, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.6), + child: const CustomLoadingOverlay( + message: "Updating exchange rate", + eventBus: null, + ), + ), ), - ), - ), ), ); @@ -185,27 +181,26 @@ class _ExchangeFormState extends ConsumerState { Future _getAggregateCurrency(Currency currency) async { final rateType = ref.read(efRateTypeProvider); - final currencies = await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo( - currency.ticker, - caseSensitive: false, - ) - .and() - .tokenContractEqualTo(currency.tokenContract) - .findAll(); + final currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .and() + .tickerEqualTo(currency.ticker, caseSensitive: false) + .and() + .tokenContractEqualTo(currency.tokenContract) + .findAll(); final items = [Tuple2(currency.exchangeName, currency)]; @@ -242,10 +237,9 @@ class _ExchangeFormState extends ConsumerState { if (selectedCurrency != null) { await showUpdatingExchangeRate( whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref.read(efCurrencyPairProvider).setSend( - aggregateSelected, - notifyListeners: true, - ), + (aggregateSelected) => ref + .read(efCurrencyPairProvider) + .setSend(aggregateSelected, notifyListeners: true), ), ); } @@ -269,10 +263,9 @@ class _ExchangeFormState extends ConsumerState { if (selectedCurrency != null) { await showUpdatingExchangeRate( whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref.read(efCurrencyPairProvider).setReceive( - aggregateSelected, - notifyListeners: true, - ), + (aggregateSelected) => ref + .read(efCurrencyPairProvider) + .setReceive(aggregateSelected, notifyListeners: true), ), ); } @@ -284,20 +277,20 @@ class _ExchangeFormState extends ConsumerState { _receiveFocusNode.unfocus(); final temp = ref.read(efCurrencyPairProvider).send; - ref.read(efCurrencyPairProvider).setSend( + ref + .read(efCurrencyPairProvider) + .setSend( ref.read(efCurrencyPairProvider).receive, notifyListeners: true, ); - ref.read(efCurrencyPairProvider).setReceive( - temp, - notifyListeners: true, - ); + ref.read(efCurrencyPairProvider).setReceive(temp, notifyListeners: true); // final reversed = ref.read(efReversedProvider); final amount = ref.read(efSendAmountProvider); - ref.read(efSendAmountProvider.notifier).state = - ref.read(efReceiveAmountProvider); + ref.read(efSendAmountProvider.notifier).state = ref.read( + efReceiveAmountProvider, + ); ref.read(efReceiveAmountProvider.notifier).state = amount; @@ -315,72 +308,73 @@ class _ExchangeFormState extends ConsumerState { _sendFocusNode.unfocus(); _receiveFocusNode.unfocus(); - final result = isDesktop - ? await showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxHeight: 700, - maxWidth: 580, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( + final result = + isDesktop + ? await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxHeight: 700, + maxWidth: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Choose a coin to exchange", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( padding: const EdgeInsets.only( left: 32, + right: 32, + bottom: 32, ), - child: Text( - "Choose a coin to exchange", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Row( - children: [ - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - borderColor: Theme.of(context) - .extension()! - .background, - child: ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, - isFixedRate: isFixedRate, - willChangeIsSend: willChangeIsSend, + child: Row( + children: [ + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: ExchangeCurrencySelectionView( + willChangeTicker: willChange, + pairedTicker: paired, + isFixedRate: isFixedRate, + willChangeIsSend: willChangeIsSend, + ), ), ), - ), - ], + ], + ), ), ), + ], + ), + ); + }, + ) + : await Navigator.of(context).push( + MaterialPageRoute( + builder: + (_) => ExchangeCurrencySelectionView( + willChangeTicker: willChange, + pairedTicker: paired, + isFixedRate: isFixedRate, + willChangeIsSend: willChangeIsSend, ), - ], - ), - ); - }, - ) - : await Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, - isFixedRate: isFixedRate, - willChangeIsSend: willChangeIsSend, ), - ), - ); + ); if (mounted && result is Currency) { return result; @@ -398,20 +392,31 @@ class _ExchangeFormState extends ConsumerState { } void onExchangePressed() async { + final exchangeName = ref.read(efExchangeProvider).name; + final rateType = ref.read(efRateTypeProvider); final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; + final fromNetwork = ref + .read(efCurrencyPairProvider) + .send + ?.networkFor(exchangeName); final toTicker = ref.read(efCurrencyPairProvider).receive?.ticker ?? ""; + final toNetwork = ref + .read(efCurrencyPairProvider) + .receive + ?.networkFor(exchangeName); final estimate = ref.read(efEstimateProvider)!; final sendAmount = ref.read(efSendAmountProvider)!; if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") { await showDialog( context: context, - builder: (context) => const StackOkDialog( - title: "WOW error", - message: - "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", - ), + builder: + (context) => const StackOkDialog( + title: "WOW error", + message: + "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", + ), ); return; @@ -421,9 +426,10 @@ class _ExchangeFormState extends ConsumerState { final amountToSend = estimate.reversed ? estimate.estimatedAmount : sendAmount; - final amountToReceive = estimate.reversed - ? ref.read(efReceiveAmountProvider)! - : estimate.estimatedAmount; + final amountToReceive = + estimate.reversed + ? ref.read(efReceiveAmountProvider)! + : estimate.estimatedAmount; switch (rateType) { case ExchangeRateType.estimated: @@ -466,32 +472,30 @@ class _ExchangeFormState extends ConsumerState { "Do you want to attempt trade anyways?", style: STextStyles.desktopTextSmall(context), ), - const Spacer( - flex: 2, - ), + const Spacer(flex: 2), Row( children: [ Expanded( child: SecondaryButton( label: "Cancel", buttonHeight: ButtonHeight.l, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(true), + onPressed: + () => Navigator.of( + context, + rootNavigator: true, + ).pop(true), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Attempt", buttonHeight: ButtonHeight.l, - onPressed: () => Navigator.of( - context, - rootNavigator: true, - ).pop(false), + onPressed: + () => Navigator.of( + context, + rootNavigator: true, + ).pop(false), ), ), ], @@ -521,10 +525,7 @@ class _ExchangeFormState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Attempt", - style: STextStyles.button(context), - ), + child: Text("Attempt", style: STextStyles.button(context)), onPressed: () { // continue and try to attempt trade Navigator.of(context).pop(false); @@ -540,15 +541,15 @@ class _ExchangeFormState extends ConsumerState { return; } rate = - "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal( - scaleOnInfinitePrecision: 12, - ).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; + "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(scaleOnInfinitePrecision: 12).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; break; } final model = IncompleteExchangeModel( sendTicker: fromTicker.toUpperCase(), + sendNetwork: fromNetwork, receiveTicker: toTicker.toUpperCase(), + receiveNetwork: toNetwork, rateInfo: rate, sendAmount: amountToSend, receiveAmount: amountToReceive, @@ -560,8 +561,10 @@ class _ExchangeFormState extends ConsumerState { if (mounted) { if (walletInitiated) { - ref.read(exchangeSendFromWalletIdStateProvider.state).state = - Tuple2(walletId!, coin!); + ref.read(exchangeSendFromWalletIdStateProvider.state).state = Tuple2( + walletId!, + coin!, + ); if (isDesktop) { ref.read(ssss.state).state = model; await showDialog( @@ -571,18 +574,15 @@ class _ExchangeFormState extends ConsumerState { return const DesktopDialog( maxWidth: 720, maxHeight: double.infinity, - child: StepScaffold( - initialStep: 2, - ), + child: StepScaffold(initialStep: 2), ); }, ); } else { unawaited( - Navigator.of(context).pushNamed( - Step2View.routeName, - arguments: model, - ), + Navigator.of( + context, + ).pushNamed(Step2View.routeName, arguments: model), ); } } else { @@ -597,18 +597,15 @@ class _ExchangeFormState extends ConsumerState { return const DesktopDialog( maxWidth: 720, maxHeight: double.infinity, - child: StepScaffold( - initialStep: 1, - ), + child: StepScaffold(initialStep: 1), ); }, ); } else { unawaited( - Navigator.of(context).pushNamed( - Step1View.routeName, - arguments: model, - ), + Navigator.of( + context, + ).pushNamed(Step1View.routeName, arguments: model), ); } } @@ -620,9 +617,10 @@ class _ExchangeFormState extends ConsumerState { return false; } - final String? ticker = isSend - ? ref.read(efCurrencyPairProvider).send?.ticker - : ref.read(efCurrencyPairProvider).receive?.ticker; + final String? ticker = + isSend + ? ref.read(efCurrencyPairProvider).send?.ticker + : ref.read(efCurrencyPairProvider).receive?.ticker; if (ticker == null) { return false; @@ -640,9 +638,10 @@ class _ExchangeFormState extends ConsumerState { } final reversed = ref.read(efReversedProvider); - final amount = reversed - ? ref.read(efReceiveAmountProvider) - : ref.read(efSendAmountProvider); + final amount = + reversed + ? ref.read(efReceiveAmountProvider) + : ref.read(efSendAmountProvider); final pair = ref.read(efCurrencyPairProvider); if (amount == null || @@ -654,7 +653,7 @@ class _ExchangeFormState extends ConsumerState { } final rateType = ref.read(efRateTypeProvider); final Map>, Range?>> - results = {}; + results = {}; for (final exchange in usableExchanges) { final sendCurrency = pair.send?.forExchange(exchange.name); @@ -663,26 +662,29 @@ class _ExchangeFormState extends ConsumerState { if (sendCurrency != null && receiveCurrency != null) { final rangeResponse = await exchange.getRange( reversed ? receiveCurrency.ticker : sendCurrency.ticker, + reversed ? receiveCurrency.network : sendCurrency.network, reversed ? sendCurrency.ticker : receiveCurrency.ticker, + reversed ? sendCurrency.network : receiveCurrency.network, rateType == ExchangeRateType.fixed, ); + Logging.instance.d( + "${exchange.name}: fixedRate=$rateType, RANGE=$rangeResponse", + ); + final estimateResponse = await exchange.getEstimates( sendCurrency.ticker, + sendCurrency.network, receiveCurrency.ticker, + receiveCurrency.network, amount, rateType == ExchangeRateType.fixed, reversed, ); - results.addAll( - { - exchange.name: Tuple2( - estimateResponse, - rangeResponse.value, - ), - }, - ); + results.addAll({ + exchange.name: Tuple2(estimateResponse, rangeResponse.value), + }); } } @@ -767,18 +769,17 @@ class _ExchangeFormState extends ConsumerState { .setReceive(null, notifyListeners: true); ExchangeDataLoadingService.instance .getAggregateCurrency( - widget.contract == null ? coin!.ticker : widget.contract!.symbol, - ExchangeRateType.estimated, - widget.contract == null ? null : widget.contract!.address, - ) + widget.contract == null ? coin!.ticker : widget.contract!.symbol, + ExchangeRateType.estimated, + widget.contract?.address, + ) .then((value) { - if (value != null) { - ref.read(efCurrencyPairProvider).setSend( - value, - notifyListeners: true, - ); - } - }); + if (value != null) { + ref + .read(efCurrencyPairProvider) + .setSend(value, notifyListeners: true); + } + }); }); } else { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { @@ -816,9 +817,7 @@ class _ExchangeFormState extends ConsumerState { if (_sendFocusNode.hasFocus) { _sendController.selection = TextSelection.fromPosition( - TextPosition( - offset: _sendController.text.length, - ), + TextPosition(offset: _sendController.text.length), ); } } @@ -835,9 +834,7 @@ class _ExchangeFormState extends ConsumerState { if (_receiveFocusNode.hasFocus) { _receiveController.selection = TextSelection.fromPosition( - TextPosition( - offset: _receiveController.text.length, - ), + TextPosition(offset: _receiveController.text.length), ); } } @@ -868,13 +865,13 @@ class _ExchangeFormState extends ConsumerState { color: Theme.of(context).extension()!.textDark3, ), ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), ExchangeTextField( - key: Key("exchangeTextFieldKeyFor_" - "${Theme.of(context).extension()!.themeId}" - "${ref.watch(efCurrencyPairProvider.select((value) => value.send?.ticker))}"), + key: Key( + "exchangeTextFieldKeyFor_" + "${Theme.of(context).extension()!.themeId}" + "${ref.watch(efCurrencyPairProvider.select((value) => value.send?.ticker))}", + ), controller: _sendController, focusNode: _sendFocusNode, textStyle: STextStyles.smallMed14(context).copyWith( @@ -893,15 +890,12 @@ class _ExchangeFormState extends ConsumerState { onChanged: sendFieldOnChanged, onButtonTap: selectSendCurrency, isWalletCoin: isWalletCoin(coin, true), - currency: - ref.watch(efCurrencyPairProvider.select((value) => value.send)), - ), - SizedBox( - height: isDesktop ? 10 : 4, - ), - SizedBox( - height: isDesktop ? 10 : 4, + currency: ref.watch( + efCurrencyPairProvider.select((value) => value.send), + ), ), + SizedBox(height: isDesktop ? 10 : 4), + SizedBox(height: isDesktop ? 10 : 4), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -914,20 +908,23 @@ class _ExchangeFormState extends ConsumerState { ), ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => MouseRegion( + cursor: SystemMouseCursors.click, + child: child, + ), child: Semantics( label: "Swap Button. Reverse The Exchange Currencies.", excludeSemantics: true, child: RoundedContainer( - padding: isDesktop - ? const EdgeInsets.all(6) - : const EdgeInsets.all(2), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + padding: + isDesktop + ? const EdgeInsets.all(6) + : const EdgeInsets.all(2), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, radiusMultiplier: 0.75, child: GestureDetector( onTap: () async { @@ -939,9 +936,10 @@ class _ExchangeFormState extends ConsumerState { Assets.svg.swap, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), @@ -950,9 +948,7 @@ class _ExchangeFormState extends ConsumerState { ), ], ), - SizedBox( - height: isDesktop ? 10 : 7, - ), + SizedBox(height: isDesktop ? 10 : 7), ExchangeTextField( key: Key( "exchangeTextFieldKeyFor1_${Theme.of(context).extension()!.themeId}", @@ -967,52 +963,47 @@ class _ExchangeFormState extends ConsumerState { borderRadius: Constants.size.circularBorderRadius, background: Theme.of(context).extension()!.textFieldDefaultBG, - onTap: rateType == ExchangeRateType.estimated && - ref.watch(efExchangeProvider).name == - ChangeNowExchange.exchangeName - ? null - : () { - if (_sendController.text == "-") { - _sendController.text = ""; - } - }, + onTap: + rateType == ExchangeRateType.estimated && + ref.watch(efExchangeProvider).name == + ChangeNowExchange.exchangeName + ? null + : () { + if (_sendController.text == "-") { + _sendController.text = ""; + } + }, onChanged: receiveFieldOnChanged, onButtonTap: selectReceiveCurrency, isWalletCoin: isWalletCoin(coin, true), - currency: ref - .watch(efCurrencyPairProvider.select((value) => value.receive)), - readOnly: rateType == ExchangeRateType.estimated && + currency: ref.watch( + efCurrencyPairProvider.select((value) => value.receive), + ), + readOnly: + rateType == ExchangeRateType.estimated && ref.watch(efExchangeProvider).name == ChangeNowExchange.exchangeName, ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), SizedBox( height: isDesktop ? 60 : 40, - child: RateTypeToggle( - key: UniqueKey(), - onChanged: onRateTypeChanged, - ), + child: RateTypeToggle(key: UniqueKey(), onChanged: onRateTypeChanged), ), AnimatedSize( duration: const Duration(milliseconds: 300), - child: ref.watch(efSendAmountProvider) == null && - ref.watch(efReceiveAmountProvider) == null - ? const SizedBox( - height: 0, - ) - : Padding( - padding: EdgeInsets.only(top: isDesktop ? 20 : 12), - child: ExchangeProviderOptions( - fixedRate: rateType == ExchangeRateType.fixed, - reversed: ref.watch(efReversedProvider), + child: + ref.watch(efSendAmountProvider) == null && + ref.watch(efReceiveAmountProvider) == null + ? const SizedBox(height: 0) + : Padding( + padding: EdgeInsets.only(top: isDesktop ? 20 : 12), + child: ExchangeProviderOptions( + fixedRate: rateType == ExchangeRateType.fixed, + reversed: ref.watch(efReversedProvider), + ), ), - ), - ), - SizedBox( - height: isDesktop ? 20 : 12, ), + SizedBox(height: isDesktop ? 20 : 12), PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, enabled: ref.watch(efCanExchangeProvider), diff --git a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart index 2cd014fc3..92c713acb 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart @@ -79,10 +79,7 @@ class _Step3ViewState extends ConsumerState { } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), body: LayoutBuilder( builder: (context, constraints) { @@ -100,21 +97,13 @@ class _Step3ViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - StepRow( - count: 4, - current: 2, - width: width, - ), - const SizedBox( - height: 14, - ), + StepRow(count: 4, current: 2, width: width), + const SizedBox(height: 14), Text( "Confirm exchange details", style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), RoundedWhiteContainer( child: Row( children: [ @@ -130,9 +119,7 @@ class _Step3ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( children: [ @@ -148,9 +135,7 @@ class _Step3ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( children: [ @@ -166,9 +151,7 @@ class _Step3ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -177,9 +160,7 @@ class _Step3ViewState extends ConsumerState { "Recipient ${model.receiveTicker.toUpperCase()} address", style: STextStyles.itemSubtitle(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( model.recipientAddress!, style: STextStyles.itemSubtitle12(context), @@ -187,10 +168,7 @@ class _Step3ViewState extends ConsumerState { ], ), ), - if (supportsRefund) - const SizedBox( - height: 8, - ), + if (supportsRefund) const SizedBox(height: 8), if (supportsRefund) RoundedWhiteContainer( child: Column( @@ -200,9 +178,7 @@ class _Step3ViewState extends ConsumerState { "Refund ${model.sendTicker.toUpperCase()} address", style: STextStyles.itemSubtitle(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( model.refundAddress!, style: STextStyles.itemSubtitle12(context), @@ -210,9 +186,7 @@ class _Step3ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), const Spacer(), Row( children: [ @@ -227,16 +201,15 @@ class _Step3ViewState extends ConsumerState { child: Text( "Back", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: TextButton( onPressed: () async { @@ -244,19 +217,22 @@ class _Step3ViewState extends ConsumerState { showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: const CustomLoadingOverlay( - message: "Creating a trade", - eventBus: null, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.6), + child: + const CustomLoadingOverlay( + message: + "Creating a trade", + eventBus: null, + ), + ), ), - ), - ), ), ); @@ -265,18 +241,23 @@ class _Step3ViewState extends ConsumerState { .read(efExchangeProvider) .createTrade( from: model.sendTicker, + fromNetwork: model.sendNetwork, to: model.receiveTicker, - fixedRate: model.rateType != + toNetwork: model.receiveNetwork, + fixedRate: + model.rateType != ExchangeRateType.estimated, - amount: model.reversed - ? model.receiveAmount - : model.sendAmount, + amount: + model.reversed + ? model.receiveAmount + : model.sendAmount, addressTo: model.recipientAddress!, extraId: null, - addressRefund: supportsRefund - ? model.refundAddress! - : "", + addressRefund: + supportsRefund + ? model.refundAddress! + : "", refundExtraId: "", estimate: model.estimate, reversed: model.reversed, @@ -304,10 +285,12 @@ class _Step3ViewState extends ConsumerState { showDialog( context: context, barrierDismissible: true, - builder: (_) => StackDialog( - title: "Failed to create trade", - message: message ?? "", - ), + builder: + (_) => StackDialog( + title: + "Failed to create trade", + message: message ?? "", + ), ), ); } @@ -315,7 +298,9 @@ class _Step3ViewState extends ConsumerState { } // save trade to hive - await ref.read(tradesServiceProvider).add( + await ref + .read(tradesServiceProvider) + .add( trade: response.value!, shouldNotifyListeners: true, ); diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart index 1ffa12275..6bc4b5c04 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart @@ -70,10 +70,12 @@ class _ExchangeProviderOptionsState @override Widget build(BuildContext context) { - final sendCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.send)); - final receivingCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.receive)); + final sendCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.send), + ); + final receivingCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.receive), + ); final showChangeNow = exchangeSupported( exchangeName: ChangeNowExchange.exchangeName, @@ -98,9 +100,10 @@ class _ExchangeProviderOptionsState return RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(0) : const EdgeInsets.all(12), - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, child: Column( children: [ if (showChangeNow) @@ -112,13 +115,10 @@ class _ExchangeProviderOptionsState if (showChangeNow && showMajesticBank) isDesktop ? Container( - height: 1, - color: - Theme.of(context).extension()!.background, - ) - : const SizedBox( - height: 16, - ), + height: 1, + color: Theme.of(context).extension()!.background, + ) + : const SizedBox(height: 16), if (showMajesticBank) ExchangeOption( exchange: MajesticBankExchange.instance, @@ -128,13 +128,10 @@ class _ExchangeProviderOptionsState if ((showChangeNow || showMajesticBank) && showTrocador) isDesktop ? Container( - height: 1, - color: - Theme.of(context).extension()!.background, - ) - : const SizedBox( - height: 16, - ), + height: 1, + color: Theme.of(context).extension()!.background, + ) + : const SizedBox(height: 16), if (showTrocador) ExchangeOption( fixedRate: widget.fixedRate, @@ -145,13 +142,10 @@ class _ExchangeProviderOptionsState showNanswap) isDesktop ? Container( - height: 1, - color: - Theme.of(context).extension()!.background, - ) - : const SizedBox( - height: 16, - ), + height: 1, + color: Theme.of(context).extension()!.background, + ) + : const SizedBox(height: 16), if (showNanswap) ExchangeOption( fixedRate: widget.fixedRate, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 0416056a7..8bb6017c2 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -20,7 +20,7 @@ import 'package:tuple/tuple.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../app_config.dart'; -import '../../models/exchange/change_now/exchange_transaction_status.dart'; +import '../../models/exchange/change_now/cn_exchange_transaction_status.dart'; import '../../models/isar/models/blockchain_data/transaction.dart'; import '../../models/isar/stack_theme.dart'; import '../../notifications/show_flush_bar.dart'; @@ -164,7 +164,8 @@ class _TradeDetailsViewState extends ConsumerState { ), ); - final bool hasTx = sentFromStack || + final bool hasTx = + sentFromStack || !(trade.status == "New" || trade.status == "new" || trade.status == "Waiting" || @@ -176,7 +177,8 @@ class _TradeDetailsViewState extends ConsumerState { trade.status == "Expired" || trade.status == "expired" || trade.status == "Failed" || - trade.status == "failed"); + trade.status == "failed" || + trade.status.toLowerCase().startsWith("waiting")); //todo: check if print needed // debugPrint("walletId: $walletId"); @@ -190,9 +192,14 @@ class _TradeDetailsViewState extends ConsumerState { final isDesktop = Util.isDesktop; - final showSendFromStackButton = !hasTx && - !["xmr", "monero", "wow", "wownero"] - .contains(trade.payInCurrency.toLowerCase()) && + final showSendFromStackButton = + !hasTx && + ![ + "xmr", + "monero", + "wow", + "wownero", + ].contains(trade.payInCurrency.toLowerCase()) && AppConfig.isStackCoin(trade.payInCurrency) && (trade.status == "New" || trade.status == "new" || @@ -201,132 +208,128 @@ class _TradeDetailsViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Trade details", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Trade details", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), ), ), ), - ), - ), child: Padding( - padding: isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(0), child: BranchedParent( condition: isDesktop, - conditionBranchBuilder: (children) => Padding( - padding: const EdgeInsets.only( - right: 20, - ), - child: Padding( - padding: const EdgeInsets.only( - right: 12, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - RoundedWhiteContainer( - borderColor: Theme.of(context) - .extension()! - .backgroundAppBar, - padding: const EdgeInsets.all(0), - child: ListView( - primary: false, - shrinkWrap: true, - children: children, - ), - ), - if (showSendFromStackButton) - const SizedBox( - height: 32, - ), - if (showSendFromStackButton) - SecondaryButton( - label: "Send from ${AppConfig.prefix}", - buttonHeight: ButtonHeight.l, - onPressed: () { - CryptoCurrency coin; - try { - coin = AppConfig.getCryptoCurrencyForTicker( - trade.payInCurrency, - )!; - } catch (_) { - coin = AppConfig.getCryptoCurrencyByPrettyName( - trade.payInCurrency, - ); - } - final amount = Amount.fromDecimal( - sendAmount, - fractionDigits: coin.fractionDigits, - ); - final address = trade.payInAddress; + conditionBranchBuilder: + (children) => Padding( + padding: const EdgeInsets.only(right: 20), + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + RoundedWhiteContainer( + borderColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, + padding: const EdgeInsets.all(0), + child: ListView( + primary: false, + shrinkWrap: true, + children: children, + ), + ), + if (showSendFromStackButton) const SizedBox(height: 32), + if (showSendFromStackButton) + SecondaryButton( + label: "Send from ${AppConfig.prefix}", + buttonHeight: ButtonHeight.l, + onPressed: () { + CryptoCurrency coin; + try { + coin = + AppConfig.getCryptoCurrencyForTicker( + trade.payInCurrency, + )!; + } catch (_) { + coin = AppConfig.getCryptoCurrencyByPrettyName( + trade.payInCurrency, + ); + } + final amount = Amount.fromDecimal( + sendAmount, + fractionDigits: coin.fractionDigits, + ); + final address = trade.payInAddress; - Navigator.of(context).pushNamed( - SendFromView.routeName, - arguments: Tuple4( - coin, - amount, - address, - trade, - ), - ); - }, - ), - const SizedBox( - height: 32, + Navigator.of(context).pushNamed( + SendFromView.routeName, + arguments: Tuple4(coin, amount, address, trade), + ); + }, + ), + const SizedBox(height: 32), + ], ), - ], + ), + ), + otherBranchBuilder: + (children) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, + children: children, ), - ), - ), - otherBranchBuilder: (children) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, - children: children, - ), children: [ RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), child: Container( - decoration: isDesktop - ? BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, + decoration: + isDesktop + ? BoxDecoration( + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - ) - : null, + ) + : null, child: Padding( - padding: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -343,9 +346,7 @@ class _TradeDetailsViewState extends ConsumerState { width: 32, height: 32, ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SelectableText( "Swap service", style: STextStyles.desktopTextMedium(context), @@ -353,25 +354,24 @@ class _TradeDetailsViewState extends ConsumerState { ], ), Column( - crossAxisAlignment: isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, children: [ SelectableText( "${trade.payInCurrency.toUpperCase()} → ${trade.payOutCurrency.toUpperCase()}", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Builder( builder: (context) { String text; try { final coin = AppConfig.getCryptoCurrencyForTicker( - trade.payInCurrency, - )!; + trade.payInCurrency, + )!; final amount = sendAmount.toAmount( fractionDigits: coin.fractionDigits, ); @@ -419,15 +419,12 @@ class _TradeDetailsViewState extends ConsumerState { ), ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -435,10 +432,7 @@ class _TradeDetailsViewState extends ConsumerState { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Status", - style: STextStyles.itemSubtitle(context), - ), + Text("Status", style: STextStyles.itemSubtitle(context)), if (trade.exchangeName == MajesticBankExchange.exchangeName && trade.status == "Completed") @@ -449,137 +443,136 @@ class _TradeDetailsViewState extends ConsumerState { onTap: () { showDialog( context: context, - builder: (context) => const StackOkDialog( - title: "Trade Info", - message: - "Majestic Bank does not store order data indefinitely", - ), + builder: + (context) => const StackOkDialog( + title: "Trade Info", + message: + "Majestic Bank does not store order data indefinitely", + ), ); }, child: SvgPicture.asset( Assets.svg.circleInfo, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, ), ), ], ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( trade.status, style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .colorForStatus(trade.status), + color: Theme.of( + context, + ).extension()!.colorForStatus(trade.status), ), ), ], ), ), if (!sentFromStack && !hasTx) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), if (!sentFromStack && !hasTx) RoundedContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: isDesktop - ? Theme.of(context).extension()!.popupBG - : Theme.of(context) - .extension()! - .warningBackground, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + isDesktop + ? Theme.of(context).extension()!.popupBG + : Theme.of( + context, + ).extension()!.warningBackground, child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + builder: + (child) => Column( + mainAxisSize: MainAxisSize.min, children: [ - Column( + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Amount", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - const SizedBox( - height: 2, - ), - Text( - "${trade.payInAmount} ${trade.payInCurrency.toUpperCase()}", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Amount", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 2), + Text( + "${trade.payInAmount} ${trade.payInCurrency.toUpperCase()}", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ), + ), + ], ), + IconCopyButton(data: trade.payInAmount), ], ), - IconCopyButton( - data: trade.payInAmount, - ), + const SizedBox(height: 6), + child, ], ), - const SizedBox( - height: 6, - ), - child, - ], - ), 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()! - .accentColorRed, - ) - : STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, - ), + "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()!.accentColorRed, + ) + : STextStyles.label(context).copyWith( + color: + Theme.of(context) + .extension()! + .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()! - .accentColorRed, - ) - : STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, - ), + "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()! + .accentColorRed, + ) + : STextStyles.label(context).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, + ), ), ], ), @@ -587,39 +580,30 @@ class _TradeDetailsViewState extends ConsumerState { ), ), if (sentFromStack) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), if (sentFromStack) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Sent from", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 4, - ), + Text("Sent from", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 4), SelectableText( widget.walletName!, style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), CustomTextButton( text: "View transaction", onTap: () { - final coin = AppConfig.getCryptoCurrencyForTicker( - trade.payInCurrency, - )!; + final coin = + AppConfig.getCryptoCurrencyForTicker( + trade.payInCurrency, + )!; if (isDesktop) { Navigator.of(context).push( @@ -655,16 +639,13 @@ class _TradeDetailsViewState extends ConsumerState { ), ), if (sentFromStack) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), if (sentFromStack) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -677,9 +658,7 @@ class _TradeDetailsViewState extends ConsumerState { "${trade.exchangeName} address", style: STextStyles.itemSubtitle(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Row( children: [ Flexible( @@ -693,24 +672,18 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - if (isDesktop) - IconCopyButton( - data: trade.payInAddress, - ), + if (isDesktop) IconCopyButton(data: trade.payInAddress), ], ), ), if (!sentFromStack && !hasTx) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), if (!sentFromStack && !hasTx) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -722,52 +695,45 @@ class _TradeDetailsViewState extends ConsumerState { style: STextStyles.itemSubtitle(context), ), isDesktop - ? IconCopyButton( - data: trade.payInAddress, - ) + ? IconCopyButton(data: trade.payInAddress) : GestureDetector( - onTap: () async { - final address = trade.payInAddress; - await Clipboard.setData( - ClipboardData( - text: address, + onTap: () async { + final address = trade.payInAddress; + await Clipboard.setData( + ClipboardData(text: address), + ); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + context: context, ), ); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - width: 12, - height: 12, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], - ), + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 12, + height: 12, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], ), + ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Row( children: [ Expanded( @@ -778,9 +744,7 @@ class _TradeDetailsViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), GestureDetector( onTap: () { showDialog( @@ -799,9 +763,7 @@ class _TradeDetailsViewState extends ConsumerState { style: STextStyles.pageTitleH2(context), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: RepaintBoundary( // key: _qrKey, @@ -815,9 +777,7 @@ class _TradeDetailsViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: SizedBox( width: width, @@ -833,11 +793,13 @@ class _TradeDetailsViewState extends ConsumerState { ), child: Text( "Cancel", - style: STextStyles.button(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -855,13 +817,12 @@ class _TradeDetailsViewState extends ConsumerState { Assets.svg.qrcode, width: 12, height: 12, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, ), + const SizedBox(width: 4), Text( "Show QR code", style: STextStyles.link2(context), @@ -872,73 +833,60 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx) RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Memo", - style: STextStyles.itemSubtitle(context), - ), + Text("Memo", style: STextStyles.itemSubtitle(context)), isDesktop - ? IconCopyButton( - data: trade.payInExtraId, - ) + ? IconCopyButton(data: trade.payInExtraId) : GestureDetector( - onTap: () async { - final address = trade.payInExtraId; - await Clipboard.setData( - ClipboardData( - text: address, + onTap: () async { + final address = trade.payInExtraId; + await Clipboard.setData( + ClipboardData(text: address), + ); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + context: context, ), ); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - width: 12, - height: 12, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], - ), + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 12, + height: 12, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], ), + ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( trade.payInExtraId, style: STextStyles.itemSubtitle12(context), @@ -947,15 +895,12 @@ class _TradeDetailsViewState extends ConsumerState { ), ), if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -968,6 +913,86 @@ class _TradeDetailsViewState extends ConsumerState { ), isDesktop ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditTradeNoteView( + tradeId: tradeId, + note: ref + .read(tradeNoteServiceProvider) + .getNote(tradeId: tradeId), + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditTradeNoteView.routeName, + arguments: Tuple2( + tradeId, + ref + .read(tradeNoteServiceProvider) + .getNote(tradeId: tradeId), + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, + ), + const SizedBox(width: 4), + Text("Edit", style: STextStyles.link2(context)), + ], + ), + ), + ], + ), + const SizedBox(height: 4), + SelectableText( + ref.watch( + tradeNoteServiceProvider.select( + (value) => value.getNote(tradeId: tradeId), + ), + ), + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + if (sentFromStack) + isDesktop ? const _Divider() : const SizedBox(height: 12), + if (sentFromStack) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction note", + style: STextStyles.itemSubtitle(context), + ), + isDesktop + ? IconPencilButton( onPressed: () { showDialog( context: context, @@ -975,26 +1000,22 @@ class _TradeDetailsViewState extends ConsumerState { return DesktopDialog( maxWidth: 580, maxHeight: 360, - child: EditTradeNoteView( - tradeId: tradeId, - note: ref - .read(tradeNoteServiceProvider) - .getNote(tradeId: tradeId), + child: EditNoteView( + txid: transactionIfSentFromStack!.txid, + walletId: walletId!, ), ); }, ); }, ) - : GestureDetector( + : GestureDetector( onTap: () { Navigator.of(context).pushNamed( - EditTradeNoteView.routeName, + EditNoteView.routeName, arguments: Tuple2( - tradeId, - ref - .read(tradeNoteServiceProvider) - .getNote(tradeId: tradeId), + transactionIfSentFromStack!.txid, + walletId, ), ); }, @@ -1004,13 +1025,12 @@ class _TradeDetailsViewState extends ConsumerState { Assets.svg.pencil, width: 10, height: 10, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, + color: + Theme.of(context) + .extension()! + .infoItemIcons, ), + const SizedBox(width: 4), Text( "Edit", style: STextStyles.link2(context), @@ -1018,105 +1038,16 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - ], - ), - const SizedBox( - height: 4, - ), - SelectableText( - ref.watch( - tradeNoteServiceProvider - .select((value) => value.getNote(tradeId: tradeId)), - ), - style: STextStyles.itemSubtitle12(context), - ), - ], - ), - ), - if (sentFromStack) - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), - if (sentFromStack) - RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction note", - style: STextStyles.itemSubtitle(context), - ), - isDesktop - ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: - transactionIfSentFromStack!.txid, - walletId: walletId!, - ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - transactionIfSentFromStack!.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.link2(context), - ), - ], - ), - ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( ref .watch( - pTransactionNote( - ( - txid: transactionIfSentFromStack!.txid, - walletId: walletId!, - ), - ), + pTransactionNote(( + txid: transactionIfSentFromStack!.txid, + walletId: walletId!, + )), ) ?.value ?? "", @@ -1125,15 +1056,12 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -1142,24 +1070,20 @@ class _TradeDetailsViewState extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Date", - style: STextStyles.itemSubtitle(context), - ), - if (isDesktop) - const SizedBox( - height: 2, - ), + Text("Date", style: STextStyles.itemSubtitle(context)), + if (isDesktop) const SizedBox(height: 2), if (isDesktop) SelectableText( Format.extractDateFrom( trade.timestamp.millisecondsSinceEpoch ~/ 1000, ), - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -1180,15 +1104,12 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -1200,10 +1121,7 @@ class _TradeDetailsViewState extends ConsumerState { "Swap service", style: STextStyles.itemSubtitle(context), ), - if (isDesktop) - const SizedBox( - height: 2, - ), + if (isDesktop) const SizedBox(height: 2), if (isDesktop) SelectableText( trade.exchangeName, @@ -1211,10 +1129,7 @@ class _TradeDetailsViewState extends ConsumerState { ), ], ), - if (isDesktop) - IconCopyButton( - data: trade.exchangeName, - ), + if (isDesktop) IconCopyButton(data: trade.exchangeName), if (!isDesktop) SelectableText( trade.exchangeName, @@ -1223,15 +1138,12 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -1243,10 +1155,7 @@ class _TradeDetailsViewState extends ConsumerState { "Trade ID", style: STextStyles.itemSubtitle(context), ), - if (isDesktop) - const SizedBox( - height: 2, - ), + if (isDesktop) const SizedBox(height: 2), if (isDesktop) Text( trade.tradeId, @@ -1254,10 +1163,7 @@ class _TradeDetailsViewState extends ConsumerState { ), ], ), - if (isDesktop) - IconCopyButton( - data: trade.tradeId, - ), + if (isDesktop) IconCopyButton(data: trade.tradeId), if (!isDesktop) Row( children: [ @@ -1265,9 +1171,7 @@ class _TradeDetailsViewState extends ConsumerState { trade.tradeId, style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), GestureDetector( onTap: () async { final data = ClipboardData(text: trade.tradeId); @@ -1284,9 +1188,10 @@ class _TradeDetailsViewState extends ConsumerState { }, child: SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, width: 12, ), ), @@ -1295,25 +1200,17 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop - ? const _Divider() - : const SizedBox( - height: 12, - ), + isDesktop ? const _Divider() : const SizedBox(height: 12), RoundedWhiteContainer( - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Tracking", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 4, - ), + Text("Tracking", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 4), Builder( builder: (context) { late final String url; @@ -1336,18 +1233,20 @@ class _TradeDetailsViewState extends ConsumerState { break; default: - if (trade.exchangeName - .startsWith(TrocadorExchange.exchangeName)) { + if (trade.exchangeName.startsWith( + TrocadorExchange.exchangeName, + )) { url = "https://trocador.app/en/checkout/${trade.tradeId}"; } } return ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => MouseRegion( + cursor: SystemMouseCursors.click, + child: child, + ), child: GestureDetector( onTap: () { launchUrl( @@ -1355,10 +1254,7 @@ class _TradeDetailsViewState extends ConsumerState { mode: LaunchMode.externalApplication, ); }, - child: Text( - url, - style: STextStyles.link2(context), - ), + child: Text(url, style: STextStyles.link2(context)), ), ); }, @@ -1366,19 +1262,17 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), if (!isDesktop && showSendFromStackButton) SecondaryButton( label: "Send from ${AppConfig.prefix}", onPressed: () { CryptoCurrency coin; try { - coin = AppConfig.getCryptoCurrencyForTicker( - trade.payInCurrency, - )!; + coin = + AppConfig.getCryptoCurrencyForTicker( + trade.payInCurrency, + )!; } catch (_) { coin = AppConfig.getCryptoCurrencyByPrettyName( trade.payInCurrency, @@ -1392,12 +1286,7 @@ class _TradeDetailsViewState extends ConsumerState { Navigator.of(context).pushNamed( SendFromView.routeName, - arguments: Tuple4( - coin, - amount, - address, - trade, - ), + arguments: Tuple4(coin, amount, address, trade), ); }, ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index b6e872bd4..679ccc84c 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -141,10 +141,13 @@ abstract class SWB { if (!backupFile.existsSync()) { final String jsonBackup = plaintext; final Uint8List content = Uint8List.fromList(utf8.encode(jsonBackup)); - final Uint8List encryptedContent = - await encryptWithPassphrase(passphrase, content); - backupFile - .writeAsStringSync(Format.uint8listToString(encryptedContent)); + final Uint8List encryptedContent = await encryptWithPassphrase( + passphrase, + content, + ); + backupFile.writeAsStringSync( + Format.uint8listToString(encryptedContent), + ); } Logging.instance.d(backupFile.absolute); return true; @@ -170,8 +173,9 @@ abstract class SWB { content, version: adkVersion, ); - backupFile - .writeAsStringSync(Format.uint8listToString(encryptedContent)); + backupFile.writeAsStringSync( + Format.uint8listToString(encryptedContent), + ); } Logging.instance.d(backupFile.absolute); return true; @@ -207,8 +211,10 @@ abstract class SWB { final encryptedBytes = Format.stringToUint8List(encryptedText); - final decryptedContent = - await decryptWithPassphrase(passphrase, encryptedBytes); + final decryptedContent = await decryptWithPassphrase( + passphrase, + encryptedBytes, + ); final jsonBackup = utf8.decode(decryptedContent); return jsonBackup; @@ -225,50 +231,41 @@ abstract class SWB { Logging.instance.d("Starting createStackWalletJSON..."); final _wallets = Wallets.sharedInstance; final Map backupJson = {}; - final NodeService nodeService = - NodeService(secureStorageInterface: secureStorage); + final NodeService nodeService = NodeService( + secureStorageInterface: secureStorage, + ); final _secureStore = secureStorage; - Logging.instance.d( - "createStackWalletJSON awaiting DB.instance.mutex...", - ); + Logging.instance.d("createStackWalletJSON awaiting DB.instance.mutex..."); // prevent modification of data await DB.instance.mutex.protect(() async { - Logging.instance.i( - "...createStackWalletJSON DB.instance.mutex acquired", - ); - Logging.instance.i( - "SWB backing up nodes", - ); + Logging.instance.i("...createStackWalletJSON DB.instance.mutex acquired"); + Logging.instance.i("SWB backing up nodes"); try { - final primaryNodes = nodeService.primaryNodes.map((e) async { - final map = e.toMap(); - map["password"] = await e.getPassword(_secureStore); - return map; - }).toList(); + final primaryNodes = + nodeService.primaryNodes.map((e) async { + final map = e.toMap(); + map["password"] = await e.getPassword(_secureStore); + return map; + }).toList(); backupJson['primaryNodes'] = await Future.wait(primaryNodes); } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); } try { - final nodesFuture = nodeService.nodes.map((e) async { - final map = e.toMap(); - map["password"] = await e.getPassword(_secureStore); - return map; - }).toList(); + final nodesFuture = + nodeService.nodes.map((e) async { + final map = e.toMap(); + map["password"] = await e.getPassword(_secureStore); + return map; + }).toList(); final nodes = await Future.wait(nodesFuture); backupJson['nodes'] = nodes; } catch (e, s) { Logging.instance.e("", error: e, stackTrace: s); } - Logging.instance.d( - "SWB backing up prefs", - ); + Logging.instance.d("SWB backing up prefs"); final Map prefs = {}; final _prefs = Prefs.instance; @@ -289,18 +286,14 @@ abstract class SWB { backupJson['prefs'] = prefs; - Logging.instance.d( - "SWB backing up addressbook", - ); + Logging.instance.d("SWB backing up addressbook"); final AddressBookService addressBookService = AddressBookService(); final addresses = addressBookService.contacts; backupJson['addressBookEntries'] = addresses.map((e) => e.toMap()).toList(); - Logging.instance.d( - "SWB backing up wallets", - ); + Logging.instance.d("SWB backing up wallets"); final List backupWallets = []; for (final wallet in _wallets.wallets) { @@ -349,14 +342,15 @@ abstract class SWB { backupWallet['restoreHeight'] = wallet.info.restoreHeight; - final isarNotes = await MainDB.instance.isar.transactionNotes - .where() - .walletIdEqualTo(wallet.walletId) - .findAll(); + final isarNotes = + await MainDB.instance.isar.transactionNotes + .where() + .walletIdEqualTo(wallet.walletId) + .findAll(); - final notes = isarNotes - .asMap() - .map((key, value) => MapEntry(value.txid, value.value)); + final notes = isarNotes.asMap().map( + (key, value) => MapEntry(value.txid, value.value), + ); backupWallet['notes'] = notes; @@ -364,14 +358,13 @@ abstract class SWB { } backupJson['wallets'] = backupWallets; - Logging.instance.d( - "SWB backing up trades", - ); + Logging.instance.d("SWB backing up trades"); // back up trade history final tradesService = TradesService(); - final trades = - tradesService.trades.map((e) => e.toMap()).toList(growable: false); + final trades = tradesService.trades + .map((e) => e.toMap()) + .toList(growable: false); backupJson["tradeHistory"] = trades; // back up trade history lookup data for trades send from stack wallet @@ -380,18 +373,14 @@ abstract class SWB { tradeTxidLookupDataService.all.map((e) => e.toMap()).toList(); backupJson["tradeTxidLookupData"] = lookupData; - Logging.instance.d( - "SWB backing up trade notes", - ); + Logging.instance.d("SWB backing up trade notes"); // back up trade notes final tradeNotesService = TradeNotesService(); final tradeNotes = tradeNotesService.all; backupJson["tradeNotes"] = tradeNotes; }); - Logging.instance.d( - "createStackWalletJSON DB.instance.mutex released", - ); + Logging.instance.d("createStackWalletJSON DB.instance.mutex released"); // // back up notifications data // final notificationsService = NotificationsService(); @@ -473,9 +462,7 @@ abstract class SWB { knownSalts: [], participants: participants, myName: myName, - threshold: frost.multisigThreshold( - multisigConfig: multisigConfig, - ), + threshold: frost.multisigThreshold(multisigConfig: multisigConfig), ); await MainDB.instance.isar.writeTxn(() async { @@ -507,7 +494,7 @@ abstract class SWB { case const (WowneroWallet): await (wallet as WowneroWallet).init(isRestore: true); break; - + case const (XelisWallet): await (wallet as XelisWallet).init(isRestore: true); break; @@ -547,8 +534,9 @@ abstract class SWB { } // restore notes - final notesMap = - Map.from(walletbackup["notes"] as Map? ?? {}); + final notesMap = Map.from( + walletbackup["notes"] as Map? ?? {}, + ); final List notes = []; for (final key in notesMap.keys) { @@ -601,11 +589,7 @@ abstract class SWB { mnemonicPassphrase: mnemonicPassphrase, ); } catch (e, s) { - Logging.instance.i( - "", - error: e, - stackTrace: s, - ); + Logging.instance.i("", error: e, stackTrace: s); uiState?.update( walletId: info.walletId, restoringStatus: StackRestoringStatus.failed, @@ -639,17 +623,13 @@ abstract class SWB { uiState?.preferences = StackRestoringStatus.restoring; - Logging.instance.d( - "SWB restoring prefs", - ); + Logging.instance.d("SWB restoring prefs"); await _restorePrefs(prefs); uiState?.preferences = StackRestoringStatus.success; uiState?.addressBook = StackRestoringStatus.restoring; - Logging.instance.d( - "SWB restoring addressbook", - ); + Logging.instance.d("SWB restoring addressbook"); if (addressBookEntries != null) { await _restoreAddressBook(addressBookEntries); } @@ -657,40 +637,28 @@ abstract class SWB { uiState?.addressBook = StackRestoringStatus.success; uiState?.nodes = StackRestoringStatus.restoring; - Logging.instance.d( - "SWB restoring nodes", - ); - await _restoreNodes( - nodes, - primaryNodes, - secureStorageInterface, - ); + Logging.instance.d("SWB restoring nodes"); + await _restoreNodes(nodes, primaryNodes, secureStorageInterface); uiState?.nodes = StackRestoringStatus.success; uiState?.trades = StackRestoringStatus.restoring; // restore trade history if (trades != null) { - Logging.instance.d( - "SWB restoring trades", - ); + Logging.instance.d("SWB restoring trades"); await _restoreTrades(trades); } // restore trade history lookup data for trades send from stack wallet if (tradeTxidLookupData != null) { - Logging.instance.d( - "SWB restoring trade look up data", - ); + Logging.instance.d("SWB restoring trade look up data"); await _restoreTradesLookUpData(tradeTxidLookupData, oldToNewWalletIdMap); } // restore trade notes if (tradeNotes != null) { - Logging.instance.d( - "SWB restoring trade notes", - ); + Logging.instance.d("SWB restoring trade notes"); await _restoreTradesNotes(tradeNotes); } @@ -722,22 +690,22 @@ abstract class SWB { ) async { if (!Platform.isLinux) await WakelockPlus.enable(); - Logging.instance.d( - "SWB creating temp backup", - ); - final preRestoreJSON = - await createStackWalletJSON(secureStorage: secureStorageInterface); - Logging.instance.d( - "SWB temp backup created", + Logging.instance.d("SWB creating temp backup"); + final preRestoreJSON = await createStackWalletJSON( + secureStorage: secureStorageInterface, ); + Logging.instance.d("SWB temp backup created"); - final List _currentWalletIds = await MainDB.instance.isar.walletInfo - .where() - .walletIdProperty() - .findAll(); + final List _currentWalletIds = + await MainDB.instance.isar.walletInfo + .where() + .walletIdProperty() + .findAll(); - final preRestoreState = - PreRestoreState(_currentWalletIds.toSet(), preRestoreJSON); + final preRestoreState = PreRestoreState( + _currentWalletIds.toSet(), + preRestoreJSON, + ); final Map oldToNewWalletIdMap = {}; @@ -759,10 +727,7 @@ abstract class SWB { // basic cancel check here // no reverting required yet as nothing has been written to store - if (_checkShouldCancel( - null, - secureStorageInterface, - )) { + if (_checkShouldCancel(null, secureStorageInterface)) { return false; } @@ -774,10 +739,7 @@ abstract class SWB { ); // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } @@ -794,10 +756,7 @@ abstract class SWB { for (final walletbackup in wallets) { // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } @@ -818,8 +777,9 @@ abstract class SWB { Map? otherData; try { if (walletbackup["otherDataJsonString"] is String) { - final data = - jsonDecode(walletbackup["otherDataJsonString"] as String); + final data = jsonDecode( + walletbackup["otherDataJsonString"] as String, + ); otherData = Map.from(data as Map); } } catch (e, s) { @@ -859,19 +819,13 @@ abstract class SWB { // final failovers = nodeService.failoverNodesFor(coin: coin); // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } managers.add(Tuple2(walletbackup, info)); // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } @@ -884,10 +838,7 @@ abstract class SWB { } // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } @@ -898,10 +849,7 @@ abstract class SWB { // start restoring wallets for (final tuple in managers) { // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } final bools = await _asyncRestore( @@ -915,19 +863,13 @@ abstract class SWB { } // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } for (final Future status in restoreStatuses) { // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } await status; @@ -935,19 +877,17 @@ abstract class SWB { if (!Platform.isLinux) await WakelockPlus.disable(); // check if cancel was requested and restore previous state - if (_checkShouldCancel( - preRestoreState, - secureStorageInterface, - )) { + if (_checkShouldCancel(preRestoreState, secureStorageInterface)) { return false; } - Logging.instance.d( - "done with SWB restore", - ); + Logging.instance.d("done with SWB restore"); - await Wallets.sharedInstance - .loadAfterStackRestore(_prefs, uiState?.wallets ?? [], Util.isDesktop); + await Wallets.sharedInstance.loadAfterStackRestore( + _prefs, + uiState?.wallets ?? [], + Util.isDesktop, + ); return true; } @@ -998,11 +938,12 @@ abstract class SWB { // ensure this contact's data matches the pre restore state final List addresses = []; for (final address in (contact['addresses'] as List)) { - final entry = ContactAddressEntry() - ..coinName = address['coin'] as String - ..address = address['address'] as String - ..label = address['label'] as String - ..other = address['other'] as String?; + final entry = + ContactAddressEntry() + ..coinName = address['coin'] as String + ..address = address['address'] as String + ..label = address['label'] as String + ..other = address['other'] as String?; try { entry.coin; @@ -1011,9 +952,7 @@ abstract class SWB { continue; } - addresses.add( - entry, - ); + addresses.add(entry); } await addressBookService.editContact( ContactEntry( @@ -1174,22 +1113,22 @@ abstract class SWB { } // finally remove any added wallets - final allWalletIds = (await MainDB.instance.isar.walletInfo - .where() - .walletIdProperty() - .findAll()) - .toSet(); + final allWalletIds = + (await MainDB.instance.isar.walletInfo + .where() + .walletIdProperty() + .findAll()) + .toSet(); final walletIdsToDelete = allWalletIds.difference(revertToState.walletIds); await MainDB.instance.isar.writeTxn(() async { - await MainDB.instance.isar.walletInfo - .deleteAllByWalletId(walletIdsToDelete.toList()); + await MainDB.instance.isar.walletInfo.deleteAllByWalletId( + walletIdsToDelete.toList(), + ); }); _cancelCompleter!.complete(); _shouldCancelRestore = false; - Logging.instance.d( - "Revert SWB complete", - ); + Logging.instance.d("Revert SWB complete"); } static Future _restorePrefs(Map prefs) async { @@ -1201,9 +1140,10 @@ abstract class SWB { _prefs.language = prefs['language'] as String; _prefs.showFavoriteWallets = prefs['showFavoriteWallets'] as bool; _prefs.wifiOnly = prefs['wifiOnly'] as bool; - _prefs.syncType = prefs['syncType'] == "currentWalletOnly" - ? SyncingType.currentWalletOnly - : prefs['syncType'] == "selectedWalletsAtStartup" + _prefs.syncType = + prefs['syncType'] == "currentWalletOnly" + ? SyncingType.currentWalletOnly + : prefs['syncType'] == "selectedWalletsAtStartup" ? SyncingType.currentWalletOnly : SyncingType.allWalletsOnStartup; // _prefs.walletIdsSyncOnStartup = @@ -1217,8 +1157,9 @@ abstract class SWB { (e) => e.name == (prefs['backupFrequencyType'] as String?), orElse: () => BackupFrequencyType.everyAppStart, ); - _prefs.lastAutoBackup = - DateTime.tryParse(prefs['lastAutoBackup'] as String? ?? ""); + _prefs.lastAutoBackup = DateTime.tryParse( + prefs['lastAutoBackup'] as String? ?? "", + ); } static Future _restoreAddressBook( @@ -1228,11 +1169,12 @@ abstract class SWB { for (final contact in addressBookEntries) { final List addresses = []; for (final address in (contact['addresses'] as List)) { - final entry = ContactAddressEntry() - ..coinName = address['coin'] as String - ..address = address['address'] as String - ..label = address['label'] as String - ..other = address['other'] as String?; + final entry = + ContactAddressEntry() + ..coinName = address['coin'] as String + ..address = address['address'] as String + ..label = address['label'] as String + ..other = address['other'] as String?; try { entry.coin; @@ -1241,9 +1183,7 @@ abstract class SWB { continue; } - addresses.add( - entry, - ); + addresses.add(entry); } if (addresses.isNotEmpty) { await addressBookService.addContact( @@ -1313,53 +1253,35 @@ abstract class SWB { await nodeService.updateDefaults(); } - static Future _restoreTrades( - List trades, - ) async { - final tradesService = TradesService(); - for (int i = 0; i < trades.length - 1; i++) { - ExchangeTransaction? exTx; - try { - exTx = ExchangeTransaction.fromJson(trades[i] as Map); - } catch (e) { - // unneeded log - // Logging.instance.log("$e\n$s", error: e, stackTrace: s,); - } - - Trade trade; - if (exTx != null) { - trade = Trade.fromExchangeTransaction(exTx, false); - } else { - trade = Trade.fromMap(trades[i] as Map); - } - - await tradesService.add( - trade: trade, - shouldNotifyListeners: false, - ); - } - // only call notifyListeners on last one added + static Future _restoreTrades(List trades) async { if (trades.isNotEmpty) { - ExchangeTransaction? exTx; - try { - exTx = - ExchangeTransaction.fromJson(trades.last as Map); - } catch (e) { - // unneeded log - // Logging.instance.log("$e\n$s", level: LogLevel.Warning); - } + final tradesService = TradesService(); + for (int i = 0; i < trades.length; i++) { + // First check for old old database entries + ExchangeTransaction? exTx; + try { + exTx = ExchangeTransaction.fromJson( + trades[i] as Map, + ); + } catch (e) { + // unneeded log + // Logging.instance.log("$e\n$s", error: e, stackTrace: s,); + } - Trade trade; - if (exTx != null) { - trade = Trade.fromExchangeTransaction(exTx, false); - } else { - trade = Trade.fromMap(trades.last as Map); - } + Trade trade; + if (exTx != null) { + trade = Trade.fromExchangeTransaction(exTx, false); + } else { + trade = Trade.fromMap(trades[i] as Map); + } - await tradesService.add( - trade: trade, - shouldNotifyListeners: true, - ); + await tradesService.add( + trade: trade, + shouldNotifyListeners: + i == + trades.length - 1, // only call notifyListeners on last one added + ); + } } } diff --git a/lib/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart b/lib/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart index c487ff991..d2a053d74 100644 --- a/lib/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart +++ b/lib/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart @@ -19,7 +19,7 @@ import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; import '../../db/isar/main_db.dart'; -import '../../models/exchange/change_now/exchange_transaction_status.dart'; +import '../../models/exchange/change_now/cn_exchange_transaction_status.dart'; import '../../models/exchange/response_objects/trade.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/isar/stack_theme.dart'; @@ -104,41 +104,32 @@ class _DesktopAllTradesViewState extends ConsumerState { background: Theme.of(context).extension()!.popupBG, leading: Row( children: [ - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), AppBarIconButton( size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: Navigator.of(context).pop, ), - const SizedBox( - width: 12, - ), - Text( - "Trades", - style: STextStyles.desktopH3(context), - ), + const SizedBox(width: 12), + Text("Trades", style: STextStyles.desktopH3(context)), ], ), ), body: Padding( - padding: const EdgeInsets.only( - left: 20, - top: 20, - right: 20, - ), + padding: const EdgeInsets.only(left: 20, top: 20, right: 20), child: Column( children: [ Row( @@ -159,11 +150,13 @@ class _DesktopAllTradesViewState extends ConsumerState { _searchString = value; }); }, - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -183,35 +176,34 @@ class _DesktopAllTradesViewState extends ConsumerState { height: 20, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: Consumer( builder: (_, ref, __) { @@ -237,38 +229,36 @@ class _DesktopAllTradesViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (index != 0) - const SizedBox( - height: 12, - ), + if (index != 0) const SizedBox(height: 12), Text( month.item1, style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: ListView.separated( shrinkWrap: true, primary: false, - separatorBuilder: (context, _) => Container( - height: 1, - color: Theme.of(context) - .extension()! - .background, - ), + separatorBuilder: + (context, _) => Container( + height: 1, + color: + Theme.of(context) + .extension()! + .background, + ), itemCount: month.item2.length, - itemBuilder: (context, index) => Padding( - padding: const EdgeInsets.all(4), - child: DesktopTradeRowCard( - key: Key( - "transactionCard_key_${month.item2[index].tradeId}", + itemBuilder: + (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: DesktopTradeRowCard( + key: Key( + "transactionCard_key_${month.item2[index].tradeId}", + ), + tradeId: month.item2[index].tradeId, + ), ), - tradeId: month.item2[index].tradeId, - ), - ), ), ), ], @@ -287,10 +277,7 @@ class _DesktopAllTradesViewState extends ConsumerState { } class DesktopTradeRowCard extends ConsumerStatefulWidget { - const DesktopTradeRowCard({ - super.key, - required this.tradeId, - }); + const DesktopTradeRowCard({super.key, required this.tradeId}); final String tradeId; @@ -347,8 +334,9 @@ class _DesktopTradeRowCardState extends ConsumerState { @override Widget build(BuildContext context) { - final String? txid = - ref.read(tradeSentFromStackLookupProvider).getTxidForTradeId(tradeId); + final String? txid = ref + .read(tradeSentFromStackLookupProvider) + .getTxidForTradeId(tradeId); final List? walletIds = ref .read(tradeSentFromStackLookupProvider) .getWalletIdsForTradeId(tradeId); @@ -360,8 +348,9 @@ class _DesktopTradeRowCardState extends ConsumerState { color: Theme.of(context).extension()!.popupBG, elevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), child: RawMaterialButton( shape: RoundedRectangleBorder( @@ -374,25 +363,27 @@ class _DesktopTradeRowCardState extends ConsumerState { //todo: check if print needed // debugPrint("name: ${manager.walletName}"); - final tx = await MainDB.instance - .getTransactions(walletIds.first) - .filter() - .txidEqualTo(txid) - .findFirst(); + final tx = + await MainDB.instance + .getTransactions(walletIds.first) + .filter() + .txidEqualTo(txid) + .findFirst(); if (mounted) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: TradeDetailsView( - tradeId: tradeId, - transactionIfSentFromStack: tx, - walletName: ref.read(pWalletName(walletIds.first)), - walletId: walletIds.first, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TradeDetailsView( + tradeId: tradeId, + transactionIfSentFromStack: tx, + walletName: ref.read(pWalletName(walletIds.first)), + walletId: walletIds.first, + ), + ), ); } @@ -400,62 +391,67 @@ class _DesktopTradeRowCardState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => Navigator( - initialRoute: TradeDetailsView.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - FadePageRoute( - DesktopDialog( - maxHeight: null, - maxWidth: 580, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 16, - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Trade details", - style: STextStyles.desktopH3(context), + builder: + (context) => Navigator( + initialRoute: TradeDetailsView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + DesktopDialog( + maxHeight: null, + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + bottom: 16, ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Trade details", + style: STextStyles.desktopH3( + context, + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + ], ), - ], - ), - ), - Flexible( - child: SingleChildScrollView( - primary: false, - child: TradeDetailsView( - tradeId: tradeId, - transactionIfSentFromStack: tx, - walletName: ref - .read(pWalletName(walletIds.first)), - walletId: walletIds.first, ), - ), + Flexible( + child: SingleChildScrollView( + primary: false, + child: TradeDetailsView( + tradeId: tradeId, + transactionIfSentFromStack: tx, + walletName: ref.read( + pWalletName(walletIds.first), + ), + walletId: walletIds.first, + ), + ), + ), + ], ), - ], + ), + const RouteSettings( + name: TradeDetailsView.routeName, + ), ), - ), - const RouteSettings( - name: TradeDetailsView.routeName, - ), - ), - ]; - }, - ), + ]; + }, + ), ), ); } @@ -463,70 +459,69 @@ class _DesktopTradeRowCardState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => Navigator( - initialRoute: TradeDetailsView.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - FadePageRoute( - DesktopDialog( - maxHeight: null, - maxWidth: 580, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 16, - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Trade details", - style: STextStyles.desktopH3(context), + builder: + (context) => Navigator( + initialRoute: TradeDetailsView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + DesktopDialog( + maxHeight: null, + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + bottom: 16, ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Trade details", + style: STextStyles.desktopH3(context), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + ], ), - ], - ), - ), - Flexible( - child: SingleChildScrollView( - primary: false, - child: TradeDetailsView( - tradeId: tradeId, - transactionIfSentFromStack: null, - walletName: null, - walletId: walletIds?.first, ), - ), + Flexible( + child: SingleChildScrollView( + primary: false, + child: TradeDetailsView( + tradeId: tradeId, + transactionIfSentFromStack: null, + walletName: null, + walletId: walletIds?.first, + ), + ), + ), + ], ), - ], + ), + const RouteSettings( + name: TradeDetailsView.routeName, + ), ), - ), - const RouteSettings( - name: TradeDetailsView.routeName, - ), - ), - ]; - }, - ), + ]; + }, + ), ), ); } }, child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row( children: [ Container( @@ -540,9 +535,7 @@ class _DesktopTradeRowCardState extends ConsumerState { File( _fetchIconAssetForStatus( trade.status, - ref.watch( - themeAssetsProvider, - ), + ref.watch(themeAssetsProvider), ), ), width: 32, @@ -550,15 +543,14 @@ class _DesktopTradeRowCardState extends ConsumerState { ), ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( flex: 3, child: Text( "${trade.payInCurrency.toUpperCase()} → ${trade.payOutCurrency.toUpperCase()}", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark, ), ), @@ -576,8 +568,9 @@ class _DesktopTradeRowCardState extends ConsumerState { flex: 6, child: Text( "-${Decimal.tryParse(trade.payInAmount)?.toStringAsFixed(8) ?? "..."} ${trade.payInCurrency.toUpperCase()}", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark, ), ), diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart index c6769e68a..3fe2b20d7 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart @@ -47,14 +47,11 @@ final ssss = StateProvider((_) => null); final desktopExchangeModelProvider = ChangeNotifierProvider( - (ref) => ref.watch(ssss.state).state, -); + (ref) => ref.watch(ssss.state).state, + ); class StepScaffold extends ConsumerStatefulWidget { - const StepScaffold({ - super.key, - required this.initialStep, - }); + const StepScaffold({super.key, required this.initialStep}); final int initialStep; @@ -79,19 +76,19 @@ class _StepScaffoldState extends ConsumerState { showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: const CustomLoadingOverlay( - message: "Creating a trade", - eventBus: null, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.6), + child: const CustomLoadingOverlay( + message: "Creating a trade", + eventBus: null, + ), + ), ), - ), - ), ), ); @@ -99,12 +96,16 @@ class _StepScaffoldState extends ConsumerState { .read(efExchangeProvider) .createTrade( from: ref.read(desktopExchangeModelProvider)!.sendTicker, + fromNetwork: ref.read(desktopExchangeModelProvider)!.sendNetwork, to: ref.read(desktopExchangeModelProvider)!.receiveTicker, - fixedRate: ref.read(desktopExchangeModelProvider)!.rateType != + toNetwork: ref.read(desktopExchangeModelProvider)!.receiveNetwork, + fixedRate: + ref.read(desktopExchangeModelProvider)!.rateType != ExchangeRateType.estimated, - amount: ref.read(desktopExchangeModelProvider)!.reversed - ? ref.read(desktopExchangeModelProvider)!.receiveAmount - : ref.read(desktopExchangeModelProvider)!.sendAmount, + amount: + ref.read(desktopExchangeModelProvider)!.reversed + ? ref.read(desktopExchangeModelProvider)!.receiveAmount + : ref.read(desktopExchangeModelProvider)!.sendAmount, addressTo: ref.read(desktopExchangeModelProvider)!.recipientAddress!, extraId: null, addressRefund: ref.read(desktopExchangeModelProvider)!.refundAddress!, @@ -131,10 +132,11 @@ class _StepScaffoldState extends ConsumerState { showDialog( context: context, barrierDismissible: true, - builder: (_) => SimpleDesktopDialog( - title: "Failed to create trade", - message: message ?? "", - ), + builder: + (_) => SimpleDesktopDialog( + title: "Failed to create trade", + message: message ?? "", + ), ), ); } @@ -142,10 +144,9 @@ class _StepScaffoldState extends ConsumerState { } // save trade to hive - await ref.read(tradesServiceProvider).add( - trade: response.value!, - shouldNotifyListeners: true, - ); + await ref + .read(tradesServiceProvider) + .add(trade: response.value!, shouldNotifyListeners: true); String status = response.value!.status; @@ -206,35 +207,35 @@ class _StepScaffoldState extends ConsumerState { void sendFromStack() { final trade = ref.read(desktopExchangeModelProvider)!.trade!; final address = trade.payInAddress; - final coin = AppConfig.getCryptoCurrencyForTicker(trade.payInCurrency) ?? + final coin = + AppConfig.getCryptoCurrencyForTicker(trade.payInCurrency) ?? AppConfig.getCryptoCurrencyByPrettyName(trade.payInCurrency); - final amount = Decimal.parse(trade.payInAmount).toAmount( - fractionDigits: coin.fractionDigits, - ); + final amount = Decimal.parse( + trade.payInAmount, + ).toAmount(fractionDigits: coin.fractionDigits); showDialog( context: context, - builder: (context) => Navigator( - initialRoute: SendFromView.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - FadePageRoute( - SendFromView( - coin: coin, - trade: trade, - amount: amount, - address: address, - shouldPopRoot: true, - fromDesktopStep4: true, - ), - const RouteSettings( - name: SendFromView.routeName, - ), - ), - ]; - }, - ), + builder: + (context) => Navigator( + initialRoute: SendFromView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + SendFromView( + coin: coin, + trade: trade, + amount: amount, + address: address, + shouldPopRoot: true, + fromDesktopStep4: true, + ), + const RouteSettings(name: SendFromView.routeName), + ), + ]; + }, + ), ); } @@ -258,13 +259,11 @@ class _StepScaffoldState extends ConsumerState { children: [ currentStep != 4 ? AppBarBackButton( - isCompact: true, - iconSize: 23, - onPressed: onBack, - ) - : const SizedBox( - width: 32, - ), + isCompact: true, + iconSize: 23, + onPressed: onBack, + ) + : const SizedBox(width: 32), Text( "Exchange ${model?.sendTicker.toUpperCase()} to ${model?.receiveTicker.toUpperCase()}", style: STextStyles.desktopH3(context), @@ -279,31 +278,19 @@ class _StepScaffoldState extends ConsumerState { ), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), - child: DesktopExchangeStepsIndicator( - currentStep: currentStep, - ), - ), - const SizedBox( - height: 32, + padding: const EdgeInsets.symmetric(horizontal: 32), + child: DesktopExchangeStepsIndicator(currentStep: currentStep), ), + const SizedBox(height: 32), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: FadeStack( index: currentStep - 1, children: [ const DesktopStep1(), - DesktopStep2( - enableNextChanged: updateEnableNext, - ), + DesktopStep2(enableNextChanged: updateEnableNext), const DesktopStep3(), const DesktopStep4(), ], @@ -321,9 +308,10 @@ class _StepScaffoldState extends ConsumerState { Expanded( child: AnimatedCrossFade( duration: const Duration(milliseconds: 250), - crossFadeState: currentStep == 4 - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, + crossFadeState: + currentStep == 4 + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, firstChild: SecondaryButton( label: "Back", buttonHeight: ButtonHeight.l, @@ -336,20 +324,20 @@ class _StepScaffoldState extends ConsumerState { ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: AnimatedCrossFade( duration: const Duration(milliseconds: 250), - crossFadeState: currentStep == 4 - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, + crossFadeState: + currentStep == 4 + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, firstChild: AnimatedCrossFade( duration: const Duration(milliseconds: 250), - crossFadeState: currentStep == 3 - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, + crossFadeState: + currentStep == 3 + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, firstChild: PrimaryButton( label: "Next", enabled: currentStep != 2 ? true : enableNext, @@ -394,9 +382,7 @@ class _StepScaffoldState extends ConsumerState { "Send ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendAmount.toStringAsFixed(8)))} ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker))} to this address", style: STextStyles.desktopH3(context), ), - const SizedBox( - height: 48, - ), + const SizedBox(height: 48), Center( child: QR( // TODO: grab coin uri scheme from somewhere @@ -409,9 +395,7 @@ class _StepScaffoldState extends ConsumerState { size: 290, ), ), - const SizedBox( - height: 48, - ), + const SizedBox(height: 48), SecondaryButton( label: "Cancel", width: 310, diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart index fd7c72a23..c7ba641ca 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart @@ -59,23 +59,23 @@ class _DesktopStep2State extends ConsumerState { void selectRecipientAddressFromStack() async { try { - final coin = AppConfig.getCryptoCurrencyForTicker( - ref.read(desktopExchangeModelProvider)!.receiveTicker, - )!; + final coin = + AppConfig.getCryptoCurrencyForTicker( + ref.read(desktopExchangeModelProvider)!.receiveTicker, + )!; final info = await showDialog?>( context: context, barrierColor: Colors.transparent, - builder: (context) => DesktopDialog( - maxWidth: 720, - maxHeight: 670, - child: Padding( - padding: const EdgeInsets.all(32), - child: DesktopChooseFromStack( - coin: coin, + builder: + (context) => DesktopDialog( + maxWidth: 720, + maxHeight: 670, + child: Padding( + padding: const EdgeInsets.all(32), + child: DesktopChooseFromStack(coin: coin), + ), ), - ), - ), ); if (info is Tuple2) { @@ -83,44 +83,40 @@ class _DesktopStep2State extends ConsumerState { ref.read(desktopExchangeModelProvider)!.recipientAddress = info.item2; } } catch (e, s) { - Logging.instance.i("$e\n$s", error: e, stackTrace: s,); + Logging.instance.i("$e\n$s", error: e, stackTrace: s); } - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); } void selectRefundAddressFromStack() async { try { - final coin = AppConfig.getCryptoCurrencyForTicker( - ref.read(desktopExchangeModelProvider)!.sendTicker, - )!; + final coin = + AppConfig.getCryptoCurrencyForTicker( + ref.read(desktopExchangeModelProvider)!.sendTicker, + )!; final info = await showDialog?>( context: context, barrierColor: Colors.transparent, - builder: (context) => DesktopDialog( - maxWidth: 720, - maxHeight: 670, - child: Padding( - padding: const EdgeInsets.all(32), - child: DesktopChooseFromStack( - coin: coin, + builder: + (context) => DesktopDialog( + maxWidth: 720, + maxHeight: 670, + child: Padding( + padding: const EdgeInsets.all(32), + child: DesktopChooseFromStack(coin: coin), + ), ), - ), - ), ); if (info is Tuple2) { _refundController.text = info.item1; ref.read(desktopExchangeModelProvider)!.refundAddress = info.item2; } } catch (e, s) { - Logging.instance.i("$e\n$s", error: e, stackTrace: s,); + Logging.instance.i("$e\n$s", error: e, stackTrace: s); } - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); } void selectRecipientFromAddressBook() async { @@ -131,43 +127,36 @@ class _DesktopStep2State extends ConsumerState { final entry = await showDialog( context: context, barrierColor: Colors.transparent, - builder: (context) => DesktopDialog( - maxWidth: 720, - maxHeight: 670, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 720, + maxHeight: 670, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: STextStyles.desktopH3(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Address book", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - const DesktopDialogCloseButton(), + Expanded(child: AddressBookAddressChooser(coin: coin)), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: coin, - ), - ), - ], - ), - ), + ), ); if (entry != null) { _toController.text = entry.address; ref.read(desktopExchangeModelProvider)!.recipientAddress = entry.address; - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); } } @@ -179,43 +168,36 @@ class _DesktopStep2State extends ConsumerState { final entry = await showDialog( context: context, barrierColor: Colors.transparent, - builder: (context) => DesktopDialog( - maxWidth: 720, - maxHeight: 670, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 720, + maxHeight: 670, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: STextStyles.desktopH3(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Address book", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - const DesktopDialogCloseButton(), + Expanded(child: AddressBookAddressChooser(coin: coin)), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: coin, - ), - ), - ], - ), - ), + ), ); if (entry != null) { _refundController.text = entry.address; ref.read(desktopExchangeModelProvider)!.refundAddress = entry.address; - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); } } @@ -242,33 +224,41 @@ class _DesktopStep2State extends ConsumerState { doesRefundAddress = ref.read(efExchangeProvider).supportsRefundAddress; if (!doesRefundAddress) { - // hack: set to empty to not throw null unwrap error later - ref.read(desktopExchangeModelProvider)!.refundAddress = ""; + WidgetsBinding.instance.addPostFrameCallback((_) { + // hack: set to empty to not throw null unwrap error later + ref.read(desktopExchangeModelProvider)!.refundAddress = ""; + }); } final tuple = ref.read(exchangeSendFromWalletIdStateProvider.state).state; if (tuple != null) { if (ref.read(desktopExchangeModelProvider)!.receiveTicker.toLowerCase() == tuple.item2.ticker.toLowerCase()) { - _toController.text = ref - .read(pWallets) - .getWallet(tuple.item1) - .info - .cachedReceivingAddress; - - ref.read(desktopExchangeModelProvider)!.recipientAddress = - _toController.text; + _toController.text = + ref + .read(pWallets) + .getWallet(tuple.item1) + .info + .cachedReceivingAddress; + + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(desktopExchangeModelProvider)!.recipientAddress = + _toController.text; + }); } else { if (doesRefundAddress && ref.read(desktopExchangeModelProvider)!.sendTicker.toUpperCase() == tuple.item2.ticker.toUpperCase()) { - _refundController.text = ref - .read(pWallets) - .getWallet(tuple.item1) - .info - .cachedReceivingAddress; - ref.read(desktopExchangeModelProvider)!.refundAddress = - _refundController.text; + _refundController.text = + ref + .read(pWallets) + .getWallet(tuple.item1) + .info + .cachedReceivingAddress; + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(desktopExchangeModelProvider)!.refundAddress = + _refundController.text; + }); } } } @@ -297,32 +287,30 @@ class _DesktopStep2State extends ConsumerState { style: STextStyles.desktopTextMedium(context), textAlign: TextAlign.center, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Text( "Enter your recipient and refund addresses", style: STextStyles.desktopTextExtraExtraSmall(context), textAlign: TextAlign.center, ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Recipient Wallet", style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), ), if (AppConfig.isStackCoin( ref.watch( - desktopExchangeModelProvider - .select((value) => value!.receiveTicker), + desktopExchangeModelProvider.select( + (value) => value!.receiveTicker, + ), ), )) CustomTextButton( @@ -331,9 +319,7 @@ class _DesktopStep2State extends ConsumerState { ), ], ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -359,9 +345,7 @@ class _DesktopStep2State extends ConsumerState { onChanged: (value) { ref.read(desktopExchangeModelProvider)!.recipientAddress = _toController.text; - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); }, decoration: standardInputDecoration( "Enter the ${ref.watch(desktopExchangeModelProvider.select((value) => value!.receiveTicker.toUpperCase()))} payout address", @@ -376,57 +360,56 @@ class _DesktopStep2State extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _toController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _toController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _toController.text.isNotEmpty ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - _toController.text = ""; + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + _toController.text = ""; + ref + .read(desktopExchangeModelProvider)! + .recipientAddress = _toController.text; + widget.enableNextChanged.call(_next()); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = await clipboard + .getData(Clipboard.kTextPlain); + if (data?.text != null && + data!.text!.isNotEmpty) { + final content = data.text!.trim(); + _toController.text = content; ref .read(desktopExchangeModelProvider)! .recipientAddress = _toController.text; - widget.enableNextChanged.call( - _next(), - ); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = await clipboard - .getData(Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - final content = data.text!.trim(); - _toController.text = content; - ref - .read(desktopExchangeModelProvider)! - .recipientAddress = _toController.text; - widget.enableNextChanged.call( - _next(), - ); - } - }, - child: _toController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + widget.enableNextChanged.call(_next()); + } + }, + child: + _toController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_toController.text.isEmpty && AppConfig.isStackCoin( ref.watch( - desktopExchangeModelProvider - .select((value) => value!.receiveTicker), + desktopExchangeModelProvider.select( + (value) => value!.receiveTicker, + ), ), )) TextFieldIconButton( @@ -441,9 +424,7 @@ class _DesktopStep2State extends ConsumerState { ), ), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), RoundedWhiteContainer( borderColor: Theme.of(context).extension()!.background, child: Text( @@ -451,10 +432,7 @@ class _DesktopStep2State extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall(context), ), ), - if (doesRefundAddress) - const SizedBox( - height: 24, - ), + if (doesRefundAddress) const SizedBox(height: 24), if (doesRefundAddress) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -462,15 +440,17 @@ class _DesktopStep2State extends ConsumerState { Text( "Refund Wallet (required)", style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), if (AppConfig.isStackCoin( ref.watch( - desktopExchangeModelProvider - .select((value) => value!.sendTicker), + desktopExchangeModelProvider.select( + (value) => value!.sendTicker, + ), ), )) CustomTextButton( @@ -479,10 +459,7 @@ class _DesktopStep2State extends ConsumerState { ), ], ), - if (doesRefundAddress) - const SizedBox( - height: 10, - ), + if (doesRefundAddress) const SizedBox(height: 10), if (doesRefundAddress) ClipRRect( borderRadius: BorderRadius.circular( @@ -508,9 +485,7 @@ class _DesktopStep2State extends ConsumerState { onChanged: (value) { ref.read(desktopExchangeModelProvider)!.refundAddress = _refundController.text; - widget.enableNextChanged.call( - _next(), - ); + widget.enableNextChanged.call(_next()); }, decoration: standardInputDecoration( "Enter ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker.toUpperCase()))} refund address", @@ -525,60 +500,59 @@ class _DesktopStep2State extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _refundController.text.isEmpty - ? const EdgeInsets.only(right: 16) - : const EdgeInsets.only(right: 0), + padding: + _refundController.text.isEmpty + ? const EdgeInsets.only(right: 16) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _refundController.text.isNotEmpty ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - _refundController.text = ""; + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + _refundController.text = ""; + ref + .read(desktopExchangeModelProvider)! + .refundAddress = _refundController.text; + + widget.enableNextChanged.call(_next()); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = await clipboard + .getData(Clipboard.kTextPlain); + if (data?.text != null && + data!.text!.isNotEmpty) { + final content = data.text!.trim(); + + _refundController.text = content; ref .read(desktopExchangeModelProvider)! .refundAddress = _refundController.text; - widget.enableNextChanged.call( - _next(), - ); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = await clipboard - .getData(Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - final content = data.text!.trim(); - - _refundController.text = content; - ref - .read(desktopExchangeModelProvider)! - .refundAddress = _refundController.text; - - widget.enableNextChanged.call( - _next(), - ); - } - }, - child: _refundController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + widget.enableNextChanged.call(_next()); + } + }, + child: + _refundController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_refundController.text.isEmpty && AppConfig.isStackCoin( ref.watch( - desktopExchangeModelProvider - .select((value) => value!.sendTicker), + desktopExchangeModelProvider.select( + (value) => value!.sendTicker, + ), ), )) TextFieldIconButton( @@ -593,10 +567,7 @@ class _DesktopStep2State extends ConsumerState { ), ), ), - if (doesRefundAddress) - const SizedBox( - height: 10, - ), + if (doesRefundAddress) const SizedBox(height: 10), if (doesRefundAddress) RoundedWhiteContainer( borderColor: Theme.of(context).extension()!.background, diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index d7cf255d5..7b5cd0737 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -12,18 +12,14 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:tuple/tuple.dart'; import '../../../exceptions/exchange/exchange_exception.dart'; import '../../../exceptions/exchange/pair_unavailable_exception.dart'; -import '../../../exceptions/exchange/unsupported_currency_exception.dart'; import '../../../external_api_keys.dart'; -import '../../../models/exchange/change_now/cn_exchange_estimate.dart'; +import '../../../models/exchange/change_now/cn_exchange_transaction.dart'; +import '../../../models/exchange/change_now/cn_exchange_transaction_status.dart'; import '../../../models/exchange/change_now/estimated_exchange_amount.dart'; -import '../../../models/exchange/change_now/exchange_transaction.dart'; -import '../../../models/exchange/change_now/exchange_transaction_status.dart'; import '../../../models/exchange/response_objects/estimate.dart'; -import '../../../models/exchange/response_objects/fixed_rate_market.dart'; import '../../../models/exchange/response_objects/range.dart'; import '../../../models/isar/exchange_cache/currency.dart'; import '../../../models/isar/exchange_cache/pair.dart'; @@ -34,10 +30,25 @@ import '../../tor_service.dart'; import '../exchange_response.dart'; import 'change_now_exchange.dart'; +enum CNFlow { + standard("standard"), + fixedRate("fixed-rate"); + + const CNFlow(this.value); + final String value; +} + +enum CNExchangeType { + direct("direct"), + reverse("reverse"); + + const CNExchangeType(this.value); + final String value; +} + class ChangeNowAPI { static const String scheme = "https"; static const String authority = "api.changenow.io"; - static const String apiVersion = "/v1"; static const String apiVersionV2 = "/v2"; final HTTP client; @@ -48,56 +59,24 @@ class ChangeNowAPI { static final ChangeNowAPI _instance = ChangeNowAPI(); static ChangeNowAPI get instance => _instance; - Uri _buildUri(String path, Map? params) { - return Uri.https(authority, apiVersion + path, params); - } - Uri _buildUriV2(String path, Map? params) { return Uri.https(authority, apiVersionV2 + path, params); } - Future _makeGetRequest(Uri uri) async { - try { - final response = await client.get( - url: uri, - headers: {'Content-Type': 'application/json'}, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - String? data; - try { - data = response.body; - final parsed = jsonDecode(data); - - return parsed; - } on FormatException catch (e) { - return { - "error": "Dart format exception", - "message": data, - }; - } - } catch (e, s) { - Logging.instance.e( - "_makeRequest($uri) threw", - error: e, - stackTrace: s, - ); - rethrow; - } - } - Future _makeGetRequestV2(Uri uri, String apiKey) async { + Logging.instance.t("ChangeNOW _makeGetRequestV2 to $uri"); + try { final response = await client.get( url: uri, headers: { - // 'Content-Type': 'application/json', - 'x-changenow-api-key': apiKey, + "Content-Type": "application/json", + "x-changenow-api-key": apiKey, }, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); final data = response.body; @@ -105,27 +84,29 @@ class ChangeNowAPI { return parsed; } catch (e, s) { - Logging.instance.e( - "_makeRequestV2($uri) threw", - error: e, - stackTrace: s, - ); + Logging.instance.e("_makeRequestV2($uri) threw", error: e, stackTrace: s); rethrow; } } - Future _makePostRequest( + Future _makePostRequestV2( Uri uri, Map body, + String apiKey, ) async { + Logging.instance.t("ChangeNOW _makePostRequestV2 to $uri"); try { final response = await client.post( url: uri, - headers: {'Content-Type': 'application/json'}, + headers: { + "Content-Type": "application/json", + "x-changenow-api-key": apiKey, + }, body: jsonEncode(body), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); String? data; @@ -144,7 +125,7 @@ class ChangeNowAPI { } } catch (e, s) { Logging.instance.e( - "_makePostRequest($uri) threw", + "_makePostRequestV2($uri) threw", error: e, stackTrace: s, ); @@ -152,129 +133,41 @@ class ChangeNowAPI { } } - /// This API endpoint returns the list of available currencies. + /// Retrieves the list of available currencies from the API. /// - /// Set [active] to true to return only active currencies. - /// Set [fixedRate] to true to return only currencies available on a fixed-rate flow. + /// - Set [active] to `true` to return only active currencies. + /// - Set [buy] to `true` to return only currencies available for buying. + /// - Set [sell] to `true` to return only currencies available for selling. + /// - Set [flow] to specify the type of exchange flow. + /// Options are [CNFlow.standard] (default) or [CNFlow.fixedRate]. Future>> getAvailableCurrencies({ - bool? fixedRate, bool? active, + bool? buy, + bool? sell, + CNFlow flow = CNFlow.standard, + String? apiKey, }) async { - Map? params; - - if (active != null || fixedRate != null) { - params = {}; - if (fixedRate != null) { - params.addAll({"fixedRate": fixedRate.toString()}); - } - if (active != null) { - params.addAll({"active": active.toString()}); - } - } - - final uri = _buildUri("/currencies", params); - - try { - // json array is expected here - final jsonArray = await _makeGetRequest(uri); - - try { - final result = await compute( - _parseAvailableCurrenciesJson, - Tuple2(jsonArray as List, fixedRate == true), - ); - return result; - } catch (e, s) { - Logging.instance.e( - "getAvailableCurrencies exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - "Error: $jsonArray", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } catch (e, s) { - Logging.instance.e( - "getAvailableCurrencies exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - ExchangeResponse> _parseAvailableCurrenciesJson( - Tuple2, bool> args, - ) { - try { - final List currencies = []; - - for (final json in args.item1) { - try { - final map = Map.from(json as Map); - currencies.add( - Currency.fromJson( - map, - rateType: (map["supportsFixedRate"] as bool) - ? SupportedRateType.both - : SupportedRateType.estimated, - exchangeName: ChangeNowExchange.exchangeName, - ), - ); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } - - return ExchangeResponse(value: currencies); - } catch (_) { - rethrow; - } - } - - Future>> getCurrenciesV2( - // { - // bool? fixedRate, - // bool? active, - // } - ) async { - Map? params; - - // if (active != null || fixedRate != null) { - // params = {}; - // if (fixedRate != null) { - // params.addAll({"fixedRate": fixedRate.toString()}); - // } - // if (active != null) { - // params.addAll({"active": active.toString()}); - // } - // } + final params = { + "flow": flow.value, + if (active != null) "active": active.toString(), + if (buy != null) "buy": buy.toString(), + if (sell != null) "sell": sell.toString(), + }; final uri = _buildUriV2("/exchange/currencies", params); try { // json array is expected here - final jsonArray = await _makeGetRequest(uri); + final jsonArray = await _makeGetRequestV2( + uri, + apiKey ?? kChangeNowApiKey, + ); try { - final result = await compute( - _parseV2CurrenciesJson, - jsonArray as List, - ); + final result = await compute(_parseAvailableCurrenciesJson, ( + jsonList: jsonArray as List, + fixedRateFlow: flow == CNFlow.fixedRate, + )); return result; } catch (e, s) { Logging.instance.e( @@ -304,21 +197,22 @@ class ChangeNowAPI { } } - ExchangeResponse> _parseV2CurrenciesJson( - List args, + ExchangeResponse> _parseAvailableCurrenciesJson( + ({List jsonList, bool fixedRateFlow}) args, ) { try { final List currencies = []; - for (final json in args) { + for (final json in args.jsonList) { try { final map = Map.from(json as Map); currencies.add( Currency.fromJson( map, - rateType: (map["supportsFixedRate"] as bool) - ? SupportedRateType.both - : SupportedRateType.estimated, + rateType: + (map["supportsFixedRate"] as bool) + ? SupportedRateType.both + : SupportedRateType.estimated, exchangeName: ChangeNowExchange.exchangeName, ), ); @@ -338,110 +232,37 @@ class ChangeNowAPI { } } - /// This API endpoint returns the array of markets available for the specified currency be default. - /// The availability of a particular pair is determined by the 'isAvailable' field. + /// Retrieves the minimum amount required to exchange [fromCurrency] to [toCurrency]. /// - /// Required [ticker] to fetch paired currencies for. - /// Set [fixedRate] to true to return only currencies available on a fixed-rate flow. - Future>> getPairedCurrencies({ - required String ticker, - bool? fixedRate, - }) async { - Map? params; - - if (fixedRate != null) { - params = {}; - params.addAll({"fixedRate": fixedRate.toString()}); - } - - final uri = _buildUri("/currencies-to/$ticker", params); - - try { - // json array is expected here - - final response = await _makeGetRequest(uri); - - if (response is Map && response["error"] != null) { - return ExchangeResponse( - exception: UnsupportedCurrencyException( - response["message"] as String? ?? response["error"].toString(), - ExchangeExceptionType.generic, - ticker, - ), - ); - } - - final jsonArray = response as List; - - final List currencies = []; - try { - for (final json in jsonArray) { - try { - final map = Map.from(json as Map); - currencies.add( - Currency.fromJson( - map, - rateType: (map["supportsFixedRate"] as bool) - ? SupportedRateType.both - : SupportedRateType.estimated, - exchangeName: ChangeNowExchange.exchangeName, - ), - ); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } - } catch (e, s) { - Logging.instance.e( - "getPairedCurrencies exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - "Error: $jsonArray", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - return ExchangeResponse(value: currencies); - } catch (e, s) { - Logging.instance.e( - "getPairedCurrencies exception", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// The API endpoint returns minimal payment amount required to make - /// an exchange of [fromTicker] to [toTicker]. - /// If you try to exchange less, the transaction will most likely fail. + /// If you attempt to exchange less than this amount, the transaction may fail. + /// + /// - [fromCurrency]: Ticker of the currency you want to exchange (e.g., "btc"). + /// - [toCurrency]: Ticker of the currency you want to receive (e.g., "usdt"). + /// - [fromNetwork]: (Optional) Network of the currency you want to exchange (e.g., "btc"). + /// - [toNetwork]: (Optional) Network of the currency you want to receive (e.g., "eth"). + /// - [flow]: (Optional) Exchange flow type. Defaults to [CNFlow.standard]. + /// - [apiKey]: (Optional) API key if required. Future> getMinimalExchangeAmount({ - required String fromTicker, - required String toTicker, + required String fromCurrency, + required String toCurrency, + String? fromNetwork, + String? toNetwork, + CNFlow flow = CNFlow.standard, String? apiKey, }) async { - final Map params = { - "api_key": apiKey ?? kChangeNowApiKey, + final params = { + "fromCurrency": fromCurrency, + "toCurrency": toCurrency, + "flow": flow.value, + if (fromNetwork != null) "fromNetwork": fromNetwork, + if (toNetwork != null) "toNetwork": toNetwork, }; - final uri = _buildUri("/min-amount/${fromTicker}_$toTicker", params); + final uri = _buildUriV2("/exchange/min-amount", params); try { // simple json object is expected here - final json = await _makeGetRequest(uri); + final json = await _makeGetRequestV2(uri, apiKey ?? kChangeNowApiKey); try { final value = Decimal.parse(json["minAmount"].toString()); @@ -469,27 +290,40 @@ class ChangeNowAPI { } } - /// The API endpoint returns minimal payment amount and maximum payment amount - /// required to make an exchange. If you try to exchange less than minimum or - /// more than maximum, the transaction will most likely fail. Any pair of - /// assets has minimum amount and some of pairs have maximum amount. + /// Retrieves the minimum and maximum exchangeable amounts for a given currency pair. + /// + /// Attempting to exchange less than the minimum or more than the maximum may result in a failed transaction. + /// Every asset pair has a minimum exchange amount, and some also have a maximum. + /// + /// - [fromCurrency]: Ticker of the currency you want to exchange (e.g., "btc"). + /// - [toCurrency]: Ticker of the currency you want to receive (e.g., "eth"). + /// - [fromNetwork]: (Optional) Network of the currency you want to exchange (e.g., "btc"). + /// - [toNetwork]: (Optional) Network of the currency you want to receive (e.g., "eth"). + /// - [flow]: (Optional) Type of exchange flow. Defaults to [CNFlow.standard]. + /// - [apiKey]: (Optional) API key if required. Future> getRange({ - required String fromTicker, - required String toTicker, - required bool isFixedRate, + required String fromCurrency, + required String toCurrency, + String? fromNetwork, + String? toNetwork, + CNFlow flow = CNFlow.standard, String? apiKey, }) async { - final Map params = { - "api_key": apiKey ?? kChangeNowApiKey, + final params = { + "fromCurrency": fromCurrency, + "toCurrency": toCurrency, + "flow": flow.value, + if (fromNetwork != null) "fromNetwork": fromNetwork, + if (toNetwork != null) "toNetwork": toNetwork, }; - final uri = _buildUri( - "/exchange-range${isFixedRate ? "/fixed-rate" : ""}/${fromTicker}_$toTicker", - params, - ); + final uri = _buildUriV2("/exchange/range", params); try { - final jsonObject = await _makeGetRequest(uri); + final jsonObject = await _makeGetRequestV2( + uri, + apiKey ?? kChangeNowApiKey, + ); final json = Map.from(jsonObject as Map); return ExchangeResponse( @@ -499,11 +333,7 @@ class ChangeNowAPI { ), ); } catch (e, s) { - Logging.instance.e( - "getRange exception: ", - error: e, - stackTrace: s, - ); + Logging.instance.f("getRange exception: ", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -513,24 +343,50 @@ class ChangeNowAPI { } } - /// Get estimated amount of [toTicker] cryptocurrency to receive - /// for [fromAmount] of [fromTicker] + /// Retrieves an estimated amount of [toCurrency] you would receive for a given input amount of [fromCurrency]. + /// + /// - [fromCurrency]: Ticker of the currency you want to exchange (e.g., "btc"). + /// - [toCurrency]: Ticker of the currency you want to receive (e.g., "eth"). + /// - [fromAmount]: (Required if [type] is [CNExchangeType.direct]) Amount to exchange. Must be greater than 0. + /// - [toAmount]: (Required if [type] is [CNExchangeType.reverse]) Desired amount to receive. Must be greater than 0. + /// - [fromNetwork]: (Optional) Network of the currency you want to exchange (e.g., "btc"). + /// - [toNetwork]: (Optional) Network of the currency you want to receive (e.g., "eth"). + /// - [flow]: (Optional) Type of exchange flow. Defaults to [CNFlow.standard]. + /// - [type]: (Optional) Exchange direction. Either [CNExchangeType.direct] or [CNExchangeType.reverse]. Defaults to [CNExchangeType.direct]. + /// - [useRateId]: (Optional) For fixed-rate flow. When true, the response includes a [rateId] for locking the rate in the next request. + /// - [isTopUp]: (Optional) If true, gets an estimate for a balance top-up (no withdrawal fee). + /// - [apiKey]: (Optional) API key if required. Future> getEstimatedExchangeAmount({ - required String fromTicker, - required String toTicker, - required Decimal fromAmount, + required String fromCurrency, + required String toCurrency, + Decimal? fromAmount, + Decimal? toAmount, + String? fromNetwork, + String? toNetwork, + CNFlow flow = CNFlow.standard, + CNExchangeType type = CNExchangeType.direct, + bool? useRateId, + bool? isTopUp, String? apiKey, }) async { - final Map params = {"api_key": apiKey ?? kChangeNowApiKey}; + final params = { + "fromCurrency": fromCurrency, + "toCurrency": toCurrency, + if (fromAmount != null) "fromAmount": fromAmount.toString(), + if (toAmount != null) "toAmount": toAmount.toString(), + if (fromNetwork != null) "fromNetwork": fromNetwork, + if (toNetwork != null) "toNetwork": toNetwork, + "flow": flow.value, + "type": type.value, + if (useRateId != null) "useRateId": useRateId.toString(), + if (isTopUp != null) "isTopUp": isTopUp.toString(), + }; - final uri = _buildUri( - "/exchange-amount/${fromAmount.toString()}/${fromTicker}_$toTicker", - params, - ); + final uri = _buildUriV2("/exchange/estimated-amount", params); try { // simple json object is expected here - final json = await _makeGetRequest(uri); + final json = await _makeGetRequestV2(uri, apiKey ?? kChangeNowApiKey); try { final map = Map.from(json as Map); @@ -554,104 +410,19 @@ class ChangeNowAPI { } final value = EstimatedExchangeAmount.fromJson(map); + final reversed = value.type == CNExchangeType.reverse; return ExchangeResponse( value: Estimate( - estimatedAmount: value.estimatedAmount, - fixedRate: false, - reversed: false, - rateId: value.rateId, - warningMessage: value.warningMessage, - exchangeProvider: ChangeNowExchange.exchangeName, - ), - ); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } catch (e, s) { - Logging.instance.e( - "getEstimatedExchangeAmount exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// Get estimated amount of [toTicker] cryptocurrency to receive - /// for [fromAmount] of [fromTicker] - Future> getEstimatedExchangeAmountFixedRate({ - required String fromTicker, - required String toTicker, - required Decimal fromAmount, - required bool reversed, - bool useRateId = true, - String? apiKey, - }) async { - final Map params = { - "api_key": apiKey ?? kChangeNowApiKey, - "useRateId": useRateId.toString(), - }; - - late final Uri uri; - if (reversed) { - uri = _buildUri( - "/exchange-deposit/fixed-rate/${fromAmount.toString()}/${fromTicker}_$toTicker", - params, - ); - } else { - uri = _buildUri( - "/exchange-amount/fixed-rate/${fromAmount.toString()}/${fromTicker}_$toTicker", - params, - ); - } - - try { - // simple json object is expected here - final json = await _makeGetRequest(uri); - - try { - final map = Map.from(json as Map); - - if (map["error"] != null) { - if (map["error"] == "not_valid_fixed_rate_pair") { - return ExchangeResponse( - exception: PairUnavailableException( - map["message"] as String? ?? "Unsupported fixed rate pair", - ExchangeExceptionType.generic, - ), - ); - } else { - return ExchangeResponse( - exception: ExchangeException( - map["message"] as String? ?? map["error"].toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - final value = EstimatedExchangeAmount.fromJson(map); - return ExchangeResponse( - value: Estimate( - estimatedAmount: value.estimatedAmount, - fixedRate: true, + estimatedAmount: reversed ? value.fromAmount : value.toAmount, + fixedRate: value.flow == CNFlow.fixedRate, reversed: reversed, rateId: value.rateId, warningMessage: value.warningMessage, exchangeProvider: ChangeNowExchange.exchangeName, ), ); - } catch (_) { + } catch (e, s) { + Logging.instance.f(json, error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( "Failed to serialize $json", @@ -674,325 +445,100 @@ class ChangeNowAPI { } } - // old v1 version - /// This API endpoint returns fixed-rate estimated exchange amount of - /// [toTicker] cryptocurrency to receive for [fromAmount] of [fromTicker] - // Future> - // getEstimatedFixedRateExchangeAmount({ - // required String fromTicker, - // required String toTicker, - // required Decimal fromAmount, - // // (Optional) Use rateId for fixed-rate flow. If this field is true, you - // // could use returned field "rateId" in next method for creating transaction - // // to freeze estimated amount that you got in this method. Current estimated - // // amount would be valid until time in field "validUntil" - // bool useRateId = true, - // String? apiKey, - // }) async { - // Map params = { - // "api_key": apiKey ?? kChangeNowApiKey, - // "useRateId": useRateId.toString(), - // }; - // - // final uri = _buildUri( - // "/exchange-amount/fixed-rate/${fromAmount.toString()}/${fromTicker}_$toTicker", - // params, - // ); - // - // try { - // // simple json object is expected here - // final json = await _makeGetRequest(uri); - // - // try { - // final value = EstimatedExchangeAmount.fromJson( - // Map.from(json as Map)); - // return ExchangeResponse(value: value); - // } catch (_) { - // return ExchangeResponse( - // exception: ExchangeException( - // "Failed to serialize $json", - // ExchangeExceptionType.serializeResponseError, - // ), - // ); - // } - // } catch (e, s) { - // Logging.instance.log( - // "getEstimatedFixedRateExchangeAmount exception: $e\n$s", - // level: LogLevel.Error); - // return ExchangeResponse( - // exception: ExchangeException( - // e.toString(), - // ExchangeExceptionType.generic, - // ), - // ); - // } - // } - - /// Get estimated amount of [toTicker] cryptocurrency to receive - /// for [fromAmount] of [fromTicker] - Future> getEstimatedExchangeAmountV2({ - required String fromTicker, - required String toTicker, - required CNEstimateType fromOrTo, - required Decimal amount, - String? fromNetwork, - String? toNetwork, - CNFlowType flow = CNFlowType.standard, + /// Creates a new exchange transaction. + /// + /// This method initializes a currency exchange by specifying the source and destination + /// currencies, the exchange direction, recipient details, and optional metadata. + /// + /// If using a fixed-rate flow, you **must** provide a [rateId] obtained from a prior estimate + /// to lock in the rate. If using a standard flow, [rateId] can be left null. + /// + /// Parameters: + /// - [fromCurrency]: Ticker of the currency you want to exchange (e.g., "btc"). + /// - [fromNetwork]: Network of the currency you want to exchange (e.g., "btc"). + /// - [toCurrency]: Ticker of the currency you want to receive (e.g., "usdt"). + /// - [toNetwork]: Network of the currency you want to receive (e.g., "eth"). + /// - [fromAmount]: Amount of currency you want to exchange (used in "direct" flow). + /// - [toAmount]: Amount of currency you want to receive (used in "reverse" flow). + /// - [flow]: Type of exchange flow. Either [CNFlow.standard] or [CNFlow.fixedRate]. + /// - [type]: Direction of the exchange. Use [CNExchangeType.direct] to define the amount to send, + /// or [CNExchangeType.reverse] to define the amount to receive. + /// - [address]: Wallet address that will receive the exchanged funds. + /// - [extraId]: (Optional) Extra ID required by some currencies (e.g., memo, tag). + /// - [refundAddress]: (Optional) Address used to refund funds in case of timeout or failure. + /// - [refundExtraId]: (Optional) Extra ID for the refund address if required. + /// - [userId]: (Optional) Internal user identifier for partners with special access. + /// - [payload]: (Optional) Arbitrary string to store additional context for the transaction. + /// - [contactEmail]: (Optional) Email address to contact the user in case of issues. + /// - [rateId]: (Required for fixed-rate) The rate ID returned from the estimate step to freeze the exchange rate. + /// - [apiKey]: (Optional) Your API key, if authentication is required. + /// + /// Returns a [Future] resolving to [ExchangeResponse] containing the created [ExchangeTransaction]. + Future> createExchangeTransaction({ + required String fromCurrency, + required String fromNetwork, + required String toCurrency, + required String toNetwork, + Decimal? fromAmount, + Decimal? toAmount, + CNFlow flow = CNFlow.standard, + CNExchangeType type = CNExchangeType.direct, + required String address, + String? extraId, + String? refundAddress, + String? refundExtraId, + String? userId, + String? payload, + String? contactEmail, + required String? rateId, String? apiKey, }) async { - final Map params = { - "fromCurrency": fromTicker, - "toCurrency": toTicker, + final Map body = { + "fromCurrency": fromCurrency, + "fromNetwork": fromNetwork ?? "", + "toCurrency": toCurrency, + "toNetwork": toNetwork ?? "", + "fromAmount": fromAmount?.toString() ?? "", + "toAmount": toAmount?.toString() ?? "", "flow": flow.value, - "type": fromOrTo.name, + "type": type.value, + "address": address, + "extraId": extraId ?? "", + "refundAddress": refundAddress ?? "", + "refundExtraId": refundExtraId ?? "", + "userId": userId ?? "", + "payload": payload ?? "", + "contactEmail": contactEmail ?? "", + "rateId": rateId ?? "", }; - switch (fromOrTo) { - case CNEstimateType.direct: - params["fromAmount"] = amount.toString(); - break; - case CNEstimateType.reverse: - params["toAmount"] = amount.toString(); - break; - } - - if (fromNetwork != null) { - params["fromNetwork"] = fromNetwork; - } - - if (toNetwork != null) { - params["toNetwork"] = toNetwork; - } - - if (flow == CNFlowType.fixedRate) { - params["useRateId"] = "true"; - } - - final uri = _buildUriV2("/exchange/estimated-amount", params); + final uri = _buildUriV2("/exchange", null); try { // simple json object is expected here - final json = await _makeGetRequestV2(uri, apiKey ?? kChangeNowApiKey); - - try { - final value = - CNExchangeEstimate.fromJson(Map.from(json as Map)); - return ExchangeResponse(value: value); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } catch (e, s) { - Logging.instance.e( - "getEstimatedExchangeAmountV2 exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), + final json = await _makePostRequestV2( + uri, + body, + apiKey ?? kChangeNowApiKey, ); - } - } - - /// This API endpoint returns the list of all the pairs available on a - /// fixed-rate flow. Some currencies get enabled or disabled from time to - /// time and the market info gets updates, so make sure to refresh the list - /// occasionally. One time per minute is sufficient. - Future>> getAvailableFixedRateMarkets({ - String? apiKey, - }) async { - final uri = _buildUri( - "/market-info/fixed-rate/${apiKey ?? kChangeNowApiKey}", - null, - ); - try { - // json array is expected here - final jsonArray = await _makeGetRequest(uri); + json["date"] = DateTime.now().toIso8601String(); try { - final result = - await compute(_parseFixedRateMarketsJson, jsonArray as List); - return result; - } catch (e, s) { - Logging.instance.e( - "getAvailableFixedRateMarkets exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - "Error: $jsonArray", - ExchangeExceptionType.serializeResponseError, - ), + final value = CNExchangeTransaction.fromJson( + Map.from(json as Map), ); - } - } catch (e, s) { - Logging.instance.e( - "getAvailableFixedRateMarkets exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - ExchangeResponse> _parseFixedRateMarketsJson( - List jsonArray, - ) { - try { - final List markets = []; - for (final json in jsonArray) { - try { - markets.add( - FixedRateMarket.fromMap(Map.from(json as Map)), - ); - } catch (_) { + return ExchangeResponse(value: value); + } catch (e, s) { + if (json["error"] == "rate_id_not_found_or_expired") { return ExchangeResponse( exception: ExchangeException( - "Failed to serialize $json", + "Rate ID not found or expired", ExchangeExceptionType.serializeResponseError, ), ); } - } - return ExchangeResponse(value: markets); - } catch (_) { - rethrow; - } - } - - /// The API endpoint creates a transaction, generates an address for - /// sending funds and returns transaction attributes. - Future> - createStandardExchangeTransaction({ - required String fromTicker, - required String toTicker, - required String receivingAddress, - required Decimal amount, - String extraId = "", - String userId = "", - String contactEmail = "", - String refundAddress = "", - String refundExtraId = "", - String? apiKey, - }) async { - final Map map = { - "from": fromTicker, - "to": toTicker, - "address": receivingAddress, - "amount": amount.toString(), - "flow": "standard", - "extraId": extraId, - "userId": userId, - "contactEmail": contactEmail, - "refundAddress": refundAddress, - "refundExtraId": refundExtraId, - }; - - final uri = _buildUri("/transactions/${apiKey ?? kChangeNowApiKey}", null); - - try { - // simple json object is expected here - final json = await _makePostRequest(uri, map); - - // pass in date to prevent using default 1970 date - json["date"] = DateTime.now().toString(); - - try { - final value = ExchangeTransaction.fromJson( - Map.from(json as Map), - ); - return ExchangeResponse(value: value); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } catch (e, s) { - Logging.instance.e( - "createStandardExchangeTransaction exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// The API endpoint creates a transaction, generates an address for - /// sending funds and returns transaction attributes. - Future> - createFixedRateExchangeTransaction({ - required String fromTicker, - required String toTicker, - required String receivingAddress, - required Decimal amount, - required String rateId, - required bool reversed, - String extraId = "", - String userId = "", - String contactEmail = "", - String refundAddress = "", - String refundExtraId = "", - String? apiKey, - }) async { - final Map map = { - "from": fromTicker, - "to": toTicker, - "address": receivingAddress, - "flow": "fixed-rate", - "extraId": extraId, - "userId": userId, - "contactEmail": contactEmail, - "refundAddress": refundAddress, - "refundExtraId": refundExtraId, - "rateId": rateId, - }; - - if (reversed) { - map["result"] = amount.toString(); - } else { - map["amount"] = amount.toString(); - } - - final uri = _buildUri( - "/transactions/fixed-rate${reversed ? "/from-result" : ""}/${apiKey ?? kChangeNowApiKey}", - null, - ); - - try { - // simple json object is expected here - final json = await _makePostRequest(uri, map); - - // pass in date to prevent using default 1970 date - json["date"] = DateTime.now().toString(); - - try { - final value = ExchangeTransaction.fromJson( - Map.from(json as Map), - ); - return ExchangeResponse(value: value); - } catch (_) { + Logging.instance.f(json, error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( "Failed to serialize $json", @@ -1015,23 +561,23 @@ class ChangeNowAPI { } } - Future> getTransactionStatus({ + Future> getTransactionStatus({ required String id, String? apiKey, }) async { - final uri = - _buildUri("/transactions/$id/${apiKey ?? kChangeNowApiKey}", null); + final uri = _buildUriV2("/exchange/by-id", {"id": id}); try { // simple json object is expected here - final json = await _makeGetRequest(uri); + final json = await _makeGetRequestV2(uri, apiKey ?? kChangeNowApiKey); try { - final value = ExchangeTransactionStatus.fromJson( + final value = CNExchangeTransactionStatus.fromMap( Map.from(json as Map), ); return ExchangeResponse(value: value); - } catch (_) { + } catch (e, s) { + Logging.instance.f(json, error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( "Failed to serialize $json", @@ -1053,81 +599,4 @@ class ChangeNowAPI { ); } } - - Future>> getAvailableFloatingRatePairs({ - bool includePartners = false, - }) async { - final uri = _buildUri( - "/market-info/available-pairs", - {"includePartners": includePartners.toString()}, - ); - - try { - // json array is expected here - final jsonArray = await _makeGetRequest(uri); - - try { - final result = await compute( - _parseAvailableFloatingRatePairsJson, - jsonArray as List, - ); - return result; - } catch (e, s) { - Logging.instance.e( - "getAvailableFloatingRatePairs exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - "Error: $jsonArray", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } catch (e, s) { - Logging.instance.e( - "getAvailableFloatingRatePairs exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - ExchangeResponse> _parseAvailableFloatingRatePairsJson( - List jsonArray, - ) { - try { - final List pairs = []; - for (final json in jsonArray) { - try { - final List stringPair = (json as String).split("_"); - pairs.add( - Pair( - exchangeName: ChangeNowExchange.exchangeName, - from: stringPair[0], - to: stringPair[1], - rateType: SupportedRateType.estimated, - ), - ); - } catch (_) { - return ExchangeResponse( - exception: ExchangeException( - "Failed to serialize $json", - ExchangeExceptionType.serializeResponseError, - ), - ); - } - } - return ExchangeResponse(value: pairs); - } catch (_) { - rethrow; - } - } } diff --git a/lib/services/exchange/change_now/change_now_exchange.dart b/lib/services/exchange/change_now/change_now_exchange.dart index 35e8e30b2..48389afeb 100644 --- a/lib/services/exchange/change_now/change_now_exchange.dart +++ b/lib/services/exchange/change_now/change_now_exchange.dart @@ -9,16 +9,16 @@ */ import 'package:decimal/decimal.dart'; -import '../../../models/exchange/change_now/exchange_transaction.dart'; +import 'package:uuid/uuid.dart'; + import '../../../models/exchange/response_objects/estimate.dart'; import '../../../models/exchange/response_objects/range.dart'; import '../../../models/exchange/response_objects/trade.dart'; import '../../../models/isar/exchange_cache/currency.dart'; import '../../../models/isar/exchange_cache/pair.dart'; -import 'change_now_api.dart'; import '../exchange.dart'; import '../exchange_response.dart'; -import 'package:uuid/uuid.dart'; +import 'change_now_api.dart'; class ChangeNowExchange extends Exchange { ChangeNowExchange._(); @@ -35,6 +35,8 @@ class ChangeNowExchange extends Exchange { Future> createTrade({ required String from, required String to, + String? fromNetwork, + String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -44,45 +46,35 @@ class ChangeNowExchange extends Exchange { Estimate? estimate, required bool reversed, }) async { - late final ExchangeResponse response; - if (fixedRate) { - response = await ChangeNowAPI.instance.createFixedRateExchangeTransaction( - fromTicker: from, - toTicker: to, - receivingAddress: addressTo, - amount: amount, - rateId: estimate!.rateId!, - extraId: extraId ?? "", - refundAddress: addressRefund, - refundExtraId: refundExtraId, - reversed: reversed, - ); - } else { - response = await ChangeNowAPI.instance.createStandardExchangeTransaction( - fromTicker: from, - toTicker: to, - receivingAddress: addressTo, - amount: amount, - extraId: extraId ?? "", - refundAddress: addressRefund, - refundExtraId: refundExtraId, - ); - } + final response = await ChangeNowAPI.instance.createExchangeTransaction( + fromCurrency: from, + fromNetwork: fromNetwork ?? "", + toCurrency: to, + toNetwork: toNetwork ?? "", + address: addressTo, + rateId: estimate?.rateId, + refundAddress: addressRefund, + refundExtraId: refundExtraId, + fromAmount: reversed ? null : amount, + toAmount: reversed ? amount : null, + flow: fixedRate ? CNFlow.fixedRate : CNFlow.standard, + type: reversed ? CNExchangeType.reverse : CNExchangeType.direct, + ); + if (response.exception != null) { return ExchangeResponse(exception: response.exception); } - final statusResponse = await ChangeNowAPI.instance - .getTransactionStatus(id: response.value!.id); + final statusResponse = await ChangeNowAPI.instance.getTransactionStatus( + id: response.value!.id, + ); if (statusResponse.exception != null) { return ExchangeResponse(exception: statusResponse.exception); } return ExchangeResponse( - value: Trade.fromExchangeTransaction( - response.value!.copyWith( - statusObject: statusResponse.value!, - ), + value: Trade.fromCNExchangeTransaction( + response.value!.copyWithStatus(statusResponse.value!), reversed, ), ); @@ -92,75 +84,70 @@ class ChangeNowExchange extends Exchange { Future>> getAllCurrencies( bool fixedRate, ) async { - return await ChangeNowAPI.instance.getCurrenciesV2(); - // return await ChangeNowAPI.instance.getAvailableCurrencies( - // fixedRate: fixedRate ? true : null, - // active: true, - // ); - } - - @override - Future>> getPairedCurrencies( - String forCurrency, - bool fixedRate, - ) async { - return await ChangeNowAPI.instance.getPairedCurrencies( - ticker: forCurrency, - fixedRate: fixedRate, - ); - } - - @override - Future>> getAllPairs(bool fixedRate) async { - if (fixedRate) { - final markets = - await ChangeNowAPI.instance.getAvailableFixedRateMarkets(); - - if (markets.value == null) { - return ExchangeResponse(exception: markets.exception); - } - - final List pairs = []; - for (final market in markets.value!) { - pairs.add( - Pair( - exchangeName: ChangeNowExchange.exchangeName, - from: market.from, - to: market.to, - rateType: SupportedRateType.fixed, - ), - ); - } - return ExchangeResponse(value: pairs); - } else { - return await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); - } + return await ChangeNowAPI.instance.getAvailableCurrencies(); } + // + // @override + // Future>> getPairedCurrencies( + // String forCurrency, + // bool fixedRate, + // ) async { + // return await ChangeNowAPI.instance.getPairedCurrencies( + // ticker: forCurrency, + // fixedRate: fixedRate, + // ); + // } + // + // @override + // Future>> getAllPairs(bool fixedRate) async { + // if (fixedRate) { + // final markets = + // await ChangeNowAPI.instance.getAvailableFixedRateMarkets(); + // + // if (markets.value == null) { + // return ExchangeResponse(exception: markets.exception); + // } + // + // final List pairs = []; + // for (final market in markets.value!) { + // pairs.add( + // Pair( + // exchangeName: ChangeNowExchange.exchangeName, + // from: market.from, + // to: market.to, + // rateType: SupportedRateType.fixed, + // ), + // ); + // } + // return ExchangeResponse(value: pairs); + // } else { + // return await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + // } + // } @override Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, ) async { - late final ExchangeResponse response; - if (fixedRate) { - response = - await ChangeNowAPI.instance.getEstimatedExchangeAmountFixedRate( - fromTicker: from, - toTicker: to, - fromAmount: amount, - reversed: reversed, - ); - } else { - response = await ChangeNowAPI.instance.getEstimatedExchangeAmount( - fromTicker: from, - toTicker: to, - fromAmount: amount, - ); - } + final response = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + fromCurrency: from, + fromNetwork: fromNetwork, + toCurrency: to, + toNetwork: toNetwork, + flow: fixedRate ? CNFlow.fixedRate : CNFlow.standard, + type: reversed ? CNExchangeType.reverse : CNExchangeType.direct, + fromAmount: reversed ? null : amount, + toAmount: reversed ? amount : null, + + useRateId: fixedRate ? true : null, + ); + return ExchangeResponse( value: response.value == null ? null : [response.value!], exception: response.exception, @@ -170,13 +157,17 @@ class ChangeNowExchange extends Exchange { @override Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ) async { return await ChangeNowAPI.instance.getRange( - fromTicker: from, - toTicker: to, - isFixedRate: fixedRate, + fromCurrency: from, + fromNetwork: fromNetwork, + toCurrency: to, + toNetwork: toNetwork, + flow: fixedRate ? CNFlow.fixedRate : CNFlow.standard, ); } @@ -191,8 +182,9 @@ class ChangeNowExchange extends Exchange { @override Future> getTrade(String tradeId) async { - final response = - await ChangeNowAPI.instance.getTransactionStatus(id: tradeId); + final response = await ChangeNowAPI.instance.getTransactionStatus( + id: tradeId, + ); if (response.exception != null) { return ExchangeResponse(exception: response.exception); } @@ -207,19 +199,19 @@ class ChangeNowExchange extends Exchange { timestamp: timestamp, updatedAt: DateTime.tryParse(t.updatedAt) ?? timestamp, payInCurrency: t.fromCurrency, - payInAmount: t.expectedSendAmountDecimal, + payInAmount: t.expectedAmountFrom ?? "", payInAddress: t.payinAddress, payInNetwork: "", - payInExtraId: t.payinExtraId, - payInTxid: t.payinHash, + payInExtraId: t.payinExtraId ?? "", + payInTxid: t.payinHash ?? "", payOutCurrency: t.toCurrency, - payOutAmount: t.expectedReceiveAmountDecimal, + payOutAmount: t.expectedAmountTo ?? "", payOutAddress: t.payoutAddress, payOutNetwork: "", - payOutExtraId: t.payoutExtraId, - payOutTxid: t.payoutHash, - refundAddress: t.refundAddress, - refundExtraId: t.refundExtraId, + payOutExtraId: t.payoutExtraId ?? "", + payOutTxid: t.payoutHash ?? "", + refundAddress: t.refundAddress ?? "", + refundExtraId: t.refundExtraId ?? "", status: t.status.name, exchangeName: ChangeNowExchange.exchangeName, ); @@ -229,8 +221,9 @@ class ChangeNowExchange extends Exchange { @override Future> updateTrade(Trade trade) async { - final response = - await ChangeNowAPI.instance.getTransactionStatus(id: trade.tradeId); + final response = await ChangeNowAPI.instance.getTransactionStatus( + id: trade.tradeId, + ); if (response.exception != null) { return ExchangeResponse(exception: response.exception); } @@ -245,23 +238,19 @@ class ChangeNowExchange extends Exchange { timestamp: timestamp, updatedAt: DateTime.tryParse(t.updatedAt) ?? timestamp, payInCurrency: t.fromCurrency, - payInAmount: t.amountSendDecimal.isEmpty - ? t.expectedSendAmountDecimal - : t.amountSendDecimal, + payInAmount: t.amountFrom ?? t.expectedAmountFrom ?? trade.payInAmount, payInAddress: t.payinAddress, payInNetwork: trade.payInNetwork, - payInExtraId: t.payinExtraId, - payInTxid: t.payinHash, + payInExtraId: t.payinExtraId ?? "", + payInTxid: t.payinHash ?? "", payOutCurrency: t.toCurrency, - payOutAmount: t.amountReceiveDecimal.isEmpty - ? t.expectedReceiveAmountDecimal - : t.amountReceiveDecimal, + payOutAmount: t.amountTo ?? t.expectedAmountTo ?? trade.payOutAmount, payOutAddress: t.payoutAddress, payOutNetwork: trade.payOutNetwork, - payOutExtraId: t.payoutExtraId, - payOutTxid: t.payoutHash, - refundAddress: t.refundAddress, - refundExtraId: t.refundExtraId, + payOutExtraId: t.payoutExtraId ?? "", + payOutTxid: t.payoutHash ?? "", + refundAddress: t.refundAddress ?? "", + refundExtraId: t.refundExtraId ?? "", status: t.status.name, exchangeName: ChangeNowExchange.exchangeName, ); diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index bf592fab3..f25bddc77 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -14,7 +14,6 @@ import '../../models/exchange/response_objects/estimate.dart'; import '../../models/exchange/response_objects/range.dart'; import '../../models/exchange/response_objects/trade.dart'; import '../../models/isar/exchange_cache/currency.dart'; -import '../../models/isar/exchange_cache/pair.dart'; import 'change_now/change_now_exchange.dart'; import 'exchange_response.dart'; import 'majestic_bank/majestic_bank_exchange.dart'; @@ -53,17 +52,17 @@ abstract class Exchange { Future>> getAllCurrencies(bool fixedRate); - Future>> getPairedCurrencies( - String forCurrency, - bool fixedRate, - ); - - Future>> getPairsFor( - String currency, - bool fixedRate, - ); + // Future>> getPairedCurrencies( + // String forCurrency, + // bool fixedRate, + // ); - Future>> getAllPairs(bool fixedRate); + // Future>> getPairsFor( + // String currency, + // bool fixedRate, + // ); + // + // Future>> getAllPairs(bool fixedRate); Future> getTrade(String tradeId); Future> updateTrade(Trade trade); @@ -72,13 +71,17 @@ abstract class Exchange { Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ); Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, @@ -87,6 +90,8 @@ abstract class Exchange { Future> createTrade({ required String from, required String to, + required String? fromNetwork, + required String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -101,10 +106,10 @@ abstract class Exchange { /// /// Add to this list when adding a new exchange which supports Tor. static List get exchangesWithTorSupport => [ - MajesticBankExchange.instance, - TrocadorExchange.instance, - NanswapExchange.instance, // Maybe?? - ]; + MajesticBankExchange.instance, + TrocadorExchange.instance, + NanswapExchange.instance, // Maybe?? + ]; /// List of exchange names which support Tor. /// diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index 210be8af4..ee87bf159 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -50,9 +50,10 @@ class MajesticBankAPI { try { final response = await client.get( url: uri, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); code = response.code; @@ -61,16 +62,17 @@ class MajesticBankAPI { return parsed; } catch (e, s) { - Logging.instance - .e("_makeRequest($uri) HTTP:$code threw: ", error: e, stackTrace: s); + Logging.instance.e( + "_makeRequest($uri) HTTP:$code threw: ", + error: e, + stackTrace: s, + ); rethrow; } } Future>> getRates() async { - final uri = _buildUri( - endpoint: "rates", - ); + final uri = _buildUri(endpoint: "rates"); try { final jsonObject = await _makeGetRequest(uri); @@ -90,11 +92,7 @@ class MajesticBankAPI { } return ExchangeResponse(value: rates); } catch (e, s) { - Logging.instance.e( - "getRates exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getRates exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -109,9 +107,7 @@ class MajesticBankAPI { }) async { final uri = _buildUri( endpoint: "limits", - params: { - "from_currency": fromCurrency, - }, + params: {"from_currency": fromCurrency}, ); try { @@ -127,11 +123,7 @@ class MajesticBankAPI { return ExchangeResponse(value: limit); } catch (e, s) { - Logging.instance.e( - "getLimits exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getLimits exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -163,11 +155,7 @@ class MajesticBankAPI { return ExchangeResponse(value: limits); } catch (e, s) { - Logging.instance.e( - "getLimits exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getLimits exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -196,10 +184,7 @@ class MajesticBankAPI { params["from_amount"] = amount; } - final uri = _buildUri( - endpoint: "calculate", - params: params, - ); + final uri = _buildUri(endpoint: "calculate", params: params); try { final jsonObject = await _makeGetRequest(uri); @@ -284,11 +269,7 @@ class MajesticBankAPI { return ExchangeResponse(value: order); } catch (e, s) { - Logging.instance.e( - "createOrder exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("createOrder exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -342,8 +323,11 @@ class MajesticBankAPI { return ExchangeResponse(value: order); } catch (e, s) { - Logging.instance - .e("createFixedRateOrder exception: ", error: e, stackTrace: s); + Logging.instance.e( + "createFixedRateOrder exception: ", + error: e, + stackTrace: s, + ); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -356,12 +340,7 @@ class MajesticBankAPI { Future> trackOrder({ required String orderId, }) async { - final uri = _buildUri( - endpoint: "track", - params: { - "trx": orderId, - }, - ); + final uri = _buildUri(endpoint: "track", params: {"trx": orderId}); try { final jsonObject = await _makeGetRequest(uri); diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart index 2d283e69e..b1f8be150 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart @@ -53,6 +53,8 @@ class MajesticBankExchange extends Exchange { Future> createTrade({ required String from, required String to, + required String? fromNetwork, + required String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -138,7 +140,8 @@ class MajesticBankExchange extends Exchange { final currency = Currency( exchangeName: MajesticBankExchange.exchangeName, ticker: limit.currency, - name: kMajesticBankCurrencyNames[limit.currency] ?? + name: + kMajesticBankCurrencyNames[limit.currency] ?? limit.currency, // todo: add more names if MB adds more network: "", image: "", @@ -154,42 +157,44 @@ class MajesticBankExchange extends Exchange { return ExchangeResponse(value: currencies); } - @override - Future>> getPairedCurrencies( - String forCurrency, - bool fixedRate, - ) { - // TODO: change this if the api changes to allow getting by paired currency - return getAllCurrencies(fixedRate); - } - - @override - Future>> getAllPairs(bool fixedRate) async { - final response = await MajesticBankAPI.instance.getRates(); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final List pairs = []; - final rates = response.value!; - - for (final rate in rates) { - final pair = Pair( - exchangeName: MajesticBankExchange.exchangeName, - from: rate.fromCurrency, - to: rate.toCurrency, - rateType: SupportedRateType.both, - ); - pairs.add(pair); - } - - return ExchangeResponse(value: pairs); - } + // @override + // Future>> getPairedCurrencies( + // String forCurrency, + // bool fixedRate, + // ) { + // // TODO: change this if the api changes to allow getting by paired currency + // return getAllCurrencies(fixedRate); + // } + // + // @override + // Future>> getAllPairs(bool fixedRate) async { + // final response = await MajesticBankAPI.instance.getRates(); + // if (response.value == null) { + // return ExchangeResponse(exception: response.exception); + // } + // + // final List pairs = []; + // final rates = response.value!; + // + // for (final rate in rates) { + // final pair = Pair( + // exchangeName: MajesticBankExchange.exchangeName, + // from: rate.fromCurrency, + // to: rate.toCurrency, + // rateType: SupportedRateType.both, + // ); + // pairs.add(pair); + // } + // + // return ExchangeResponse(value: pairs); + // } @override Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, @@ -214,33 +219,36 @@ class MajesticBankExchange extends Exchange { return ExchangeResponse(value: [estimate]); } - @override - Future>> getPairsFor( - String currency, - bool fixedRate, - ) async { - final response = await getAllPairs(fixedRate); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final pairs = response.value!.where( - (e) => - e.from.toUpperCase() == currency.toUpperCase() || - e.to.toUpperCase() == currency.toUpperCase(), - ); - - return ExchangeResponse(value: pairs.toList()); - } + // @override + // Future>> getPairsFor( + // String currency, + // bool fixedRate, + // ) async { + // final response = await getAllPairs(fixedRate); + // if (response.value == null) { + // return ExchangeResponse(exception: response.exception); + // } + // + // final pairs = response.value!.where( + // (e) => + // e.from.toUpperCase() == currency.toUpperCase() || + // e.to.toUpperCase() == currency.toUpperCase(), + // ); + // + // return ExchangeResponse(value: pairs.toList()); + // } @override Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ) async { - final response = - await MajesticBankAPI.instance.getLimit(fromCurrency: from); + final response = await MajesticBankAPI.instance.getLimit( + fromCurrency: from, + ); if (response.value == null) { return ExchangeResponse(exception: response.exception); } diff --git a/lib/services/exchange/nanswap/nanswap_exchange.dart b/lib/services/exchange/nanswap/nanswap_exchange.dart index de89b886e..2392199e7 100644 --- a/lib/services/exchange/nanswap/nanswap_exchange.dart +++ b/lib/services/exchange/nanswap/nanswap_exchange.dart @@ -30,6 +30,8 @@ class NanswapExchange extends Exchange { Future> createTrade({ required String from, required String to, + required String? fromNetwork, + required String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -74,9 +76,7 @@ class NanswapExchange extends Exchange { ); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } final t = response.value!; @@ -108,9 +108,7 @@ class NanswapExchange extends Exchange { ), ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( @@ -136,34 +134,31 @@ class NanswapExchange extends Exchange { final response = await NanswapAPI.instance.getSupportedCurrencies(); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } return ExchangeResponse( - value: response.value! - .where((e) => filter.contains(e.id)) - .map( - (e) => Currency( - exchangeName: exchangeName, - ticker: e.id, - name: e.name, - network: e.network, - image: e.image, - isFiat: false, - rateType: SupportedRateType.estimated, - isStackCoin: AppConfig.isStackCoin(e.id), - tokenContract: null, - isAvailable: true, - ), - ) - .toList(), + value: + response.value! + .where((e) => filter.contains(e.id)) + .map( + (e) => Currency( + exchangeName: exchangeName, + ticker: e.id, + name: e.name, + network: e.network, + image: e.image, + isFiat: false, + rateType: SupportedRateType.estimated, + isStackCoin: AppConfig.isStackCoin(e.id), + tokenContract: null, + isAvailable: true, + ), + ) + .toList(), ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( @@ -174,15 +169,12 @@ class NanswapExchange extends Exchange { } } - @override - Future>> getAllPairs(bool fixedRate) async { - throw UnimplementedError(); - } - @override Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, @@ -211,9 +203,7 @@ class NanswapExchange extends Exchange { } if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } final t = response.value!; @@ -231,9 +221,7 @@ class NanswapExchange extends Exchange { ], ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( @@ -243,59 +231,53 @@ class NanswapExchange extends Exchange { ); } } - - @override - Future>> getPairedCurrencies( - String forCurrency, - bool fixedRate, - ) async { - try { - if (fixedRate) { - throw ExchangeException( - "Nanswap fixedRate not available", - ExchangeExceptionType.generic, - ); - } - - final response = await getAllCurrencies( - fixedRate, - ); - - if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); - } - - return ExchangeResponse( - value: response.value!..removeWhere((e) => e.ticker == forCurrency), - ); - } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); - } catch (e) { - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - @override - Future>> getPairsFor( - String currency, - bool fixedRate, - ) async { - throw UnsupportedError("Not used"); - } + // + // @override + // Future>> getPairedCurrencies( + // String forCurrency, + // bool fixedRate, + // ) async { + // try { + // if (fixedRate) { + // throw ExchangeException( + // "Nanswap fixedRate not available", + // ExchangeExceptionType.generic, + // ); + // } + // + // final response = await getAllCurrencies( + // fixedRate, + // ); + // + // if (response.exception != null) { + // return ExchangeResponse( + // exception: response.exception, + // ); + // } + // + // return ExchangeResponse( + // value: response.value!..removeWhere((e) => e.ticker == forCurrency), + // ); + // } on ExchangeException catch (e) { + // return ExchangeResponse( + // exception: e, + // ); + // } catch (e) { + // return ExchangeResponse( + // exception: ExchangeException( + // e.toString(), + // ExchangeExceptionType.generic, + // ), + // ); + // } + // } @override Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ) async { try { @@ -312,9 +294,7 @@ class NanswapExchange extends Exchange { ); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } final t = response.value!; @@ -326,9 +306,7 @@ class NanswapExchange extends Exchange { ), ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( @@ -342,14 +320,10 @@ class NanswapExchange extends Exchange { @override Future> getTrade(String tradeId) async { try { - final response = await NanswapAPI.instance.getOrder( - id: tradeId, - ); + final response = await NanswapAPI.instance.getOrder(id: tradeId); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } final t = response.value!; @@ -381,9 +355,7 @@ class NanswapExchange extends Exchange { ), ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( @@ -406,14 +378,10 @@ class NanswapExchange extends Exchange { @override Future> updateTrade(Trade trade) async { try { - final response = await NanswapAPI.instance.getOrder( - id: trade.tradeId, - ); + final response = await NanswapAPI.instance.getOrder(id: trade.tradeId); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } final t = response.value!; @@ -445,9 +413,7 @@ class NanswapExchange extends Exchange { ), ); } on ExchangeException catch (e) { - return ExchangeResponse( - exception: e, - ); + return ExchangeResponse(exception: e); } catch (e) { return ExchangeResponse( exception: ExchangeException( diff --git a/lib/services/exchange/simpleswap/simpleswap_exchange.dart b/lib/services/exchange/simpleswap/simpleswap_exchange.dart index dae14cbf7..f477d182b 100644 --- a/lib/services/exchange/simpleswap/simpleswap_exchange.dart +++ b/lib/services/exchange/simpleswap/simpleswap_exchange.dart @@ -36,6 +36,8 @@ class SimpleSwapExchange extends Exchange { Future> createTrade({ required String from, required String to, + required String? fromNetwork, + required String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -61,28 +63,31 @@ class SimpleSwapExchange extends Exchange { Future>> getAllCurrencies( bool fixedRate, ) async { - final response = - await SimpleSwapAPI.instance.getAllCurrencies(fixedRate: fixedRate); + final response = await SimpleSwapAPI.instance.getAllCurrencies( + fixedRate: fixedRate, + ); if (response.value != null) { - final List currencies = response.value! - .map( - (e) => Currency( - exchangeName: exchangeName, - ticker: e.symbol, - name: e.name, - network: e.network, - image: e.image, - externalId: e.extraId, - isFiat: false, - rateType: fixedRate - ? SupportedRateType.both - : SupportedRateType.estimated, - isAvailable: true, - isStackCoin: AppConfig.isStackCoin(e.symbol), - tokenContract: null, - ), - ) - .toList(); + final List currencies = + response.value! + .map( + (e) => Currency( + exchangeName: exchangeName, + ticker: e.symbol, + name: e.name, + network: e.network, + image: e.image, + externalId: e.extraId, + isFiat: false, + rateType: + fixedRate + ? SupportedRateType.both + : SupportedRateType.estimated, + isAvailable: true, + isStackCoin: AppConfig.isStackCoin(e.symbol), + tokenContract: null, + ), + ) + .toList(); return ExchangeResponse>( value: currencies, exception: response.exception, @@ -95,15 +100,17 @@ class SimpleSwapExchange extends Exchange { ); } - @override - Future>> getAllPairs(bool fixedRate) async { - return await SimpleSwapAPI.instance.getAllPairs(isFixedRate: fixedRate); - } + // @override + // Future>> getAllPairs(bool fixedRate) async { + // return await SimpleSwapAPI.instance.getAllPairs(isFixedRate: fixedRate); + // } @override Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, @@ -115,9 +122,7 @@ class SimpleSwapExchange extends Exchange { amount: amount.toString(), ); if (response.exception != null) { - return ExchangeResponse( - exception: response.exception, - ); + return ExchangeResponse(exception: response.exception); } return ExchangeResponse( @@ -135,7 +140,9 @@ class SimpleSwapExchange extends Exchange { @override Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ) async { return await SimpleSwapAPI.instance.getRange( @@ -145,15 +152,6 @@ class SimpleSwapExchange extends Exchange { ); } - @override - Future>> getPairsFor( - String currency, - bool fixedRate, - ) async { - // return await SimpleSwapAPI.instance.ge - throw UnimplementedError(); - } - @override Future> getTrade(String tradeId) async { return await SimpleSwapAPI.instance.getExchange(exchangeId: tradeId); diff --git a/lib/services/exchange/trocador/response_objects/trocador_trade.dart b/lib/services/exchange/trocador/response_objects/trocador_trade.dart index 5d1f5d72a..781ef596a 100644 --- a/lib/services/exchange/trocador/response_objects/trocador_trade.dart +++ b/lib/services/exchange/trocador/response_objects/trocador_trade.dart @@ -92,32 +92,37 @@ class TrocadorTrade { ); } + Map toMap() { + return { + "tradeId": tradeId, + "date": date.toIso8601String(), + "tickerFrom": tickerFrom, + "tickerTo": tickerTo, + "coinFrom": coinFrom, + "coinTo": coinTo, + "networkFrom": networkFrom, + "networkTo": networkTo, + "amountFrom": amountFrom.toString(), + "amountTo": amountTo.toString(), + "provider": provider, + "fixed": fixed, + "status": status, + "addressProvider": addressProvider, + "addressProviderMemo": addressProviderMemo, + "addressUser": addressUser, + "addressUserMemo": addressUserMemo, + "refundAddress": refundAddress, + "refundAddressMemo": refundAddressMemo, + "password": password, + "idProvider": idProvider, + "quotes": quotes, + "payment": payment, + }; + } + + @override String toString() { - return 'TrocadorTrade( ' - 'tradeId: $tradeId, ' - 'date: $date, ' - 'tickerFrom: $tickerFrom, ' - 'tickerTo: $tickerTo, ' - 'coinFrom: $coinFrom, ' - 'coinTo: $coinTo, ' - 'networkFrom: $networkFrom, ' - 'networkTo: $networkTo, ' - 'amountFrom: $amountFrom, ' - 'amountTo: $amountTo, ' - 'provider: $provider, ' - 'fixed: $fixed, ' - 'status: $status, ' - 'addressProvider: $addressProvider, ' - 'addressProviderMemo: $addressProviderMemo, ' - 'addressUser: $addressUser, ' - 'addressUserMemo: $addressUserMemo, ' - 'refundAddress: $refundAddress, ' - 'refundAddressMemo: $refundAddressMemo, ' - 'password: $password, ' - 'idProvider: $idProvider, ' - 'quotes: $quotes, ' - 'payment: $payment ' - ')'; + return "TrocadorTrade: ${toMap()}"; } } diff --git a/lib/services/exchange/trocador/trocador_exchange.dart b/lib/services/exchange/trocador/trocador_exchange.dart index cf02cc206..3bae214b6 100644 --- a/lib/services/exchange/trocador/trocador_exchange.dart +++ b/lib/services/exchange/trocador/trocador_exchange.dart @@ -40,6 +40,8 @@ class TrocadorExchange extends Exchange { Future> createTrade({ required String from, required String to, + required String? fromNetwork, + required String? toNetwork, required bool fixedRate, required Decimal amount, required String addressTo, @@ -49,37 +51,38 @@ class TrocadorExchange extends Exchange { Estimate? estimate, required bool reversed, }) async { - final response = reversed - ? await TrocadorAPI.createNewPaymentRateTrade( - isOnion: false, - rateId: estimate?.rateId, - fromTicker: from.toLowerCase(), - fromNetwork: onlySupportedNetwork, - toTicker: to.toLowerCase(), - toNetwork: onlySupportedNetwork, - toAmount: amount.toString(), - receivingAddress: addressTo, - receivingMemo: null, - refundAddress: addressRefund, - refundMemo: null, - exchangeProvider: estimate!.exchangeProvider!, - isFixedRate: fixedRate, - ) - : await TrocadorAPI.createNewStandardRateTrade( - isOnion: false, - rateId: estimate?.rateId, - fromTicker: from.toLowerCase(), - fromNetwork: onlySupportedNetwork, - toTicker: to.toLowerCase(), - toNetwork: onlySupportedNetwork, - fromAmount: amount.toString(), - receivingAddress: addressTo, - receivingMemo: null, - refundAddress: addressRefund, - refundMemo: null, - exchangeProvider: estimate!.exchangeProvider!, - isFixedRate: fixedRate, - ); + final response = + reversed + ? await TrocadorAPI.createNewPaymentRateTrade( + isOnion: false, + rateId: estimate?.rateId, + fromTicker: from.toLowerCase(), + fromNetwork: onlySupportedNetwork, + toTicker: to.toLowerCase(), + toNetwork: onlySupportedNetwork, + toAmount: amount.toString(), + receivingAddress: addressTo, + receivingMemo: null, + refundAddress: addressRefund, + refundMemo: null, + exchangeProvider: estimate!.exchangeProvider!, + isFixedRate: fixedRate, + ) + : await TrocadorAPI.createNewStandardRateTrade( + isOnion: false, + rateId: estimate?.rateId, + fromTicker: from.toLowerCase(), + fromNetwork: onlySupportedNetwork, + toTicker: to.toLowerCase(), + toNetwork: onlySupportedNetwork, + fromAmount: amount.toString(), + receivingAddress: addressTo, + receivingMemo: null, + refundAddress: addressRefund, + refundMemo: null, + exchangeProvider: estimate!.exchangeProvider!, + isFixedRate: fixedRate, + ); if (response.value == null) { return ExchangeResponse(exception: response.exception); @@ -125,22 +128,23 @@ class TrocadorExchange extends Exchange { _cachedCurrencies?.removeWhere((e) => e.network != onlySupportedNetwork); - final value = _cachedCurrencies - ?.map( - (e) => Currency( - exchangeName: exchangeName, - ticker: e.ticker, - name: e.name, - network: e.network, - image: e.image, - isFiat: false, - rateType: SupportedRateType.both, - isStackCoin: AppConfig.isStackCoin(e.ticker), - tokenContract: null, - isAvailable: true, - ), - ) - .toList(); + final value = + _cachedCurrencies + ?.map( + (e) => Currency( + exchangeName: exchangeName, + ticker: e.ticker, + name: e.name, + network: e.network, + image: e.image, + isFiat: false, + rateType: SupportedRateType.both, + isStackCoin: AppConfig.isStackCoin(e.ticker), + tokenContract: null, + isAvailable: true, + ), + ) + .toList(); if (value == null) { return ExchangeResponse( @@ -195,28 +199,31 @@ class TrocadorExchange extends Exchange { @override Future>> getEstimates( String from, + String? fromNetwork, String to, + String? toNetwork, Decimal amount, bool fixedRate, bool reversed, ) async { - final response = reversed - ? await TrocadorAPI.getNewPaymentRate( - isOnion: false, - fromTicker: from, - fromNetwork: onlySupportedNetwork, - toTicker: to, - toNetwork: onlySupportedNetwork, - toAmount: amount.toString(), - ) - : await TrocadorAPI.getNewStandardRate( - isOnion: false, - fromTicker: from, - fromNetwork: onlySupportedNetwork, - toTicker: to, - toNetwork: onlySupportedNetwork, - fromAmount: amount.toString(), - ); + final response = + reversed + ? await TrocadorAPI.getNewPaymentRate( + isOnion: false, + fromTicker: from, + fromNetwork: onlySupportedNetwork, + toTicker: to, + toNetwork: onlySupportedNetwork, + toAmount: amount.toString(), + ) + : await TrocadorAPI.getNewStandardRate( + isOnion: false, + fromTicker: from, + fromNetwork: onlySupportedNetwork, + toTicker: to, + toNetwork: onlySupportedNetwork, + fromAmount: amount.toString(), + ); if (response.value == null) { return ExchangeResponse(exception: response.exception); @@ -265,43 +272,46 @@ class TrocadorExchange extends Exchange { } return ExchangeResponse( - value: estimates - ..sort((a, b) => b.estimatedAmount.compareTo(a.estimatedAmount)), + value: + estimates + ..sort((a, b) => b.estimatedAmount.compareTo(a.estimatedAmount)), ); } - @override - Future>> getPairedCurrencies( - String forCurrency, - bool fixedRate, - ) async { - // TODO: implement getPairedCurrencies - throw UnimplementedError(); - } - - @override - Future>> getPairsFor( - String currency, - bool fixedRate, - ) async { - final response = await getAllPairs(fixedRate); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final pairs = response.value!.where( - (e) => - e.from.toUpperCase() == currency.toUpperCase() || - e.to.toUpperCase() == currency.toUpperCase(), - ); - - return ExchangeResponse(value: pairs.toList()); - } + // @override + // Future>> getPairedCurrencies( + // String forCurrency, + // bool fixedRate, + // ) async { + // // TODO: implement getPairedCurrencies + // throw UnimplementedError(); + // } + // + // @override + // Future>> getPairsFor( + // String currency, + // bool fixedRate, + // ) async { + // final response = await getAllPairs(fixedRate); + // if (response.value == null) { + // return ExchangeResponse(exception: response.exception); + // } + // + // final pairs = response.value!.where( + // (e) => + // e.from.toUpperCase() == currency.toUpperCase() || + // e.to.toUpperCase() == currency.toUpperCase(), + // ); + // + // return ExchangeResponse(value: pairs.toList()); + // } @override Future> getRange( String from, + String? fromNetwork, String to, + String? toNetwork, bool fixedRate, ) async { if (_cachedCurrencies == null) { @@ -316,14 +326,12 @@ class TrocadorExchange extends Exchange { ); } - final fromCoin = _cachedCurrencies! - .firstWhere((e) => e.ticker.toLowerCase() == from.toLowerCase()); + final fromCoin = _cachedCurrencies!.firstWhere( + (e) => e.ticker.toLowerCase() == from.toLowerCase(), + ); return ExchangeResponse( - value: Range( - max: fromCoin.maximum, - min: fromCoin.minimum, - ), + value: Range(max: fromCoin.maximum, min: fromCoin.minimum), ); } diff --git a/lib/services/trade_service.dart b/lib/services/trade_service.dart index 6207b102e..e15216a33 100644 --- a/lib/services/trade_service.dart +++ b/lib/services/trade_service.dart @@ -38,8 +38,11 @@ class TradesService extends ChangeNotifier { required Trade trade, required bool shouldNotifyListeners, }) async { - await DB.instance - .put(boxName: DB.boxNameTradesV2, key: trade.uuid, value: trade); + await DB.instance.put( + boxName: DB.boxNameTradesV2, + key: trade.uuid, + value: trade, + ); if (shouldNotifyListeners) { notifyListeners(); diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index 73c520410..c12f215c0 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -62,8 +62,10 @@ class _EXCHANGE { case NanswapExchange.exchangeName: return nanswap; default: - throw ArgumentError("Invalid exchange name passed to " - "Assets.exchange.getIconFor()"); + throw ArgumentError( + "Invalid exchange name passed to " + "Assets.exchange.getIconFor()", + ); } } } @@ -232,7 +234,7 @@ class _SVG { String get trocadorRatingC => "assets/svg/trocador_rating_c.svg"; String get trocadorRatingD => "assets/svg/trocador_rating_d.svg"; -// TODO provide proper assets + // TODO provide proper assets String get bitcoinTestnet => "assets/svg/coin_icons/Bitcoin.svg"; String get bitcoincashTestnet => "assets/svg/coin_icons/Bitcoincash.svg"; String get firoTestnet => "assets/svg/coin_icons/Firo.svg"; diff --git a/lib/widgets/trade_card.dart b/lib/widgets/trade_card.dart index 28a05f9ae..35c8e4578 100644 --- a/lib/widgets/trade_card.dart +++ b/lib/widgets/trade_card.dart @@ -15,7 +15,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import '../models/exchange/change_now/exchange_transaction_status.dart'; +import '../models/exchange/change_now/cn_exchange_transaction_status.dart'; import '../models/exchange/response_objects/trade.dart'; import '../models/isar/stack_theme.dart'; import '../themes/theme_providers.dart'; @@ -26,11 +26,7 @@ import 'conditional_parent.dart'; import 'rounded_white_container.dart'; class TradeCard extends ConsumerWidget { - const TradeCard({ - super.key, - required this.trade, - required this.onTap, - }); + const TradeCard({super.key, required this.trade, required this.onTap}); final Trade trade; final VoidCallback onTap; @@ -78,10 +74,9 @@ class TradeCard extends ConsumerWidget { return ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: onTap, child: RoundedWhiteContainer( @@ -108,9 +103,7 @@ class TradeCard extends ConsumerWidget { ), ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( child: Column( children: [ @@ -127,9 +120,7 @@ class TradeCard extends ConsumerWidget { ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart b/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart index 0212d89d6..74d91b33f 100644 --- a/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart +++ b/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; + import '../../../models/isar/exchange_cache/currency.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange_data_loading_service.dart'; @@ -38,17 +39,15 @@ class WalletInfoCoinIcon extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { Currency? currency; if (contractAddress != null) { - currency = ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - contractAddress!, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirstSync(); + currency = + ExchangeDataLoadingService.instance.isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo(contractAddress!, caseSensitive: false) + .and() + .imageIsNotEmpty() + .findFirstSync(); } return Container( @@ -62,19 +61,14 @@ class WalletInfoCoinIcon extends ConsumerWidget { ), child: Padding( padding: EdgeInsets.all(size / 5), - child: currency != null && currency.image.isNotEmpty - ? SvgPicture.network( - currency.image, - width: 20, - height: 20, - ) - : SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), + child: + currency != null && currency.image.isNotEmpty + ? SvgPicture.network(currency.image, width: 20, height: 20) + : SvgPicture.file( + File(ref.watch(coinIconProvider(coin))), + width: 20, + height: 20, ), - width: 20, - height: 20, - ), ), ); } diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 565f05f82..1271b96b0 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -10,22 +10,17 @@ import 'package:decimal/decimal.dart' as _i19; import 'package:logger/logger.dart' as _i9; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i7; -import 'package:stackwallet/models/exchange/change_now/cn_exchange_estimate.dart' +import 'package:stackwallet/models/exchange/change_now/cn_exchange_transaction.dart' as _i22; -import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart' - as _i24; -import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart' - as _i25; +import 'package:stackwallet/models/exchange/change_now/cn_exchange_transaction_status.dart' + as _i23; import 'package:stackwallet/models/exchange/response_objects/estimate.dart' as _i21; -import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart' - as _i23; import 'package:stackwallet/models/exchange/response_objects/range.dart' as _i20; import 'package:stackwallet/models/exchange/response_objects/trade.dart' as _i15; import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i18; -import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i26; import 'package:stackwallet/networking/http.dart' as _i3; import 'package:stackwallet/services/exchange/change_now/change_now_api.dart' as _i17; @@ -1031,16 +1026,22 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { @override _i10.Future<_i4.ExchangeResponse>> getAvailableCurrencies({ - bool? fixedRate, bool? active, + bool? buy, + bool? sell, + _i17.CNFlow? flow = _i17.CNFlow.standard, + String? apiKey, }) => (super.noSuchMethod( Invocation.method( #getAvailableCurrencies, [], { - #fixedRate: fixedRate, #active: active, + #buy: buy, + #sell: sell, + #flow: flow, + #apiKey: apiKey, }, ), returnValue: @@ -1051,64 +1052,23 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getAvailableCurrencies, [], { - #fixedRate: fixedRate, #active: active, + #buy: buy, + #sell: sell, + #flow: flow, + #apiKey: apiKey, }, ), )), ) as _i10.Future<_i4.ExchangeResponse>>); - @override - _i10.Future<_i4.ExchangeResponse>> getCurrenciesV2() => - (super.noSuchMethod( - Invocation.method( - #getCurrenciesV2, - [], - ), - returnValue: - _i10.Future<_i4.ExchangeResponse>>.value( - _FakeExchangeResponse_2>( - this, - Invocation.method( - #getCurrenciesV2, - [], - ), - )), - ) as _i10.Future<_i4.ExchangeResponse>>); - - @override - _i10.Future<_i4.ExchangeResponse>> getPairedCurrencies({ - required String? ticker, - bool? fixedRate, - }) => - (super.noSuchMethod( - Invocation.method( - #getPairedCurrencies, - [], - { - #ticker: ticker, - #fixedRate: fixedRate, - }, - ), - returnValue: - _i10.Future<_i4.ExchangeResponse>>.value( - _FakeExchangeResponse_2>( - this, - Invocation.method( - #getPairedCurrencies, - [], - { - #ticker: ticker, - #fixedRate: fixedRate, - }, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse>>); - @override _i10.Future<_i4.ExchangeResponse<_i19.Decimal>> getMinimalExchangeAmount({ - required String? fromTicker, - required String? toTicker, + required String? fromCurrency, + required String? toCurrency, + String? fromNetwork, + String? toNetwork, + _i17.CNFlow? flow = _i17.CNFlow.standard, String? apiKey, }) => (super.noSuchMethod( @@ -1116,8 +1076,11 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getMinimalExchangeAmount, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, #apiKey: apiKey, }, ), @@ -1128,8 +1091,11 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getMinimalExchangeAmount, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, #apiKey: apiKey, }, ), @@ -1138,9 +1104,11 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { @override _i10.Future<_i4.ExchangeResponse<_i20.Range>> getRange({ - required String? fromTicker, - required String? toTicker, - required bool? isFixedRate, + required String? fromCurrency, + required String? toCurrency, + String? fromNetwork, + String? toNetwork, + _i17.CNFlow? flow = _i17.CNFlow.standard, String? apiKey, }) => (super.noSuchMethod( @@ -1148,9 +1116,11 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getRange, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #isFixedRate: isFixedRate, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, #apiKey: apiKey, }, ), @@ -1161,9 +1131,11 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getRange, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #isFixedRate: isFixedRate, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, #apiKey: apiKey, }, ), @@ -1172,9 +1144,16 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { @override _i10.Future<_i4.ExchangeResponse<_i21.Estimate>> getEstimatedExchangeAmount({ - required String? fromTicker, - required String? toTicker, - required _i19.Decimal? fromAmount, + required String? fromCurrency, + required String? toCurrency, + _i19.Decimal? fromAmount, + _i19.Decimal? toAmount, + String? fromNetwork, + String? toNetwork, + _i17.CNFlow? flow = _i17.CNFlow.standard, + _i17.CNExchangeType? type = _i17.CNExchangeType.direct, + bool? useRateId, + bool? isTopUp, String? apiKey, }) => (super.noSuchMethod( @@ -1182,9 +1161,16 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getEstimatedExchangeAmount, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, #fromAmount: fromAmount, + #toAmount: toAmount, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, + #type: type, + #useRateId: useRateId, + #isTopUp: isTopUp, #apiKey: apiKey, }, ), @@ -1195,9 +1181,16 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { #getEstimatedExchangeAmount, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, + #fromCurrency: fromCurrency, + #toCurrency: toCurrency, #fromAmount: fromAmount, + #toAmount: toAmount, + #fromNetwork: fromNetwork, + #toNetwork: toNetwork, + #flow: flow, + #type: type, + #useRateId: useRateId, + #isTopUp: isTopUp, #apiKey: apiKey, }, ), @@ -1205,277 +1198,109 @@ class MockChangeNowAPI extends _i1.Mock implements _i17.ChangeNowAPI { ) as _i10.Future<_i4.ExchangeResponse<_i21.Estimate>>); @override - _i10.Future<_i4.ExchangeResponse<_i21.Estimate>> - getEstimatedExchangeAmountFixedRate({ - required String? fromTicker, - required String? toTicker, - required _i19.Decimal? fromAmount, - required bool? reversed, - bool? useRateId = true, - String? apiKey, - }) => - (super.noSuchMethod( - Invocation.method( - #getEstimatedExchangeAmountFixedRate, - [], - { - #fromTicker: fromTicker, - #toTicker: toTicker, - #fromAmount: fromAmount, - #reversed: reversed, - #useRateId: useRateId, - #apiKey: apiKey, - }, - ), - returnValue: _i10.Future<_i4.ExchangeResponse<_i21.Estimate>>.value( - _FakeExchangeResponse_2<_i21.Estimate>( - this, - Invocation.method( - #getEstimatedExchangeAmountFixedRate, - [], - { - #fromTicker: fromTicker, - #toTicker: toTicker, - #fromAmount: fromAmount, - #reversed: reversed, - #useRateId: useRateId, - #apiKey: apiKey, - }, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse<_i21.Estimate>>); - - @override - _i10.Future<_i4.ExchangeResponse<_i22.CNExchangeEstimate>> - getEstimatedExchangeAmountV2({ - required String? fromTicker, - required String? toTicker, - required _i22.CNEstimateType? fromOrTo, - required _i19.Decimal? amount, - String? fromNetwork, - String? toNetwork, - _i22.CNFlowType? flow = _i22.CNFlowType.standard, + _i10.Future<_i4.ExchangeResponse<_i22.CNExchangeTransaction>> + createExchangeTransaction({ + required String? fromCurrency, + required String? fromNetwork, + required String? toCurrency, + required String? toNetwork, + _i19.Decimal? fromAmount, + _i19.Decimal? toAmount, + _i17.CNFlow? flow = _i17.CNFlow.standard, + _i17.CNExchangeType? type = _i17.CNExchangeType.direct, + required String? address, + String? extraId, + String? refundAddress, + String? refundExtraId, + String? userId, + String? payload, + String? contactEmail, + required String? rateId, String? apiKey, }) => (super.noSuchMethod( Invocation.method( - #getEstimatedExchangeAmountV2, + #createExchangeTransaction, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #fromOrTo: fromOrTo, - #amount: amount, + #fromCurrency: fromCurrency, #fromNetwork: fromNetwork, + #toCurrency: toCurrency, #toNetwork: toNetwork, + #fromAmount: fromAmount, + #toAmount: toAmount, #flow: flow, - #apiKey: apiKey, - }, - ), - returnValue: _i10 - .Future<_i4.ExchangeResponse<_i22.CNExchangeEstimate>>.value( - _FakeExchangeResponse_2<_i22.CNExchangeEstimate>( - this, - Invocation.method( - #getEstimatedExchangeAmountV2, - [], - { - #fromTicker: fromTicker, - #toTicker: toTicker, - #fromOrTo: fromOrTo, - #amount: amount, - #fromNetwork: fromNetwork, - #toNetwork: toNetwork, - #flow: flow, - #apiKey: apiKey, - }, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse<_i22.CNExchangeEstimate>>); - - @override - _i10.Future<_i4.ExchangeResponse>> - getAvailableFixedRateMarkets({String? apiKey}) => (super.noSuchMethod( - Invocation.method( - #getAvailableFixedRateMarkets, - [], - {#apiKey: apiKey}, - ), - returnValue: _i10 - .Future<_i4.ExchangeResponse>>.value( - _FakeExchangeResponse_2>( - this, - Invocation.method( - #getAvailableFixedRateMarkets, - [], - {#apiKey: apiKey}, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse>>); - - @override - _i10.Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>> - createStandardExchangeTransaction({ - required String? fromTicker, - required String? toTicker, - required String? receivingAddress, - required _i19.Decimal? amount, - String? extraId = r'', - String? userId = r'', - String? contactEmail = r'', - String? refundAddress = r'', - String? refundExtraId = r'', - String? apiKey, - }) => - (super.noSuchMethod( - Invocation.method( - #createStandardExchangeTransaction, - [], - { - #fromTicker: fromTicker, - #toTicker: toTicker, - #receivingAddress: receivingAddress, - #amount: amount, + #type: type, + #address: address, #extraId: extraId, - #userId: userId, - #contactEmail: contactEmail, #refundAddress: refundAddress, #refundExtraId: refundExtraId, + #userId: userId, + #payload: payload, + #contactEmail: contactEmail, + #rateId: rateId, #apiKey: apiKey, }, ), returnValue: _i10 - .Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>>.value( - _FakeExchangeResponse_2<_i24.ExchangeTransaction>( + .Future<_i4.ExchangeResponse<_i22.CNExchangeTransaction>>.value( + _FakeExchangeResponse_2<_i22.CNExchangeTransaction>( this, Invocation.method( - #createStandardExchangeTransaction, + #createExchangeTransaction, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #receivingAddress: receivingAddress, - #amount: amount, + #fromCurrency: fromCurrency, + #fromNetwork: fromNetwork, + #toCurrency: toCurrency, + #toNetwork: toNetwork, + #fromAmount: fromAmount, + #toAmount: toAmount, + #flow: flow, + #type: type, + #address: address, #extraId: extraId, - #userId: userId, - #contactEmail: contactEmail, #refundAddress: refundAddress, #refundExtraId: refundExtraId, + #userId: userId, + #payload: payload, + #contactEmail: contactEmail, + #rateId: rateId, #apiKey: apiKey, }, ), )), - ) as _i10.Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>>); + ) as _i10.Future<_i4.ExchangeResponse<_i22.CNExchangeTransaction>>); @override - _i10.Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>> - createFixedRateExchangeTransaction({ - required String? fromTicker, - required String? toTicker, - required String? receivingAddress, - required _i19.Decimal? amount, - required String? rateId, - required bool? reversed, - String? extraId = r'', - String? userId = r'', - String? contactEmail = r'', - String? refundAddress = r'', - String? refundExtraId = r'', + _i10.Future<_i4.ExchangeResponse<_i23.CNExchangeTransactionStatus>> + getTransactionStatus({ + required String? id, String? apiKey, }) => (super.noSuchMethod( Invocation.method( - #createFixedRateExchangeTransaction, + #getTransactionStatus, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #receivingAddress: receivingAddress, - #amount: amount, - #rateId: rateId, - #reversed: reversed, - #extraId: extraId, - #userId: userId, - #contactEmail: contactEmail, - #refundAddress: refundAddress, - #refundExtraId: refundExtraId, + #id: id, #apiKey: apiKey, }, ), - returnValue: _i10 - .Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>>.value( - _FakeExchangeResponse_2<_i24.ExchangeTransaction>( + returnValue: _i10.Future< + _i4 + .ExchangeResponse<_i23.CNExchangeTransactionStatus>>.value( + _FakeExchangeResponse_2<_i23.CNExchangeTransactionStatus>( this, Invocation.method( - #createFixedRateExchangeTransaction, + #getTransactionStatus, [], { - #fromTicker: fromTicker, - #toTicker: toTicker, - #receivingAddress: receivingAddress, - #amount: amount, - #rateId: rateId, - #reversed: reversed, - #extraId: extraId, - #userId: userId, - #contactEmail: contactEmail, - #refundAddress: refundAddress, - #refundExtraId: refundExtraId, + #id: id, #apiKey: apiKey, }, ), )), - ) as _i10.Future<_i4.ExchangeResponse<_i24.ExchangeTransaction>>); - - @override - _i10.Future< - _i4 - .ExchangeResponse<_i25.ExchangeTransactionStatus>> getTransactionStatus({ - required String? id, - String? apiKey, - }) => - (super.noSuchMethod( - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - returnValue: _i10 - .Future<_i4.ExchangeResponse<_i25.ExchangeTransactionStatus>>.value( - _FakeExchangeResponse_2<_i25.ExchangeTransactionStatus>( - this, - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse<_i25.ExchangeTransactionStatus>>); - - @override - _i10.Future<_i4.ExchangeResponse>> - getAvailableFloatingRatePairs({bool? includePartners = false}) => - (super.noSuchMethod( - Invocation.method( - #getAvailableFloatingRatePairs, - [], - {#includePartners: includePartners}, - ), - returnValue: - _i10.Future<_i4.ExchangeResponse>>.value( - _FakeExchangeResponse_2>( - this, - Invocation.method( - #getAvailableFloatingRatePairs, - [], - {#includePartners: includePartners}, - ), - )), - ) as _i10.Future<_i4.ExchangeResponse>>); + ) as _i10 + .Future<_i4.ExchangeResponse<_i23.CNExchangeTransactionStatus>>); } diff --git a/test/services/change_now/change_now_test.dart b/test/services/change_now/change_now_test.dart index f49c52064..f922bc3ed 100644 --- a/test/services/change_now/change_now_test.dart +++ b/test/services/change_now/change_now_test.dart @@ -8,7 +8,6 @@ import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'; import 'package:stackwallet/models/exchange/response_objects/estimate.dart'; -import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_api.dart'; @@ -23,12 +22,16 @@ void main() { final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode(jsonEncode(availableCurrenciesJSON)), 200)); + when( + client.get( + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => + Response(utf8.encode(jsonEncode(availableCurrenciesJSON)), 200), + ); final result = await instance.getAvailableCurrencies(); @@ -41,12 +44,18 @@ void main() { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode(jsonEncode(availableCurrenciesJSONActive)), 200)); + when( + client.get( + url: Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActive)), + 200, + ), + ); final result = await instance.getAvailableCurrencies(active: true); @@ -59,36 +68,24 @@ void main() { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies?fixedRate=true"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode(jsonEncode(availableCurrenciesJSONFixedRate)), 200)); - - final result = await instance.getAvailableCurrencies(fixedRate: true); - - expect(result.exception, null); - expect(result.value == null, false); - expect(result.value!.length, 410); - }); - - test("getAvailableCurrencies succeeds with fixedRate and active options", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/currencies?fixedRate=true&active=true"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode(jsonEncode(availableCurrenciesJSONActiveFixedRate)), - 200)); + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/currencies?fixedRate=true", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONFixedRate)), + 200, + ), + ); - final result = - await instance.getAvailableCurrencies(active: true, fixedRate: true); + final result = await instance.getAvailableCurrencies( + flow: CNFlow.fixedRate, + ); expect(result.exception, null); expect(result.value == null, false); @@ -96,116 +93,84 @@ void main() { }); test( - "getAvailableCurrencies fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode('{"some unexpected": "but valid json data"}'), 200)); - - final result = await instance.getAvailableCurrencies(); + "getAvailableCurrencies succeeds with fixedRate and active options", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/currencies?fixedRate=true&active=true", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActiveFixedRate)), + 200, + ), + ); + + final result = await instance.getAvailableCurrencies( + active: true, + flow: CNFlow.fixedRate, + ); + + expect(result.exception, null); + expect(result.value == null, false); + expect(result.value!.length, 410); + }, + ); - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); + test( + "getAvailableCurrencies fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.get( + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode('{"some unexpected": "but valid json data"}'), + 200, + ), + ); + + final result = await instance.getAvailableCurrencies(); + + expect( + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); + expect(result.value == null, true); + }, + ); test("getAvailableCurrencies fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); + when( + client.get( + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); final result = await instance.getAvailableCurrencies(); expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - }); - - group("getPairedCurrencies", () { - test("getPairedCurrencies succeeds without fixedRate option", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode(jsonEncode(getPairedCurrenciesJSON)), 200)); - - final result = await instance.getPairedCurrencies(ticker: "XMR"); - - expect(result.exception, null); - expect(result.value == null, false); - expect(result.value!.length, 537); - }); - - test("getPairedCurrencies succeeds with fixedRate option", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/currencies-to/XMR?fixedRate=true"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode(jsonEncode(getPairedCurrenciesJSONFixedRate)), 200)); - - final result = - await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); - - expect(result.exception, null); - expect(result.value == null, false); - expect(result.value!.length, 410); - }); - - test( - "getPairedCurrencies fails with ChangeNowExceptionType.serializeResponseError A", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode('[{"some unexpected": "but valid json data"}]'), 200)); - - final result = await instance.getPairedCurrencies(ticker: "XMR"); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - - test("getPairedCurrencies fails for any other reason", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); - - final result = - await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); - - expect(result.exception!.type, ExchangeExceptionType.generic); + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); expect(result.value == null, true); }); }); @@ -215,17 +180,22 @@ void main() { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"minAmount": 42}'), 200)); + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => + Response(utf8.encode('{"minAmount": 42}'), 200), + ); final result = await instance.getMinimalExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", + fromCurrency: "xmr", + toCurrency: "btc", apiKey: "testAPIKEY", ); @@ -235,49 +205,61 @@ void main() { }); test( - "getMinimalExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.getMinimalExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); + "getMinimalExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response(utf8.encode('{"error": 42}'), 200), + ); + + final result = await instance.getMinimalExchangeAmount( + fromCurrency: "xmr", + toCurrency: "btc", + apiKey: "testAPIKEY", + ); + + expect( + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); + expect(result.value == null, true); + }, + ); test("getMinimalExchangeAmount fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); final result = await instance.getMinimalExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", + fromCurrency: "xmr", + toCurrency: "btc", apiKey: "testAPIKEY", ); expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); expect(result.value == null, true); }); }); @@ -287,19 +269,26 @@ void main() { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( utf8.encode( - '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}'), - 200)); + '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}', + ), + 200, + ), + ); final result = await instance.getEstimatedExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", + fromCurrency: "xmr", + toCurrency: "btc", fromAmount: Decimal.fromInt(42), apiKey: "testAPIKEY", ); @@ -310,45 +299,55 @@ void main() { }); test( - "getEstimatedExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.getEstimatedExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", - fromAmount: Decimal.fromInt(42), - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); + "getEstimatedExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response(utf8.encode('{"error": 42}'), 200), + ); + + final result = await instance.getEstimatedExchangeAmount( + fromCurrency: "xmr", + toCurrency: "btc", + fromAmount: Decimal.fromInt(42), + apiKey: "testAPIKEY", + ); + + expect( + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); + expect(result.value == null, true); + }, + ); test("getEstimatedExchangeAmount fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); final result = await instance.getEstimatedExchangeAmount( - fromTicker: "xmr", - toTicker: "btc", + fromCurrency: "xmr", + toCurrency: "btc", fromAmount: Decimal.fromInt(42), apiKey: "testAPIKEY", ); @@ -373,8 +372,8 @@ void main() { // // final result = // await ChangeNow.instance.getEstimatedFixedRateExchangeAmount( - // fromTicker: "xmr", - // toTicker: "btc", + // fromCurrency: "xmr", + // toCurrency: "btc", // fromAmount: Decimal.fromInt(10), // apiKey: "testAPIKEY", // ); @@ -400,8 +399,8 @@ void main() { // // final result = // await ChangeNow.instance.getEstimatedFixedRateExchangeAmount( - // fromTicker: "xmr", - // toTicker: "btc", + // fromCurrency: "xmr", + // toCurrency: "btc", // fromAmount: Decimal.fromInt(10), // apiKey: "testAPIKEY", // ); @@ -425,8 +424,8 @@ void main() { // // final result = // await ChangeNow.instance.getEstimatedFixedRateExchangeAmount( - // fromTicker: "xmr", - // toTicker: "btc", + // fromCurrency: "xmr", + // toCurrency: "btc", // fromAmount: Decimal.fromInt(10), // apiKey: "testAPIKEY", // ); @@ -436,95 +435,38 @@ void main() { // }); // }); - group("getAvailableFixedRateMarkets", () { - test("getAvailableFixedRateMarkets succeeds", () async { + group("createExchangeTransaction", () { + test("createExchangeTransaction succeeds", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode(jsonEncode(fixedRateMarketsJSON)), 200)); - - final result = await instance.getAvailableFixedRateMarkets( - apiKey: "testAPIKEY", + when( + client.post( + url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', + encoding: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode(jsonEncode(createStandardTransactionResponse)), + 200, + ), ); - expect(result.exception, null); - expect(result.value == null, false); - expect(result.value!.length, 237); - }); - - test( - "getAvailableFixedRateMarkets fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.getAvailableFixedRateMarkets( - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - - test("getAvailableFixedRateMarkets fails for any other reason", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - - final result = await instance.getAvailableFixedRateMarkets( - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - }); - - group("createStandardExchangeTransaction", () { - test("createStandardExchangeTransaction succeeds", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.post( - url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', - encoding: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode(jsonEncode(createStandardTransactionResponse)), 200)); - - final result = await instance.createStandardExchangeTransaction( - fromTicker: "xmr", - toTicker: "btc", - receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", - amount: Decimal.parse("0.3"), + final result = await instance.createExchangeTransaction( + fromCurrency: "xmr", + toCurrency: "btc", + address: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", + fromAmount: Decimal.parse("0.3"), refundAddress: "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", apiKey: "testAPIKEY", + fromNetwork: 'xmr', + toNetwork: '', + rateId: '', ); expect(result.exception, null); @@ -533,58 +475,73 @@ void main() { }); test( - "createStandardExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.post( - url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', - encoding: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.createStandardExchangeTransaction( - fromTicker: "xmr", - toTicker: "btc", - receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", - amount: Decimal.parse("0.3"), - refundAddress: - "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - - test("createStandardExchangeTransaction fails for any other reason", - () async { + "createExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.post( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', + encoding: null, + ), + ).thenAnswer( + (realInvocation) async => Response(utf8.encode('{"error": 42}'), 200), + ); + + final result = await instance.createExchangeTransaction( + fromCurrency: "xmr", + toCurrency: "btc", + address: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", + fromAmount: Decimal.parse("0.3"), + refundAddress: + "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", + apiKey: "testAPIKEY", + fromNetwork: 'xmr', + toNetwork: '', + rateId: '', + ); + + expect( + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); + expect(result.value == null, true); + }, + ); + + test("createExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.post( - url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', - encoding: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - - final result = await instance.createStandardExchangeTransaction( - fromTicker: "xmr", - toTicker: "btc", - receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", - amount: Decimal.parse("0.3"), + when( + client.post( + url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', + encoding: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); + + final result = await instance.createExchangeTransaction( + fromCurrency: "xmr", + toCurrency: "btc", + address: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", + fromAmount: Decimal.parse("0.3"), refundAddress: "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", apiKey: "testAPIKEY", + fromNetwork: 'xmr', + toNetwork: '', + rateId: '', ); expect(result.exception!.type, ExchangeExceptionType.generic); @@ -592,37 +549,46 @@ void main() { }); }); - group("createFixedRateExchangeTransaction", () { - test("createFixedRateExchangeTransaction succeeds", () async { + group("createExchangeTransaction", () { + test("createExchangeTransaction succeeds", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.post( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":"","amount":"0.3"}', - encoding: null, - )).thenAnswer((realInvocation) async => Response( + when( + client.post( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":"","amount":"0.3"}', + encoding: null, + ), + ).thenAnswer( + (realInvocation) async => Response( utf8.encode( - '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress":' - ' "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "",' - ' "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "",' - '"refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id":' - ' "a5c73e2603f40d","amount": 62.9737711}'), - 200)); - - final result = await instance.createFixedRateExchangeTransaction( - fromTicker: "btc", - toTicker: "eth", - receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", - amount: Decimal.parse("0.3"), + '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress":' + ' "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "",' + ' "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "",' + '"refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id":' + ' "a5c73e2603f40d","amount": 62.9737711}', + ), + 200, + ), + ); + + final result = await instance.createExchangeTransaction( + fromCurrency: "btc", + toCurrency: "eth", + address: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", + fromAmount: Decimal.parse("0.3"), refundAddress: "", apiKey: "testAPIKEY", rateId: '', - reversed: false, + type: CNExchangeType.direct, + fromNetwork: 'xmr', + toNetwork: '', ); expect(result.exception, null); @@ -631,62 +597,76 @@ void main() { }); test( - "createFixedRateExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.post( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","amount":"0.3","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":""}', - encoding: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode('{"id": "a5c73e2603f40d","amount": 62.9737711}'), 200)); - - final result = await instance.createFixedRateExchangeTransaction( - fromTicker: "btc", - toTicker: "eth", - receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", - amount: Decimal.parse("0.3"), - refundAddress: "", - apiKey: "testAPIKEY", - rateId: '', - reversed: false, - ); - - expect(result.exception!.type, ExchangeExceptionType.generic); - expect(result.value == null, true); - }); - - test("createFixedRateExchangeTransaction fails for any other reason", - () async { + "createExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.post( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","amount":"0.3","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":""}', + encoding: null, + ), + ).thenAnswer( + (realInvocation) async => Response( + utf8.encode('{"id": "a5c73e2603f40d","amount": 62.9737711}'), + 200, + ), + ); + + final result = await instance.createExchangeTransaction( + fromCurrency: "btc", + toCurrency: "eth", + address: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", + fromAmount: Decimal.parse("0.3"), + refundAddress: "", + apiKey: "testAPIKEY", + rateId: '', + type: CNExchangeType.direct, + fromNetwork: 'xmr', + toNetwork: '', + ); + + expect(result.exception!.type, ExchangeExceptionType.generic); + expect(result.value == null, true); + }, + ); + + test("createExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.post( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - body: - '{"from": "btc","to": "eth","address": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "amount": "1.12345","extraId": "", "userId": "","contactEmail": "","refundAddress": "", "refundExtraId": "", "rateId": "" }', - encoding: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - - final result = await instance.createFixedRateExchangeTransaction( - fromTicker: "xmr", - toTicker: "btc", - receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", - amount: Decimal.parse("0.3"), + when( + client.post( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + body: + '{"from": "btc","to": "eth","address": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "amount": "1.12345","extraId": "", "userId": "","contactEmail": "","refundAddress": "", "refundExtraId": "", "rateId": "" }', + encoding: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); + + final result = await instance.createExchangeTransaction( + fromCurrency: "xmr", + toCurrency: "btc", + address: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", + fromAmount: Decimal.parse("0.3"), refundAddress: "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", apiKey: "testAPIKEY", rateId: '', - reversed: false, + type: CNExchangeType.direct, + fromNetwork: 'xmr', + toNetwork: '', ); expect(result.exception!.type, ExchangeExceptionType.generic); @@ -699,20 +679,27 @@ void main() { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response( utf8.encode( - '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", ' - '"payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", ' - '"fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", ' - '"updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, ' - '"expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z",' - ' "isPartner": false}'), - 200)); + '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", ' + '"payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", ' + '"fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", ' + '"updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, ' + '"expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z",' + ' "isPartner": false}', + ), + 200, + ), + ); final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", @@ -725,39 +712,49 @@ void main() { }); test( - "getTransactionStatus fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.getTransactionStatus( - id: "47F87eDB1675566DAfF5EC886", - apiKey: "testAPIKEY", - ); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); + "getTransactionStatus fails with ChangeNowExceptionType.serializeResponseError", + () async { + final client = MockHTTP(); + final instance = ChangeNowAPI(http: client); + + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer( + (realInvocation) async => Response(utf8.encode('{"error": 42}'), 200), + ); + + final result = await instance.getTransactionStatus( + id: "47F87eDB1675566DAfF5EC886", + apiKey: "testAPIKEY", + ); + + expect( + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); + expect(result.value == null, true); + }, + ); test("getTransactionStatus fails for any other reason", () async { final client = MockHTTP(); final instance = ChangeNowAPI(http: client); - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); + when( + client.get( + url: Uri.parse( + "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY", + ), + headers: {'Content-Type': 'application/json'}, + proxyInfo: null, + ), + ).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", @@ -765,67 +762,9 @@ void main() { ); expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - }); - - group("getAvailableFloatingRatePairs", () { - test("getAvailableFloatingRatePairs succeeds", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response( - utf8.encode('["btc_xmr","btc_firo","btc_doge","eth_ltc"]'), 200)); - - final result = await instance.getAvailableFloatingRatePairs(); - - expect(result.exception, null); - expect(result.value == null, false); - expect(result.value, isA>()); - }); - - test( - "getAvailableFloatingRatePairs fails with ChangeNowExceptionType.serializeResponseError", - () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => - Response(utf8.encode('{"error": 42}'), 200)); - - final result = await instance.getAvailableFloatingRatePairs(); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); - expect(result.value == null, true); - }); - - test("getAvailableFloatingRatePairs fails for any other reason", () async { - final client = MockHTTP(); - final instance = ChangeNowAPI(http: client); - - when(client.get( - url: Uri.parse( - "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), - headers: {'Content-Type': 'application/json'}, - proxyInfo: null, - )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - - final result = await instance.getAvailableFloatingRatePairs(); - - expect( - result.exception!.type, ExchangeExceptionType.serializeResponseError); + result.exception!.type, + ExchangeExceptionType.serializeResponseError, + ); expect(result.value == null, true); }); }); From a5554e068dd3258149a956a79dc913efafa5a363 Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 26 Apr 2025 16:14:48 -0600 Subject: [PATCH 037/206] possible fixed rate initial fetch fix --- lib/pages/exchange_view/exchange_form.dart | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 13f334d2a..6976d557b 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -745,8 +745,7 @@ class _ExchangeFormState extends ConsumerState { } }); _receiveFocusNode.addListener(() { - if (_receiveFocusNode.hasFocus && - ref.read(efExchangeProvider).name != ChangeNowExchange.exchangeName) { + if (_receiveFocusNode.hasFocus) { final reversed = ref.read(efReversedProvider); WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(efReversedProvider.notifier).state = true; @@ -964,9 +963,7 @@ class _ExchangeFormState extends ConsumerState { background: Theme.of(context).extension()!.textFieldDefaultBG, onTap: - rateType == ExchangeRateType.estimated && - ref.watch(efExchangeProvider).name == - ChangeNowExchange.exchangeName + rateType == ExchangeRateType.estimated ? null : () { if (_sendController.text == "-") { @@ -979,10 +976,7 @@ class _ExchangeFormState extends ConsumerState { currency: ref.watch( efCurrencyPairProvider.select((value) => value.receive), ), - readOnly: - rateType == ExchangeRateType.estimated && - ref.watch(efExchangeProvider).name == - ChangeNowExchange.exchangeName, + readOnly: rateType == ExchangeRateType.estimated, ), SizedBox(height: isDesktop ? 20 : 12), SizedBox( From 68adcac9c284f9cea6b7d55e77908f1c3c7751de Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 30 Apr 2025 16:14:03 -0500 Subject: [PATCH 038/206] feat(monero): enable local monero nodes via a "Bypass TOR" node option chore: whitespace fix --- .../add_edit_node_view.dart | 48 ++++++++++++++++++- .../manage_nodes_views/node_details_view.dart | 4 +- .../intermediate/lib_monero_wallet.dart | 4 +- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 4fdeec183..5703db754 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -241,6 +241,8 @@ class _AddEditNodeViewState extends ConsumerState { final plainEnabled = formData.netOption == TorPlainNetworkOption.clear || formData.netOption == TorPlainNetworkOption.both; + + final forceNoTor = formData.forceNoTor ?? false; switch (viewType) { case AddEditNodeViewType.add: @@ -258,6 +260,7 @@ class _AddEditNodeViewState extends ConsumerState { isDown: false, torEnabled: torEnabled, clearnetEnabled: plainEnabled, + forceNoTor: forceNoTor, ); await ref @@ -285,6 +288,7 @@ class _AddEditNodeViewState extends ConsumerState { isDown: false, torEnabled: torEnabled, clearnetEnabled: plainEnabled, + forceNoTor: forceNoTor, ); await ref @@ -744,7 +748,7 @@ class _AddEditNodeViewState extends ConsumerState { class NodeFormData { String? name, host, login, password; int? port; - bool? useSSL, isFailover, trusted; + bool? useSSL, isFailover, trusted, forceNoTor; TorPlainNetworkOption? netOption; @override @@ -793,6 +797,7 @@ class _NodeFormState extends ConsumerState { bool _useSSL = false; bool _isFailover = false; bool _trusted = false; + bool _forceNoTor = false; int? port; late bool enableSSLCheckbox; late TorPlainNetworkOption netOption; @@ -851,6 +856,7 @@ class _NodeFormState extends ConsumerState { ref.read(nodeFormDataProvider).isFailover = _isFailover; ref.read(nodeFormDataProvider).trusted = _trusted; ref.read(nodeFormDataProvider).netOption = netOption; + ref.read(nodeFormDataProvider).forceNoTor = _forceNoTor; } @override @@ -885,6 +891,7 @@ class _NodeFormState extends ConsumerState { _useSSL = node.useSSL; _isFailover = node.isFailover; _trusted = node.trusted ?? false; + _forceNoTor = node.forceNoTor ?? false; if (node.torEnabled && !node.clearnetEnabled) { netOption = TorPlainNetworkOption.tor; @@ -1445,9 +1452,48 @@ class _NodeFormState extends ConsumerState { ), ], ), + if (widget.coin is CryptonoteCurrency && _isLocalNode()) + const SizedBox(height: 8), + if (widget.coin is CryptonoteCurrency && _isLocalNode()) + Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: Checkbox( + fillColor: + !widget.readOnly + ? null + : MaterialStateProperty.all( + Theme.of( + context, + ).extension()!.checkboxBGDisabled, + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + value: _forceNoTor, + onChanged: + !widget.readOnly + ? (newValue) { + setState(() { + _forceNoTor = newValue!; + }); + _updateState(); + } + : null, + ), + ), + const SizedBox(width: 12), + Text("Bypass TOR", style: STextStyles.itemSubtitle12(context)), + ], + ), ], ); } + + bool _isLocalNode() { + final host = _hostController.text.toLowerCase(); + return host.contains("127.0.0.1") || host.contains("localhost"); + } } class RadioTextButton extends StatelessWidget { diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 56c87e5c4..572c7d7a2 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -320,7 +320,8 @@ class _NodeDetailsViewState extends ConsumerState { ..login = node.loginName ..port = node.port ..isFailover = node.isFailover - ..netOption = netOption; + ..netOption = netOption + ..forceNoTor = node.forceNoTor; nodeFormData.password = await node.getPassword( ref.read(secureStoreProvider), ); @@ -396,6 +397,7 @@ class _NodeDetailsViewState extends ConsumerState { TorPlainNetworkOption.clear || ref.read(nodeFormDataProvider).netOption == TorPlainNetworkOption.both, + forceNoTor: ref.read(nodeFormDataProvider).forceNoTor, ); await ref diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index 55812fe19..b21f5884f 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -520,7 +520,7 @@ abstract class LibMoneroWallet trusted: node.trusted ?? false, useSSL: node.useSSL, socksProxyAddress: - proxy == null ? null : "${proxy.host.address}:${proxy.port}", + node.forceNoTor ? null : proxy == null ? null : "${proxy.host.address}:${proxy.port}", ); }); } else { @@ -531,7 +531,7 @@ abstract class LibMoneroWallet trusted: node.trusted ?? false, useSSL: node.useSSL, socksProxyAddress: - proxy == null ? null : "${proxy.host.address}:${proxy.port}", + node.forceNoTor ? null : proxy == null ? null : "${proxy.host.address}:${proxy.port}", ); } libMoneroWallet?.startSyncing(); From 5a8d3b83f83f90593a61a3a66da780612cf09afa Mon Sep 17 00:00:00 2001 From: NyanCatTW1 <17372086+NyanCatTW1@users.noreply.github.com> Date: Sat, 19 Apr 2025 17:58:50 +0800 Subject: [PATCH 039/206] Feat: Add FACT0RN --- .../isar/models/blockchain_data/address.dart | 13 +- lib/services/price.dart | 67 ++-- .../crypto_currency/coins/fact0rn.dart | 241 +++++++++++++ .../crypto_currency/crypto_currency.dart | 1 + lib/wallets/wallet/impl/fact0rn_wallet.dart | 322 ++++++++++++++++++ lib/wallets/wallet/wallet.dart | 115 +++---- scripts/app_config/configure_stack_wallet.sh | 1 + 7 files changed, 658 insertions(+), 102 deletions(-) create mode 100644 lib/wallets/crypto_currency/coins/fact0rn.dart create mode 100644 lib/wallets/wallet/impl/fact0rn_wallet.dart diff --git a/lib/models/isar/models/blockchain_data/address.dart b/lib/models/isar/models/blockchain_data/address.dart index 8947d6c46..cb239bc5e 100644 --- a/lib/models/isar/models/blockchain_data/address.dart +++ b/lib/models/isar/models/blockchain_data/address.dart @@ -101,7 +101,8 @@ class Address extends CryptoCurrencyAddress { } @override - String toString() => "{ " + String toString() => + "{ " "id: $id, " "walletId: $walletId, " "value: $value, " @@ -130,10 +131,7 @@ class Address extends CryptoCurrencyAddress { return jsonEncode(result); } - static Address fromJsonString( - String jsonString, { - String? overrideWalletId, - }) { + static Address fromJsonString(String jsonString, {String? overrideWalletId}) { final json = jsonDecode(jsonString); final derivationPathString = json["derivationPath"] as String?; @@ -176,7 +174,8 @@ enum AddressType { p2tr, solana, cardanoShelley, - xelis; + xelis, + fact0rn; String get readableName { switch (this) { @@ -216,6 +215,8 @@ enum AddressType { return "Cardano Shelley"; case AddressType.xelis: return "Xelis"; + case AddressType.fact0rn: + return "FACT0RN"; } } } diff --git a/lib/services/price.dart b/lib/services/price.dart index 801e720e2..66a6f23bf 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -37,6 +37,7 @@ class PriceAPI { Epiccash: "epic-cash", Ecash: "ecash", Ethereum: "ethereum", + Fact0rn: "fact0rn", Firo: "zcoin", Monero: "monero", Particl: "particl", @@ -54,13 +55,15 @@ class PriceAPI { static const refreshInterval = 60; // initialize to older than current time minus at least refreshInterval - static DateTime _lastCalled = - DateTime.now().subtract(const Duration(seconds: refreshInterval + 10)); + static DateTime _lastCalled = DateTime.now().subtract( + const Duration(seconds: refreshInterval + 10), + ); static String _lastUsedBaseCurrency = ""; - static const Duration refreshIntervalDuration = - Duration(seconds: refreshInterval); + static const Duration refreshIntervalDuration = Duration( + seconds: refreshInterval, + ); final HTTP client; @@ -85,15 +88,18 @@ class PriceAPI { } } - await DB.instance - .put(boxName: DB.boxNamePriceCache, key: 'cache', value: map); + await DB.instance.put( + boxName: DB.boxNamePriceCache, + key: 'cache', + value: map, + ); } Map> get _cachedPrices { final map = DB.instance.get(boxName: DB.boxNamePriceCache, key: 'cache') - as Map? ?? - {}; + as Map? ?? + {}; // init with 0 final result = { for (final coin in AppConfig.coins) coin: Tuple2(Decimal.zero, 0.0), @@ -132,9 +138,7 @@ class PriceAPI { final externalCalls = Prefs.instance.externalCalls; if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return _cachedPrices; } final Map> result = {}; @@ -148,9 +152,10 @@ class PriceAPI { final coinGeckoResponse = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); final coinGeckoData = jsonDecode(coinGeckoResponse.body) as List; @@ -160,9 +165,10 @@ class PriceAPI { final coin = AppConfig.getCryptoCurrencyByPrettyName(coinName); final price = Decimal.parse(map["current_price"].toString()); - final change24h = map["price_change_percentage_24h"] != null - ? double.parse(map["price_change_percentage_24h"].toString()) - : 0.0; + final change24h = + map["price_change_percentage_24h"] != null + ? double.parse(map["price_change_percentage_24h"].toString()) + : 0.0; result[coin] = Tuple2(price, change24h); } @@ -172,8 +178,11 @@ class PriceAPI { return _cachedPrices; } catch (e, s) { - Logging.instance - .e("getPricesAnd24hChange($baseCurrency): ", error: e, stackTrace: s); + Logging.instance.e( + "getPricesAnd24hChange($baseCurrency): ", + error: e, + stackTrace: s, + ); // return previous cached values return _cachedPrices; } @@ -185,9 +194,7 @@ class PriceAPI { if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return null; } const uriString = @@ -197,9 +204,10 @@ class PriceAPI { final response = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); final json = jsonDecode(response.body) as List; @@ -215,21 +223,20 @@ class PriceAPI { } Future>> - getPricesAnd24hChangeForEthTokens({ + getPricesAnd24hChangeForEthTokens({ required Set contractAddresses, required String baseCurrency, }) async { final Map> tokenPrices = {}; if (AppConfig.coins.whereType().isEmpty || - contractAddresses.isEmpty) return tokenPrices; + contractAddresses.isEmpty) + return tokenPrices; final externalCalls = Prefs.instance.externalCalls; if ((!Util.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { - Logging.instance.i( - "User does not want to use external calls", - ); + Logging.instance.i("User does not want to use external calls"); return tokenPrices; } diff --git a/lib/wallets/crypto_currency/coins/fact0rn.dart b/lib/wallets/crypto_currency/coins/fact0rn.dart new file mode 100644 index 000000000..84fc902b5 --- /dev/null +++ b/lib/wallets/crypto_currency/coins/fact0rn.dart @@ -0,0 +1,241 @@ +import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; + +import '../../../models/isar/models/blockchain_data/address.dart'; +import '../../../models/node_model.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/default_nodes.dart'; +import '../../../utilities/enums/derive_path_type_enum.dart'; +import '../crypto_currency.dart'; +import '../interfaces/electrumx_currency_interface.dart'; +import '../intermediate/bip39_hd_currency.dart'; + +class Fact0rn extends Bip39HDCurrency with ElectrumXCurrencyInterface { + Fact0rn(super.network) { + _idMain = "fact0rn"; + _uriScheme = "fact0rn"; + switch (network) { + case CryptoCurrencyNetwork.main: + _id = _idMain; + _name = "FACT0RN"; + _ticker = "FACT"; + case CryptoCurrencyNetwork.test: + _id = "fact0rnTestNet"; + _name = "tFACT0RN"; + _ticker = "tFACT"; + default: + throw Exception("Unsupported network: $network"); + } + } + + late final String _id; + @override + String get identifier => _id; + + late final String _idMain; + @override + String get mainNetId => _idMain; + + late final String _name; + @override + String get prettyName => _name; + + late final String _uriScheme; + @override + String get uriScheme => _uriScheme; + + late final String _ticker; + @override + String get ticker => _ticker; + + @override + bool get torSupport => false; + + @override + List get supportedDerivationPathTypes => [ + DerivePathType.bip84, + ]; + + @override + String constructDerivePath({ + required DerivePathType derivePathType, + int account = 0, + required int chain, + required int index, + }) { + String coinType; + + switch (networkParams.wifPrefix) { + case 0x80: + coinType = "42069"; // fact0rn mainnet + break; + case 0xef: + coinType = "1"; // fact0rn testnet + break; + default: + throw Exception("Invalid Fact0rn network wif used!"); + } + + int purpose; + switch (derivePathType) { + case DerivePathType.bip84: + purpose = 84; + break; + + default: + throw Exception("DerivePathType $derivePathType not supported"); + } + + return "m/$purpose'/$coinType'/$account'/$chain/$index"; + } + + @override + Amount get dustLimit => + Amount(rawValue: BigInt.from(1000), fractionDigits: fractionDigits); + + @override + String get genesisHash { + switch (network) { + case CryptoCurrencyNetwork.main: + return "79cb40f8075b0e3dc2bc468c5ce2a7acbe0afd36c6c3d3a134ea692edac7de49"; + case CryptoCurrencyNetwork.test: + return "550bbf0a444d9f92189f067dd225f5b8a5d92587ebc2e8398d143236072580af"; + default: + throw Exception("Unsupported network: $network"); + } + } + + @override + ({coinlib.Address address, AddressType addressType}) getAddressForPublicKey({ + required coinlib.ECPublicKey publicKey, + required DerivePathType derivePathType, + }) { + switch (derivePathType) { + case DerivePathType.bip84: + final addr = coinlib.P2WPKHAddress.fromPublicKey( + publicKey, + hrp: networkParams.bech32Hrp, + ); + + return (address: addr, addressType: AddressType.p2wpkh); + + default: + throw Exception("DerivePathType $derivePathType not supported"); + } + } + + @override + int get minConfirms => 1; + + @override + coinlib.Network get networkParams { + switch (network) { + case CryptoCurrencyNetwork.main: + return coinlib.Network( + wifPrefix: 0x80, + p2pkhPrefix: 0x00, + p2shPrefix: 0x05, + privHDPrefix: 0x0488ade4, + pubHDPrefix: 0x0488b21e, + bech32Hrp: "fact", + messagePrefix: '\x18Bitcoin Signed Message:\n', + minFee: BigInt.from(1), // Not used in stack wallet currently + minOutput: dustLimit.raw, // Not used in stack wallet currently + feePerKb: BigInt.from(1), // Not used in stack wallet currently + ); + case CryptoCurrencyNetwork.test: + return coinlib.Network( + wifPrefix: 0xef, + p2pkhPrefix: 0x6f, + p2shPrefix: 0xc4, + privHDPrefix: 0x04358394, + pubHDPrefix: 0x043587cf, + bech32Hrp: "tfact", + messagePrefix: "\x18Bitcoin Signed Message:\n", + minFee: BigInt.from(1), // Not used in stack wallet currently + minOutput: dustLimit.raw, // Not used in stack wallet currently + feePerKb: BigInt.from(1), // Not used in stack wallet currently + ); + default: + throw Exception("Unsupported network: $network"); + } + } + + @override + bool validateAddress(String address) { + try { + coinlib.Address.fromString(address, networkParams); + return true; + } catch (_) { + return false; + } + } + + @override + NodeModel get defaultNode { + switch (network) { + case CryptoCurrencyNetwork.main: + return NodeModel( + host: "electrumx.fact0rn.io", + port: 50002, + name: DefaultNodes.defaultName, + id: DefaultNodes.buildId(this), + useSSL: true, + enabled: true, + coinName: identifier, + isFailover: true, + isDown: false, + torEnabled: false, + clearnetEnabled: true, + ); + + default: + throw UnimplementedError(); + } + } + + @override + int get defaultSeedPhraseLength => 12; + + @override + int get fractionDigits => 8; + + @override + bool get hasBuySupport => false; + + @override + bool get hasMnemonicPassphraseSupport => true; + + @override + List get possibleMnemonicLengths => [defaultSeedPhraseLength, 24]; + + @override + AddressType get defaultAddressType => defaultDerivePathType.getAddressType(); + + @override + BigInt get satsPerCoin => BigInt.from(100000000); + + @override + int get targetBlockTimeSeconds => 1800; + + @override + DerivePathType get defaultDerivePathType => DerivePathType.bip84; + + @override + Uri defaultBlockExplorer(String txid) { + switch (network) { + case CryptoCurrencyNetwork.main: + // "https://explorer.fact0rn.io/tx/$txid" doesn't show mempool transactions + return Uri.parse("https://factexplorer.io/tx/$txid"); + default: + throw Exception( + "Unsupported network for defaultBlockExplorer(): $network", + ); + } + } + + @override + int get transactionVersion => 2; + + @override + BigInt get defaultFeeRate => BigInt.from(1000); +} diff --git a/lib/wallets/crypto_currency/crypto_currency.dart b/lib/wallets/crypto_currency/crypto_currency.dart index d5553ceca..f262490ff 100644 --- a/lib/wallets/crypto_currency/crypto_currency.dart +++ b/lib/wallets/crypto_currency/crypto_currency.dart @@ -12,6 +12,7 @@ export 'coins/dogecoin.dart'; export 'coins/ecash.dart'; export 'coins/epiccash.dart'; export 'coins/ethereum.dart'; +export 'coins/fact0rn.dart'; export 'coins/firo.dart'; export 'coins/litecoin.dart'; export 'coins/monero.dart'; diff --git a/lib/wallets/wallet/impl/fact0rn_wallet.dart b/lib/wallets/wallet/impl/fact0rn_wallet.dart new file mode 100644 index 000000000..14c8106a9 --- /dev/null +++ b/lib/wallets/wallet/impl/fact0rn_wallet.dart @@ -0,0 +1,322 @@ +import 'package:isar/isar.dart'; + +import '../../../models/isar/models/blockchain_data/address.dart'; +import '../../../models/isar/models/blockchain_data/transaction.dart'; +import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/extensions/extensions.dart'; +import '../../../utilities/logger.dart'; +import '../../crypto_currency/crypto_currency.dart'; +import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; +import '../intermediate/bip39_hd_wallet.dart'; +import '../wallet_mixin_interfaces/coin_control_interface.dart'; +import '../wallet_mixin_interfaces/electrumx_interface.dart'; +import '../wallet_mixin_interfaces/extended_keys_interface.dart'; + +class Fact0rnWallet + extends Bip39HDWallet + with ElectrumXInterface, ExtendedKeysInterface, CoinControlInterface { + Fact0rnWallet(CryptoCurrencyNetwork network) : super(Fact0rn(network) as T); + + @override + int get isarTransactionVersion => 2; + + @override + FilterOperation? get changeAddressFilterOperation => + FilterGroup.and(standardChangeAddressFilters); + + @override + FilterOperation? get receivingAddressFilterOperation => + FilterGroup.and(standardReceivingAddressFilters); + + // =========================================================================== + + @override + Future> fetchAddressesForElectrumXScan() async { + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); + return allAddresses; + } + + // =========================================================================== + + @override + Future updateTransactions() async { + // Get all addresses. + final List
allAddressesOld = + await fetchAddressesForElectrumXScan(); + + // Separate receiving and change addresses. + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); + + // Remove duplicates. + final allAddressesSet = {...receivingAddresses, ...changeAddresses}; + + // Fetch history from ElectrumX. + final List> allTxHashes = await fetchHistory( + allAddressesSet, + ); + + // Only parse new txs (not in db yet). + final List> allTransactions = []; + for (final txHash in allTxHashes) { + // Check for duplicates by searching for tx by tx_hash in db. + final storedTx = + await mainDB.isar.transactionV2s + .where() + .txidWalletIdEqualTo(txHash["tx_hash"] as String, walletId) + .findFirst(); + + if (storedTx == null || + storedTx.height == null || + (storedTx.height != null && storedTx.height! <= 0)) { + // Tx not in db yet. + final tx = await electrumXCachedClient.getTransaction( + txHash: txHash["tx_hash"] as String, + verbose: true, + cryptoCurrency: cryptoCurrency, + ); + + // Only tx to list once. + if (allTransactions.indexWhere( + (e) => e["txid"] == tx["txid"] as String, + ) == + -1) { + tx["height"] = txHash["height"]; + allTransactions.add(tx); + } + } + } + + // Parse all new txs. + final List txns = []; + for (final txData in allTransactions) { + bool wasSentFromThisWallet = false; + // Set to true if any inputs were detected as owned by this wallet. + + bool wasReceivedInThisWallet = false; + // Set to true if any outputs were detected as owned by this wallet. + + // Parse inputs. + BigInt amountReceivedInThisWallet = BigInt.zero; + BigInt changeAmountReceivedInThisWallet = BigInt.zero; + final List inputs = []; + for (final jsonInput in txData["vin"] as List) { + final map = Map.from(jsonInput as Map); + + final List addresses = []; + String valueStringSats = "0"; + OutpointV2? outpoint; + + final coinbase = map["coinbase"] as String?; + + if (coinbase == null) { + // Not a coinbase (ie a typical input). + final txid = map["txid"] as String; + final vout = map["vout"] as int; + + final inputTx = await electrumXCachedClient.getTransaction( + txHash: txid, + cryptoCurrency: cryptoCurrency, + ); + + final prevOutJson = Map.from( + (inputTx["vout"] as List).firstWhere((e) => e["n"] == vout) as Map, + ); + + final prevOut = OutputV2.fromElectrumXJson( + prevOutJson, + decimalPlaces: cryptoCurrency.fractionDigits, + isFullAmountNotSats: true, + walletOwns: false, // Doesn't matter here as this is not saved. + ); + + outpoint = OutpointV2.isarCantDoRequiredInDefaultConstructor( + txid: txid, + vout: vout, + ); + valueStringSats = prevOut.valueStringSats; + addresses.addAll(prevOut.addresses); + } + + InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: map["scriptSig"]?["hex"] as String?, + scriptSigAsm: map["scriptSig"]?["asm"] as String?, + sequence: map["sequence"] as int?, + outpoint: outpoint, + valueStringSats: valueStringSats, + addresses: addresses, + witness: map["witness"] as String?, + coinbase: coinbase, + innerRedeemScriptAsm: map["innerRedeemscriptAsm"] as String?, + // Need addresses before we can know if the wallet owns this input. + walletOwns: false, + ); + + // Check if input was from this wallet. + if (allAddressesSet.intersection(input.addresses.toSet()).isNotEmpty) { + wasSentFromThisWallet = true; + input = input.copyWith(walletOwns: true); + } + + inputs.add(input); + } + + // Parse outputs. + final List outputs = []; + for (final outputJson in txData["vout"] as List) { + OutputV2 output = OutputV2.fromElectrumXJson( + Map.from(outputJson as Map), + decimalPlaces: cryptoCurrency.fractionDigits, + isFullAmountNotSats: true, + // Need addresses before we can know if the wallet owns this input. + walletOwns: false, + ); + + // If output was to my wallet, add value to amount received. + if (receivingAddresses + .intersection(output.addresses.toSet()) + .isNotEmpty) { + wasReceivedInThisWallet = true; + amountReceivedInThisWallet += output.value; + output = output.copyWith(walletOwns: true); + } else if (changeAddresses + .intersection(output.addresses.toSet()) + .isNotEmpty) { + wasReceivedInThisWallet = true; + changeAmountReceivedInThisWallet += output.value; + output = output.copyWith(walletOwns: true); + } + + outputs.add(output); + } + + final totalOut = outputs + .map((e) => e.value) + .fold(BigInt.zero, (value, element) => value + element); + + TransactionType type; + final TransactionSubType subType = TransactionSubType.none; + + // At least one input was owned by this wallet. + if (wasSentFromThisWallet) { + type = TransactionType.outgoing; + + if (wasReceivedInThisWallet) { + if (changeAmountReceivedInThisWallet + amountReceivedInThisWallet == + totalOut) { + // Definitely sent all to self. + type = TransactionType.sentToSelf; + } else if (amountReceivedInThisWallet == BigInt.zero) { + // Most likely just a typical send, do nothing here yet. + } + + // Fact0rn has special outputs like deadpool bounties + announcements, but they're unsupported. + // This is where we would check for them. + // TODO: [prio=none] Check for special Fact0rn outputs. + } + } else if (wasReceivedInThisWallet) { + // Only found outputs owned by this wallet. + type = TransactionType.incoming; + } else { + Logging.instance.e("Unexpected tx found (ignoring it)"); + Logging.instance.d("Unexpected tx found (ignoring it): $txData"); + continue; + } + + final tx = TransactionV2( + walletId: walletId, + blockHash: txData["blockhash"] as String?, + hash: txData["hash"] as String, + txid: txData["txid"] as String, + height: txData["height"] as int?, + version: txData["version"] as int, + timestamp: + txData["blocktime"] as int? ?? + DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, + inputs: List.unmodifiable(inputs), + outputs: List.unmodifiable(outputs), + type: type, + subType: subType, + otherData: null, + ); + + txns.add(tx); + } + + await mainDB.updateOrPutTransactionV2s(txns); + } + + @override + Future<({String? blockedReason, bool blocked, String? utxoLabel})> + checkBlockUTXO( + Map jsonUTXO, + String? scriptPubKeyHex, + Map jsonTX, + String? utxoOwnerAddress, + ) async { + bool blocked = false; + String? blockedReason; + + // check for bip47 notification + final outputs = jsonTX["vout"] as List; + for (final output in outputs) { + final List? scriptChunks = + (output['scriptPubKey']?['asm'] as String?)?.split(" "); + if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") { + final blindedPaymentCode = scriptChunks![1]; + final bytes = blindedPaymentCode.toUint8ListFromHex; + + // https://en.bitcoin.it/wiki/BIP_0047#Sending + if (bytes.length == 80 && bytes.first == 1) { + blocked = true; + blockedReason = + "Paynym notification output. Incautious " + "handling of outputs from notification transactions " + "may cause unintended loss of privacy."; + break; + } + } + } + + return (blockedReason: blockedReason, blocked: blocked, utxoLabel: null); + } + + // Typical SegWit estimation + @override + Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + return Amount( + rawValue: BigInt.from( + ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * + (feeRatePerKB / 1000).ceil(), + ), + fractionDigits: cryptoCurrency.fractionDigits, + ); + } + + @override + int estimateTxFee({required int vSize, required int feeRatePerKB}) { + return vSize * (feeRatePerKB / 1000).ceil(); + } +} diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index be21c5282..c2e542eb7 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -35,6 +35,7 @@ import 'impl/dogecoin_wallet.dart'; import 'impl/ecash_wallet.dart'; import 'impl/epiccash_wallet.dart'; import 'impl/ethereum_wallet.dart'; +import 'impl/fact0rn_wallet.dart'; import 'impl/firo_wallet.dart'; import 'impl/litecoin_wallet.dart'; import 'impl/monero_wallet.dart'; @@ -127,11 +128,7 @@ abstract class Wallet { await updateChainHeight(); } catch (e, s) { // do nothing on failure (besides logging) - Logging.instance.w( - "$e\n$s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); } // return regardless of whether it was updated or not as we want a @@ -173,7 +170,8 @@ abstract class Wallet { value: viewOnlyData!.toJsonEncodedString(), ); } else if (wallet is MnemonicInterface) { - if (wallet is CryptonoteWallet || wallet is XelisWallet) { // + if (wallet is CryptonoteWallet || wallet is XelisWallet) { + // // currently a special case due to the xmr/wow/xelis libraries handling their // own mnemonic generation on new wallet creation // if its a restore we must set them @@ -238,10 +236,11 @@ abstract class Wallet { required NodeService nodeService, required Prefs prefs, }) async { - final walletInfo = await mainDB.isar.walletInfo - .where() - .walletIdEqualTo(walletId) - .findFirst(); + final walletInfo = + await mainDB.isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .findFirst(); Logging.instance.i( "Wallet.load loading" @@ -270,10 +269,7 @@ abstract class Wallet { required EthereumWallet ethWallet, required EthContract contract, }) { - final Wallet wallet = EthTokenWallet( - ethWallet, - contract, - ); + final Wallet wallet = EthTokenWallet(ethWallet, contract); wallet.prefs = ethWallet.prefs; wallet.nodeService = ethWallet.nodeService; @@ -287,27 +283,19 @@ abstract class Wallet { // ========== Static Util ==================================================== // secure storage key - static String mnemonicKey({ - required String walletId, - }) => + static String mnemonicKey({required String walletId}) => "${walletId}_mnemonic"; // secure storage key - static String mnemonicPassphraseKey({ - required String walletId, - }) => + static String mnemonicPassphraseKey({required String walletId}) => "${walletId}_mnemonicPassphrase"; // secure storage key - static String privateKeyKey({ - required String walletId, - }) => + static String privateKeyKey({required String walletId}) => "${walletId}_privateKey"; // secure storage key - static String getViewOnlyWalletDataSecStoreKey({ - required String walletId, - }) => + static String getViewOnlyWalletDataSecStoreKey({required String walletId}) => "${walletId}_viewOnlyWalletData"; //============================================================================ @@ -321,9 +309,7 @@ abstract class Wallet { required NodeService nodeService, required Prefs prefs, }) async { - final Wallet wallet = _loadWallet( - walletInfo: walletInfo, - ); + final Wallet wallet = _loadWallet(walletInfo: walletInfo); wallet.prefs = prefs; wallet.nodeService = nodeService; @@ -339,9 +325,7 @@ abstract class Wallet { .._walletId = walletInfo.walletId; } - static Wallet _loadWallet({ - required WalletInfo walletInfo, - }) { + static Wallet _loadWallet({required WalletInfo walletInfo}) { final net = walletInfo.coin.network; switch (walletInfo.coin.runtimeType) { case const (Banano): @@ -374,6 +358,9 @@ abstract class Wallet { case const (Ethereum): return EthereumWallet(net); + case const (Fact0rn): + return Fact0rnWallet(net); + case const (Firo): return FiroWallet(net); @@ -421,12 +408,11 @@ abstract class Wallet { _periodicPingCheck(); // then periodically check - _networkAliveTimer = Timer.periodic( - Constants.networkAliveTimerDuration, - (_) async { - _periodicPingCheck(); - }, - ); + _networkAliveTimer = Timer.periodic(Constants.networkAliveTimerDuration, ( + _, + ) async { + _periodicPingCheck(); + }); } void _periodicPingCheck() async { @@ -438,15 +424,12 @@ abstract class Wallet { final bool hasNetwork = await pingCheck(); if (_isConnected != hasNetwork) { - final NodeConnectionStatus status = hasNetwork - ? NodeConnectionStatus.connected - : NodeConnectionStatus.disconnected; + final NodeConnectionStatus status = + hasNetwork + ? NodeConnectionStatus.connected + : NodeConnectionStatus.disconnected; GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - status, - walletId, - cryptoCurrency, - ), + NodeConnectionStatusChangedEvent(status, walletId, cryptoCurrency), ); _isConnected = hasNetwork; @@ -518,7 +501,8 @@ abstract class Wallet { } NodeModel getCurrentNode() { - final node = nodeService.getPrimaryNodeFor(currency: cryptoCurrency) ?? + final node = + nodeService.getPrimaryNodeFor(currency: cryptoCurrency) ?? cryptoCurrency.defaultNode; return node; @@ -538,8 +522,9 @@ abstract class Wallet { ); if (shouldAutoSync) { - _periodicRefreshTimer ??= - Timer.periodic(const Duration(seconds: 150), (timer) async { + _periodicRefreshTimer ??= Timer.periodic(const Duration(seconds: 150), ( + timer, + ) async { // chain height check currently broken // if ((await chainHeight) != (await storedChainHeight)) { @@ -596,7 +581,8 @@ abstract class Wallet { } final start = DateTime.now(); - final viewOnly = this is ViewOnlyOptionInterface && + final viewOnly = + this is ViewOnlyOptionInterface && (this as ViewOnlyOptionInterface).isViewOnly; try { @@ -621,8 +607,9 @@ abstract class Wallet { final Set codesToCheck = {}; if (this is PaynymInterface && !viewOnly) { // isSegwit does not matter here at all - final myCode = - await (this as PaynymInterface).getPaymentCode(isSegwit: false); + final myCode = await (this as PaynymInterface).getPaymentCode( + isSegwit: false, + ); final nym = await PaynymIsApi().nym(myCode.toString()); if (nym.value != null) { @@ -685,8 +672,9 @@ abstract class Wallet { // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided. if (!viewOnly && this is PaynymInterface && codesToCheck.isNotEmpty) { - await (this as PaynymInterface) - .checkForNotificationTransactionsTo(codesToCheck); + await (this as PaynymInterface).checkForNotificationTransactionsTo( + codesToCheck, + ); // check utxos again for notification outputs await updateUTXOs(); } @@ -746,10 +734,11 @@ abstract class Wallet { // Check if there's another wallet of this coin on the sync list. final List walletIds = []; for (final id in prefs.walletIdsSyncOnStartup) { - final wallet = mainDB.isar.walletInfo - .where() - .walletIdEqualTo(id) - .findFirstSync()!; + final wallet = + mainDB.isar.walletInfo + .where() + .walletIdEqualTo(id) + .findFirstSync()!; if (wallet.coin == cryptoCurrency) { walletIds.add(id); @@ -802,17 +791,11 @@ abstract class Wallet { return await mainDB.isar.addresses .buildQuery
( whereClauses: [ - IndexWhereClause.equalTo( - indexName: r"walletId", - value: [walletId], - ), + IndexWhereClause.equalTo(indexName: r"walletId", value: [walletId]), ], filter: filterOperation, sortBy: [ - const SortProperty( - property: r"derivationIndex", - sort: Sort.desc, - ), + const SortProperty(property: r"derivationIndex", sort: Sort.desc), ], ) .findFirst(); diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index e46420fa0..72e4cc8e9 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -63,6 +63,7 @@ final List _supportedCoins = List.unmodifiable([ Ecash(CryptoCurrencyNetwork.main), Epiccash(CryptoCurrencyNetwork.main), Ethereum(CryptoCurrencyNetwork.main), + Fact0rn(CryptoCurrencyNetwork.main), Firo(CryptoCurrencyNetwork.main), Litecoin(CryptoCurrencyNetwork.main), Nano(CryptoCurrencyNetwork.main), From 3d25e8a0d28bf8a2b526a951bb1f49f35a5f965f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 5 May 2025 08:32:27 -0600 Subject: [PATCH 040/206] auto format --- lib/route_generator.dart | 58 +++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/lib/route_generator.dart b/lib/route_generator.dart index f2796a150..055669c54 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -1461,43 +1461,41 @@ class RouteGenerator { return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreWalletView.routeName: - if (args - is Tuple6) { + if (args is Tuple6) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreWalletView( - walletName: args.item1, - coin: args.item2, - seedWordsLength: args.item3, - restoreBlockHeight: args.item4, - mnemonicPassphrase: args.item5, - enableLelantusScanning: args.item6 ?? false, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreWalletView( + walletName: args.item1, + coin: args.item2, + seedWordsLength: args.item3, + restoreBlockHeight: args.item4, + mnemonicPassphrase: args.item5, + enableLelantusScanning: args.item6 ?? false, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreViewOnlyWalletView.routeName: - if (args is ({ - String walletName, - CryptoCurrency coin, - int restoreBlockHeight, - bool enableLelantusScanning, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreViewOnlyWalletView( - walletName: args.walletName, - coin: args.coin, - restoreBlockHeight: args.restoreBlockHeight, - enableLelantusScanning: args.enableLelantusScanning, - ), - settings: RouteSettings( - name: settings.name, - ), + if (args + is ({ + String walletName, + CryptoCurrency coin, + int restoreBlockHeight, + bool enableLelantusScanning, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => RestoreViewOnlyWalletView( + walletName: args.walletName, + coin: args.coin, + restoreBlockHeight: args.restoreBlockHeight, + enableLelantusScanning: args.enableLelantusScanning, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); From ce0bcadb9ec0b4c7236e169bfc7737d83066f58f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 5 May 2025 11:34:49 -0600 Subject: [PATCH 041/206] add static overflow row widget --- .../static_overflow_row/measure_size.dart | 27 ++++++ .../static_overflow_row.dart | 97 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 lib/widgets/static_overflow_row/measure_size.dart create mode 100644 lib/widgets/static_overflow_row/static_overflow_row.dart diff --git a/lib/widgets/static_overflow_row/measure_size.dart b/lib/widgets/static_overflow_row/measure_size.dart new file mode 100644 index 000000000..d6d9f9708 --- /dev/null +++ b/lib/widgets/static_overflow_row/measure_size.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +class MeasureSize extends StatefulWidget { + const MeasureSize({super.key, required this.onChange, required this.child}); + + final ValueChanged onChange; + final Widget child; + + @override + State createState() => _MeasureSizeState(); +} + +class _MeasureSizeState extends State { + Size? previous; + + @override + Widget build(BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) { + final size = context.size; + if (size != null && previous != size) { + previous = size; + widget.onChange(size); + } + }); + return widget.child; + } +} diff --git a/lib/widgets/static_overflow_row/static_overflow_row.dart b/lib/widgets/static_overflow_row/static_overflow_row.dart new file mode 100644 index 000000000..3b3189343 --- /dev/null +++ b/lib/widgets/static_overflow_row/static_overflow_row.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import 'measure_size.dart'; + +class StaticOverflowRow extends StatefulWidget { + final List children; + final Widget Function(int hiddenCount) overflowBuilder; + + const StaticOverflowRow({ + super.key, + required this.children, + required this.overflowBuilder, + }); + + @override + State createState() => _StaticOverflowRowState(); +} + +class _StaticOverflowRowState extends State { + final Map _itemSizes = {}; + Size? _overflowSize; + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + final childCount = widget.children.length; + + // Still measuring + if (_itemSizes.length < childCount || _overflowSize == null) { + return Row( + children: [ + ...List.generate(childCount, (i) { + return MeasureSize( + onChange: (size) => _itemSizes[i] = size, + child: KeyedSubtree( + key: ValueKey("item-$i"), + child: widget.children[i], + ), + ); + }), + MeasureSize( + onChange: (size) => _overflowSize = size, + child: KeyedSubtree( + key: const ValueKey("overflow"), + child: widget.overflowBuilder(0), + ), + ), + ], + ); + } + + final List visible = []; + double usedWidth = 0; + + // Try first pass without overflow + for (int i = 0; i < childCount; i++) { + final itemSize = _itemSizes[i]!; + if (usedWidth + itemSize.width <= constraints.maxWidth) { + visible.add(widget.children[i]); + usedWidth += itemSize.width; + } else { + // Not all children fit. Overflow required + visible.clear(); + usedWidth = 0; + int overflowCount = 0; + + for (int j = 0; j < childCount; j++) { + final size = _itemSizes[j]!; + final needsOverflow = j < childCount - 1; + final canFit = + usedWidth + + size.width + + (needsOverflow ? _overflowSize!.width : 0) <= + constraints.maxWidth; + + if (canFit) { + visible.add(widget.children[j]); + + usedWidth += size.width; + } else { + overflowCount = childCount - j; + break; + } + } + + // Add overflow + visible.add(widget.overflowBuilder(overflowCount)); + break; + } + } + + return Row(children: visible); + }, + ); + } +} From dddf2df60afc413acdf5239cbcf14f93749a2bed Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 6 May 2025 08:06:15 -0600 Subject: [PATCH 042/206] update spark names electrumx calls --- lib/electrumx_rpc/electrumx_client.dart | 59 +++++++++++++++++-- .../buy_spark_name_option_widget.dart | 11 +++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index 9df7ed791..3852d9be9 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -1132,7 +1132,9 @@ class ElectrumXClient { } } - Future> getSparkNames({String? requestID}) async { + Future> getSparkNames({ + String? requestID, + }) async { try { final start = DateTime.now(); await checkElectrumAdapter(); @@ -1143,13 +1145,62 @@ class ElectrumXClient { final response = await request(requestID: requestID, command: command); + if (response is List) { + Logging.instance.d( + "Finished ElectrumXClient.getSparkNames(). " + "names.length: ${response.length}" + "Duration=${DateTime.now().difference(start)}", + ); + + return response + .map( + (e) => ( + name: e["name"] as String, + address: e["address"] as String, + ), + ) + .toList(); + } else if (response["error"] != null) { + Logging.instance.d(response); + throw Exception(response["error"].toString()); + } else { + throw Exception("Failed to parse getSparkNames response: $response"); + } + } catch (e) { + rethrow; + } + } + + Future<({String address, int validUntil, String additionalInfo})> + getSparkNameData({required String sparkName, String? requestID}) async { + try { + final start = DateTime.now(); + await checkElectrumAdapter(); + const command = "spark.getsparknamedata"; + Logging.instance.d( + "[${getElectrumAdapter()?.host}] => attempting to fetch $command...", + ); + + final response = await request( + requestID: requestID, + command: command, + args: [sparkName], + ); + Logging.instance.d( - "Finished ElectrumXClient.getSparkNames(). " - "coins.length: ${(response as List).length}" + "Finished ElectrumXClient.getSparkNameData(). " "Duration=${DateTime.now().difference(start)}", ); + if (response["error"] != null) { + Logging.instance.d(response); + throw Exception(response["error"].toString()); + } - return response.cast(); + return ( + address: response["address"] as String, + validUntil: response["validUntil"] as int, + additionalInfo: response["additionalInfo"] as String, + ); } catch (e) { rethrow; } diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart index b0ad03a38..04e0f6fb6 100644 --- a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -44,9 +44,14 @@ class _BuySparkNameWidgetState extends ConsumerState { final wallet = ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; - final names = await wallet.electrumXClient.getSparkNames(); - - return !names.map((e) => e.toLowerCase()).contains(name.toLowerCase()); + try { + await wallet.electrumXClient.getSparkNameData(sparkName: name); + // name exists + return false; + } catch (e) { + // name not found + return true; + } } bool _lookupLock = false; From 6c7ffc7eb9f94db3b27ef15c8f0e84c1dc4c69e8 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 6 May 2025 10:22:45 -0600 Subject: [PATCH 043/206] WIP view spark names --- .../buy_spark_name_option_widget.dart | 12 +- .../manage_spark_names_option_widget.dart | 127 +++++++++--------- 2 files changed, 67 insertions(+), 72 deletions(-) diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart index 04e0f6fb6..d2c674419 100644 --- a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -122,7 +122,6 @@ class _BuySparkNameWidgetState extends ConsumerState { @override Widget build(BuildContext context) { - final double dotBitBoxLength = Util.isDesktop ? 100 : 74; return Column( crossAxisAlignment: Util.isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, @@ -140,13 +139,8 @@ class _BuySparkNameWidgetState extends ConsumerState { Theme.of( context, ).extension()!.textFieldDefaultBG, - borderRadius: BorderRadius.only( - topLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), // Adjust radius as needed - bottomLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), + borderRadius: BorderRadius.all( + Radius.circular(Constants.size.circularBorderRadius), ), ), child: Row( @@ -206,7 +200,7 @@ class _BuySparkNameWidgetState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.end, children: [ Padding( - padding: EdgeInsets.only(right: dotBitBoxLength), + padding: const EdgeInsets.only(right: 5), child: Builder( builder: (context) { final length = _nameController.text.length; diff --git a/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart index deece1a4e..3e7ee564d 100644 --- a/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart @@ -1,14 +1,15 @@ -import 'dart:convert'; +import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; -import 'package:namecoin/namecoin.dart'; -import '../../../models/isar/models/blockchain_data/utxo.dart'; +import '../../../models/isar/models/blockchain_data/address.dart'; +import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../providers/db/main_db_provider.dart'; +import '../../../providers/global/wallets_provider.dart'; import '../../../utilities/util.dart'; -import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import 'owned_spark_name_card.dart'; class ManageSparkNamesOptionWidget extends ConsumerStatefulWidget { @@ -23,76 +24,76 @@ class ManageSparkNamesOptionWidget extends ConsumerStatefulWidget { class _ManageSparkNamesWidgetState extends ConsumerState { - double _tempWidth = 0; - double? _width; - int _count = 0; + StreamSubscription>? _streamSubscription; + final Set<({String address, String name})> _myNames = {}; - void _sillyHack(double value, int length) { - if (value > _tempWidth) _tempWidth = value; - _count++; - if (_count == length) { + void _updateNames() async { + final wallet = + ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; + final names = await wallet.electrumXClient.getSparkNames(); + final myAddresses = + await wallet.mainDB.isar.addresses + .where() + .walletIdEqualTo(widget.walletId) + .filter() + .typeEqualTo(AddressType.spark) + .and() + .subTypeEqualTo(AddressSubType.receiving) + .valueProperty() + .findAll(); + + names.retainWhere((e) => myAddresses.contains(e.name)); + + if (names.length != _myNames.length) { WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - setState(() { - _width = _tempWidth; - _tempWidth = 0; - }); - } + setState(() { + _myNames.addAll(names); + }); }); } } @override - Widget build(BuildContext context) { - final height = ref.watch(pWalletChainHeight(widget.walletId)); - return StreamBuilder( - stream: ref.watch( - mainDBProvider.select( - (s) => s.isar.utxos - .where() - .walletIdEqualTo(widget.walletId) - .filter() - .otherDataIsNotNull() - .watch(fireImmediately: true), - ), - ), - builder: (context, snapshot) { - List<(UTXO, OpNameData)> list = []; - if (snapshot.hasData) { - list = snapshot.data! - .map((utxo) { - final data = jsonDecode(utxo.otherData!) as Map; + void initState() { + super.initState(); - final nameData = - jsonDecode(data["nameOpData"] as String) as Map; + _streamSubscription = ref + .read(mainDBProvider) + .isar + .transactionV2s + .where() + .walletIdEqualTo(widget.walletId) + .watch(fireImmediately: true) + .listen((event) { + if (mounted) { + _updateNames(); + } + }); + } - return ( - utxo, - OpNameData(nameData.cast(), utxo.blockHeight ?? height), - ); - }) - .toList(growable: false); - } + @override + void dispose() { + _streamSubscription?.cancel(); + super.dispose(); + } - return Column( - children: [ - ...list.map( - (e) => Padding( - padding: const EdgeInsets.only(bottom: 10), - child: OwnedSparkNameCard( - key: ValueKey(e), - utxo: e.$1, - opNameData: e.$2, - firstColWidth: _width, - calculatedFirstColWidth: - (value) => _sillyHack(value, list.length), - ), - ), + @override + Widget build(BuildContext context) { + return Column( + children: [ + ..._myNames.map( + (e) => Padding( + padding: const EdgeInsets.only(bottom: 10), + child: OwnedSparkNameCard( + key: ValueKey(e), + name: e.name, + address: e.address, + walletId: widget.walletId, ), - SizedBox(height: Util.isDesktop ? 14 : 6), - ], - ); - }, + ), + ), + SizedBox(height: Util.isDesktop ? 14 : 6), + ], ); } } From 836ff9e10b2978dd0a7a779239a106f53b24ff27 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 7 May 2025 11:17:10 -0600 Subject: [PATCH 044/206] Spark names gui and storage using drift with sqlite for caching --- lib/db/drift/database.dart | 87 +++ lib/db/drift/database.g.dart | 459 +++++++++++++ .../spark_names/buy_spark_name_view.dart | 289 +++++--- .../spark_names/spark_names_home_view.dart | 53 +- .../buy_spark_name_option_widget.dart | 35 +- .../manage_spark_names_option_widget.dart | 101 +-- .../sub_widgets/owned_spark_name_card.dart | 173 +---- .../sub_widgets/spark_name_details.dart | 623 ++++++++---------- lib/providers/db/drift_provider.dart | 17 + lib/providers/providers.dart | 4 +- lib/route_generator.dart | 28 + lib/utilities/stack_file_system.dart | 13 + .../spark_interface.dart | 65 ++ pubspec.lock | 58 +- scripts/app_config/templates/pubspec.template | 8 +- test/cached_electrumx_test.mocks.dart | 61 ++ .../bitcoin/bitcoin_wallet_test.mocks.dart | 61 ++ .../bitcoincash_wallet_test.mocks.dart | 61 ++ .../dogecoin/dogecoin_wallet_test.mocks.dart | 61 ++ .../namecoin/namecoin_wallet_test.mocks.dart | 61 ++ .../particl/particl_wallet_test.mocks.dart | 61 ++ 21 files changed, 1662 insertions(+), 717 deletions(-) create mode 100644 lib/db/drift/database.dart create mode 100644 lib/db/drift/database.g.dart create mode 100644 lib/providers/db/drift_provider.dart diff --git a/lib/db/drift/database.dart b/lib/db/drift/database.dart new file mode 100644 index 000000000..36cb67150 --- /dev/null +++ b/lib/db/drift/database.dart @@ -0,0 +1,87 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2025 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2025-05-06 + * + */ + +import 'dart:async'; + +import 'package:drift/drift.dart'; +import 'package:drift_flutter/drift_flutter.dart'; +import 'package:path/path.dart' as path; + +import '../../utilities/stack_file_system.dart'; + +part 'database.g.dart'; + +abstract final class Drift { + static bool _didInit = false; + + static final Map _map = {}; + + static WalletDatabase get(String walletId) { + if (!_didInit) { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + _didInit = true; + } + + return _map[walletId] ??= WalletDatabase._(walletId); + } +} + +class SparkNames extends Table { + TextColumn get name => + text().customConstraint("UNIQUE NOT NULL COLLATE NOCASE")(); + TextColumn get address => text()(); + IntColumn get validUntil => integer()(); + TextColumn get additionalInfo => text().nullable()(); + + @override + Set get primaryKey => {name}; +} + +@DriftDatabase(tables: [SparkNames]) +final class WalletDatabase extends _$WalletDatabase { + WalletDatabase._(String walletId, [QueryExecutor? executor]) + : super(executor ?? _openConnection(walletId)); + + @override + int get schemaVersion => 1; + + static QueryExecutor _openConnection(String walletId) { + return driftDatabase( + name: walletId, + native: DriftNativeOptions( + shareAcrossIsolates: true, + databasePath: () async { + final dir = await StackFileSystem.applicationDriftDirectory(); + return path.join(dir.path, "wallets", walletId, "$walletId.db"); + }, + ), + ); + } + + Future upsertSparkNames( + List< + ({String name, String address, int validUntil, String? additionalInfo}) + > + names, + ) async { + await transaction(() async { + for (final name in names) { + await into(sparkNames).insertOnConflictUpdate( + SparkNamesCompanion( + name: Value(name.name), + address: Value(name.address), + validUntil: Value(name.validUntil), + additionalInfo: Value(name.additionalInfo), + ), + ); + } + }); + } +} diff --git a/lib/db/drift/database.g.dart b/lib/db/drift/database.g.dart new file mode 100644 index 000000000..42113b071 --- /dev/null +++ b/lib/db/drift/database.g.dart @@ -0,0 +1,459 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'database.dart'; + +// ignore_for_file: type=lint +class $SparkNamesTable extends SparkNames + with TableInfo<$SparkNamesTable, SparkName> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SparkNamesTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'UNIQUE NOT NULL COLLATE NOCASE'); + static const VerificationMeta _addressMeta = + const VerificationMeta('address'); + @override + late final GeneratedColumn address = GeneratedColumn( + 'address', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _validUntilMeta = + const VerificationMeta('validUntil'); + @override + late final GeneratedColumn validUntil = GeneratedColumn( + 'valid_until', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _additionalInfoMeta = + const VerificationMeta('additionalInfo'); + @override + late final GeneratedColumn additionalInfo = GeneratedColumn( + 'additional_info', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => + [name, address, validUntil, additionalInfo]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'spark_names'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('name')) { + context.handle( + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('address')) { + context.handle(_addressMeta, + address.isAcceptableOrUnknown(data['address']!, _addressMeta)); + } else if (isInserting) { + context.missing(_addressMeta); + } + if (data.containsKey('valid_until')) { + context.handle( + _validUntilMeta, + validUntil.isAcceptableOrUnknown( + data['valid_until']!, _validUntilMeta)); + } else if (isInserting) { + context.missing(_validUntilMeta); + } + if (data.containsKey('additional_info')) { + context.handle( + _additionalInfoMeta, + additionalInfo.isAcceptableOrUnknown( + data['additional_info']!, _additionalInfoMeta)); + } + return context; + } + + @override + Set get $primaryKey => {name}; + @override + SparkName map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SparkName( + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + address: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}address'])!, + validUntil: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}valid_until'])!, + additionalInfo: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}additional_info']), + ); + } + + @override + $SparkNamesTable createAlias(String alias) { + return $SparkNamesTable(attachedDatabase, alias); + } +} + +class SparkName extends DataClass implements Insertable { + final String name; + final String address; + final int validUntil; + final String? additionalInfo; + const SparkName( + {required this.name, + required this.address, + required this.validUntil, + this.additionalInfo}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['address'] = Variable(address); + map['valid_until'] = Variable(validUntil); + if (!nullToAbsent || additionalInfo != null) { + map['additional_info'] = Variable(additionalInfo); + } + return map; + } + + SparkNamesCompanion toCompanion(bool nullToAbsent) { + return SparkNamesCompanion( + name: Value(name), + address: Value(address), + validUntil: Value(validUntil), + additionalInfo: additionalInfo == null && nullToAbsent + ? const Value.absent() + : Value(additionalInfo), + ); + } + + factory SparkName.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SparkName( + name: serializer.fromJson(json['name']), + address: serializer.fromJson(json['address']), + validUntil: serializer.fromJson(json['validUntil']), + additionalInfo: serializer.fromJson(json['additionalInfo']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'address': serializer.toJson(address), + 'validUntil': serializer.toJson(validUntil), + 'additionalInfo': serializer.toJson(additionalInfo), + }; + } + + SparkName copyWith( + {String? name, + String? address, + int? validUntil, + Value additionalInfo = const Value.absent()}) => + SparkName( + name: name ?? this.name, + address: address ?? this.address, + validUntil: validUntil ?? this.validUntil, + additionalInfo: + additionalInfo.present ? additionalInfo.value : this.additionalInfo, + ); + SparkName copyWithCompanion(SparkNamesCompanion data) { + return SparkName( + name: data.name.present ? data.name.value : this.name, + address: data.address.present ? data.address.value : this.address, + validUntil: + data.validUntil.present ? data.validUntil.value : this.validUntil, + additionalInfo: data.additionalInfo.present + ? data.additionalInfo.value + : this.additionalInfo, + ); + } + + @override + String toString() { + return (StringBuffer('SparkName(') + ..write('name: $name, ') + ..write('address: $address, ') + ..write('validUntil: $validUntil, ') + ..write('additionalInfo: $additionalInfo') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(name, address, validUntil, additionalInfo); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SparkName && + other.name == this.name && + other.address == this.address && + other.validUntil == this.validUntil && + other.additionalInfo == this.additionalInfo); +} + +class SparkNamesCompanion extends UpdateCompanion { + final Value name; + final Value address; + final Value validUntil; + final Value additionalInfo; + final Value rowid; + const SparkNamesCompanion({ + this.name = const Value.absent(), + this.address = const Value.absent(), + this.validUntil = const Value.absent(), + this.additionalInfo = const Value.absent(), + this.rowid = const Value.absent(), + }); + SparkNamesCompanion.insert({ + required String name, + required String address, + required int validUntil, + this.additionalInfo = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name), + address = Value(address), + validUntil = Value(validUntil); + static Insertable custom({ + Expression? name, + Expression? address, + Expression? validUntil, + Expression? additionalInfo, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (address != null) 'address': address, + if (validUntil != null) 'valid_until': validUntil, + if (additionalInfo != null) 'additional_info': additionalInfo, + if (rowid != null) 'rowid': rowid, + }); + } + + SparkNamesCompanion copyWith( + {Value? name, + Value? address, + Value? validUntil, + Value? additionalInfo, + Value? rowid}) { + return SparkNamesCompanion( + name: name ?? this.name, + address: address ?? this.address, + validUntil: validUntil ?? this.validUntil, + additionalInfo: additionalInfo ?? this.additionalInfo, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (address.present) { + map['address'] = Variable(address.value); + } + if (validUntil.present) { + map['valid_until'] = Variable(validUntil.value); + } + if (additionalInfo.present) { + map['additional_info'] = Variable(additionalInfo.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SparkNamesCompanion(') + ..write('name: $name, ') + ..write('address: $address, ') + ..write('validUntil: $validUntil, ') + ..write('additionalInfo: $additionalInfo, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +abstract class _$WalletDatabase extends GeneratedDatabase { + _$WalletDatabase(QueryExecutor e) : super(e); + $WalletDatabaseManager get managers => $WalletDatabaseManager(this); + late final $SparkNamesTable sparkNames = $SparkNamesTable(this); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [sparkNames]; +} + +typedef $$SparkNamesTableCreateCompanionBuilder = SparkNamesCompanion Function({ + required String name, + required String address, + required int validUntil, + Value additionalInfo, + Value rowid, +}); +typedef $$SparkNamesTableUpdateCompanionBuilder = SparkNamesCompanion Function({ + Value name, + Value address, + Value validUntil, + Value additionalInfo, + Value rowid, +}); + +class $$SparkNamesTableFilterComposer + extends Composer<_$WalletDatabase, $SparkNamesTable> { + $$SparkNamesTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnFilters(column)); + + ColumnFilters get address => $composableBuilder( + column: $table.address, builder: (column) => ColumnFilters(column)); + + ColumnFilters get validUntil => $composableBuilder( + column: $table.validUntil, builder: (column) => ColumnFilters(column)); + + ColumnFilters get additionalInfo => $composableBuilder( + column: $table.additionalInfo, + builder: (column) => ColumnFilters(column)); +} + +class $$SparkNamesTableOrderingComposer + extends Composer<_$WalletDatabase, $SparkNamesTable> { + $$SparkNamesTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get address => $composableBuilder( + column: $table.address, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get validUntil => $composableBuilder( + column: $table.validUntil, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get additionalInfo => $composableBuilder( + column: $table.additionalInfo, + builder: (column) => ColumnOrderings(column)); +} + +class $$SparkNamesTableAnnotationComposer + extends Composer<_$WalletDatabase, $SparkNamesTable> { + $$SparkNamesTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get address => + $composableBuilder(column: $table.address, builder: (column) => column); + + GeneratedColumn get validUntil => $composableBuilder( + column: $table.validUntil, builder: (column) => column); + + GeneratedColumn get additionalInfo => $composableBuilder( + column: $table.additionalInfo, builder: (column) => column); +} + +class $$SparkNamesTableTableManager extends RootTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), + SparkName, + PrefetchHooks Function()> { + $$SparkNamesTableTableManager(_$WalletDatabase db, $SparkNamesTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SparkNamesTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SparkNamesTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$SparkNamesTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value name = const Value.absent(), + Value address = const Value.absent(), + Value validUntil = const Value.absent(), + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SparkNamesCompanion( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + createCompanionCallback: ({ + required String name, + required String address, + required int validUntil, + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SparkNamesCompanion.insert( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SparkNamesTableProcessedTableManager = ProcessedTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), + SparkName, + PrefetchHooks Function()>; + +class $WalletDatabaseManager { + final _$WalletDatabase _db; + $WalletDatabaseManager(this._db); + $$SparkNamesTableTableManager get sparkNames => + $$SparkNamesTableTableManager(_db, _db.sparkNames); +} diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart index 0371ec485..1ce0513d1 100644 --- a/lib/pages/spark_names/buy_spark_name_view.dart +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:isar/isar.dart'; import '../../../providers/providers.dart'; import '../../../utilities/amount/amount.dart'; @@ -14,6 +15,8 @@ import '../../../utilities/util.dart'; import '../../../wallets/models/tx_data.dart'; import '../../../widgets/desktop/primary_button.dart'; import '../../../widgets/stack_dialog.dart'; +import '../../db/drift/database.dart'; +import '../../models/isar/models/blockchain_data/address.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount_formatter.dart'; import '../../utilities/assets.dart'; @@ -25,6 +28,7 @@ import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/custom_buttons/blue_text_button.dart'; import '../../widgets/dialogs/s_dialog.dart'; import '../../widgets/rounded_white_container.dart'; import 'confirm_spark_name_transaction_view.dart'; @@ -34,10 +38,12 @@ class BuySparkNameView extends ConsumerStatefulWidget { super.key, required this.walletId, required this.name, + this.nameToRenew, }); final String walletId; final String name; + final SparkName? nameToRenew; static const routeName = "/buySparkNameView"; @@ -46,21 +52,57 @@ class BuySparkNameView extends ConsumerStatefulWidget { } class _BuySparkNameViewState extends ConsumerState { + final addressController = TextEditingController(); final additionalInfoController = TextEditingController(); + bool get isRenewal => widget.nameToRenew != null; + String get _title => isRenewal ? "Renew name" : "Buy name"; + int _years = 1; + bool _lockAddressFill = false; + Future _fillCurrentReceiving() async { + if (_lockAddressFill) return; + _lockAddressFill = true; + try { + final wallet = + ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; + final myAddress = await wallet.getCurrentReceivingSparkAddress(); + if (myAddress == null) { + throw Exception("No spark address found"); + } + addressController.text = myAddress.value; + } catch (e, s) { + Logging.instance.e("_fillCurrentReceiving", error: e, stackTrace: s); + } finally { + _lockAddressFill = false; + } + } + Future _preRegFuture() async { final wallet = ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; - final myAddress = await wallet.getCurrentReceivingSparkAddress(); - if (myAddress == null) { - throw Exception("No spark address found"); + + final myAddresses = + await wallet.mainDB.isar.addresses + .where() + .walletIdEqualTo(widget.walletId) + .filter() + .typeEqualTo(AddressType.spark) + .and() + .subTypeEqualTo(AddressSubType.receiving) + .valueProperty() + .findAll(); + + final chosenAddress = addressController.text; + + if (!myAddresses.contains(chosenAddress)) { + throw Exception("Address does not belong to this wallet"); } final txData = await wallet.prepareSparkNameTransaction( name: widget.name, - address: myAddress.value, + address: chosenAddress, years: _years, additionalInfo: additionalInfoController.text, ); @@ -129,9 +171,19 @@ class _BuySparkNameViewState extends ConsumerState { } } + @override + void initState() { + super.initState(); + if (isRenewal) { + additionalInfoController.text = widget.nameToRenew!.additionalInfo ?? ""; + addressController.text = widget.nameToRenew!.address; + } + } + @override void dispose() { additionalInfoController.dispose(); + addressController.dispose(); super.dispose(); } @@ -148,7 +200,7 @@ class _BuySparkNameViewState extends ConsumerState { leading: const AppBarBackButton(), titleSpacing: 0, title: Text( - "Buy name", + _title, style: STextStyles.navBarTitle(context), overflow: TextOverflow.ellipsis, ), @@ -181,42 +233,8 @@ class _BuySparkNameViewState extends ConsumerState { ? CrossAxisAlignment.start : CrossAxisAlignment.stretch, children: [ - if (!Util.isDesktop) - Text( - "Buy name", - style: - Util.isDesktop - ? STextStyles.desktopH3(context) - : STextStyles.pageTitleH2(context), - ), - SizedBox(height: Util.isDesktop ? 24 : 16), - // Row( - // mainAxisAlignment: - // Util.isDesktop - // ? MainAxisAlignment.center - // : MainAxisAlignment.start, - // children: [ - // Text( - // "Name registration will take approximately 2 to 4 hours.", - // style: - // Util.isDesktop - // ? STextStyles.w500_14(context).copyWith( - // color: - // Theme.of( - // context, - // ).extension()!.textDark3, - // ) - // : STextStyles.w500_12(context).copyWith( - // color: - // Theme.of( - // context, - // ).extension()!.textDark3, - // ), - // ), - // ], - // ), - // SizedBox(height: Util.isDesktop ? 24 : 16), RoundedWhiteContainer( + padding: EdgeInsets.all(Util.isDesktop ? 0 : 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -249,52 +267,117 @@ class _BuySparkNameViewState extends ConsumerState { ), SizedBox(height: Util.isDesktop ? 16 : 8), RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + padding: EdgeInsets.all(Util.isDesktop ? 0 : 12), + child: Column( children: [ - Text( - "Amount", - style: - Util.isDesktop - ? STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.infoItemLabel, - ) - : STextStyles.w500_12(context).copyWith( - color: - Theme.of( - context, - ).extension()!.infoItemLabel, - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Address", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ), + CustomTextButton( + text: "Use current", + onTap: _fillCurrentReceiving, + ), + ], ), - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - Amount.fromDecimal( - Decimal.fromInt( - kStandardSparkNamesFee[widget.name.length] * _years, - ), - fractionDigits: coin.fractionDigits, - ), - ), - style: - Util.isDesktop - ? STextStyles.w500_14(context) - : STextStyles.w500_12(context), + const SizedBox(height: 4), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + controller: addressController, + readOnly: isRenewal, + textAlignVertical: TextAlignVertical.center, + minLines: 1, + maxLines: 5, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.all(16), + hintStyle: STextStyles.fieldLabel(context), + hintText: "Address", + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + ), + ), ), ], ), ), SizedBox(height: Util.isDesktop ? 16 : 8), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Additional info", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ), + ], + ), + const SizedBox(height: 4), + RoundedWhiteContainer( + padding: EdgeInsets.all(Util.isDesktop ? 0 : 12), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + controller: additionalInfoController, + textAlignVertical: TextAlignVertical.center, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.all(16), + hintStyle: STextStyles.fieldLabel(context), + hintText: "Additional info", + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + ), + ), + ), + ), + ], + ), + SizedBox(height: Util.isDesktop ? 16 : 8), RoundedWhiteContainer( + padding: EdgeInsets.all(Util.isDesktop ? 0 : 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Register for", + "${isRenewal ? "Register" : "Renew"} for", style: Util.isDesktop ? STextStyles.w500_14(context).copyWith( @@ -387,31 +470,51 @@ class _BuySparkNameViewState extends ConsumerState { ), SizedBox(height: Util.isDesktop ? 16 : 8), RoundedWhiteContainer( - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - controller: additionalInfoController, - textAlignVertical: TextAlignVertical.center, - decoration: InputDecoration( - isDense: true, - contentPadding: const EdgeInsets.all(16), - hintStyle: STextStyles.fieldLabel(context), - hintText: "Additional info", - border: InputBorder.none, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, + padding: EdgeInsets.all(Util.isDesktop ? 0 : 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Cost", + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), ), - ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + Amount.fromDecimal( + Decimal.fromInt( + kStandardSparkNamesFee[widget.name.length] * _years, + ), + fractionDigits: coin.fractionDigits, + ), + ), + style: + Util.isDesktop + ? STextStyles.w500_14(context) + : STextStyles.w500_12(context), + ), + ], ), ), - SizedBox(height: Util.isDesktop ? 24 : 16), + SizedBox(height: Util.isDesktop ? 32 : 16), if (!Util.isDesktop) const Spacer(), PrimaryButton( - label: "Buy", - // width: Util.isDesktop ? 160 : double.infinity, + label: isRenewal ? "Renew" : "Buy", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: _prepareNameTx, ), diff --git a/lib/pages/spark_names/spark_names_home_view.dart b/lib/pages/spark_names/spark_names_home_view.dart index d4dbef2f9..e87889ce5 100644 --- a/lib/pages/spark_names/spark_names_home_view.dart +++ b/lib/pages/spark_names/spark_names_home_view.dart @@ -135,34 +135,37 @@ class _NamecoinNamesHomeViewState extends ConsumerState { ), ), const SizedBox(width: 24), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - Text( - "Names", - style: STextStyles.desktopTextExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, + Flexible( + child: SizedBox( + width: 520, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Text( + "Names", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + ], + ), + const SizedBox(height: 14), + Flexible( + child: SingleChildScrollView( + child: ManageSparkNamesOptionWidget( + walletId: widget.walletId, ), - ), - ], - ), - const SizedBox(height: 14), - Flexible( - child: SingleChildScrollView( - child: ManageSparkNamesOptionWidget( - walletId: widget.walletId, ), ), - ), - ], + ], + ), ), ), ], diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart index d2c674419..4ea12ae64 100644 --- a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -38,6 +38,7 @@ class _BuySparkNameWidgetState extends ConsumerState { final _nameFieldFocus = FocusNode(); bool _isAvailable = false; + bool _isInvalidCharacters = false; String? _lastLookedUpName; Future _checkIsAvailable(String name) async { @@ -79,20 +80,15 @@ class _BuySparkNameWidgetState extends ConsumerState { Logging.instance.i("LOOKUP RESULT: $result"); } catch (e, s) { - Logging.instance.e("_lookup failed", error: e, stackTrace: s); - - String? err; - if (e.toString().contains("Contains invalid characters")) { - err = "Contains invalid characters"; - } + const message = "Spark name lookup failed"; + Logging.instance.e(message, error: e, stackTrace: s); if (mounted) { await showDialog( context: context, builder: (_) => StackOkDialog( - title: "Spark name lookup failed", - message: err, + title: message, desktopPopRootNavigator: Util.isDesktop, maxWidth: Util.isDesktop ? 600 : null, ), @@ -184,7 +180,11 @@ class _BuySparkNameWidgetState extends ConsumerState { }, onChanged: (value) { // trigger look up button enabled/disabled state change - setState(() {}); + setState(() { + _isInvalidCharacters = + value.isNotEmpty && + !RegExp(kNameRegexString).hasMatch(value); + }); }, ), ), @@ -197,8 +197,18 @@ class _BuySparkNameWidgetState extends ConsumerState { ), const SizedBox(height: 4), Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: + _isInvalidCharacters + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.end, children: [ + if (_isInvalidCharacters) + Text( + "Invalid name", + style: STextStyles.w500_10(context).copyWith( + color: Theme.of(context).extension()!.textError, + ), + ), Padding( padding: const EdgeInsets.only(right: 5), child: Builder( @@ -221,8 +231,9 @@ class _BuySparkNameWidgetState extends ConsumerState { SizedBox(height: Util.isDesktop ? 24 : 16), SecondaryButton( label: "Lookup", - enabled: _nameController.text.isNotEmpty, - // width: Util.isDesktop ? 160 : double.infinity, + enabled: + _nameController.text.isNotEmpty && + RegExp(kNameRegexString).hasMatch(_nameController.text), buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: _lookup, ), diff --git a/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart index 3e7ee564d..18a554cee 100644 --- a/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/manage_spark_names_option_widget.dart @@ -1,15 +1,8 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:isar/isar.dart'; -import '../../../models/isar/models/blockchain_data/address.dart'; -import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; -import '../../../providers/db/main_db_provider.dart'; -import '../../../providers/global/wallets_provider.dart'; +import '../../../providers/db/drift_provider.dart'; import '../../../utilities/util.dart'; -import '../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import 'owned_spark_name_card.dart'; class ManageSparkNamesOptionWidget extends ConsumerStatefulWidget { @@ -24,76 +17,32 @@ class ManageSparkNamesOptionWidget extends ConsumerStatefulWidget { class _ManageSparkNamesWidgetState extends ConsumerState { - StreamSubscription>? _streamSubscription; - final Set<({String address, String name})> _myNames = {}; - - void _updateNames() async { - final wallet = - ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; - final names = await wallet.electrumXClient.getSparkNames(); - final myAddresses = - await wallet.mainDB.isar.addresses - .where() - .walletIdEqualTo(widget.walletId) - .filter() - .typeEqualTo(AddressType.spark) - .and() - .subTypeEqualTo(AddressSubType.receiving) - .valueProperty() - .findAll(); - - names.retainWhere((e) => myAddresses.contains(e.name)); - - if (names.length != _myNames.length) { - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _myNames.addAll(names); - }); - }); - } - } - - @override - void initState() { - super.initState(); - - _streamSubscription = ref - .read(mainDBProvider) - .isar - .transactionV2s - .where() - .walletIdEqualTo(widget.walletId) - .watch(fireImmediately: true) - .listen((event) { - if (mounted) { - _updateNames(); - } - }); - } - - @override - void dispose() { - _streamSubscription?.cancel(); - super.dispose(); - } - @override Widget build(BuildContext context) { - return Column( - children: [ - ..._myNames.map( - (e) => Padding( - padding: const EdgeInsets.only(bottom: 10), - child: OwnedSparkNameCard( - key: ValueKey(e), - name: e.name, - address: e.address, - walletId: widget.walletId, - ), - ), - ), - SizedBox(height: Util.isDesktop ? 14 : 6), - ], + final db = ref.watch(pDrift(widget.walletId)); + return StreamBuilder( + stream: db.select(db.sparkNames).watch(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column( + children: [ + ...snapshot.data!.map( + (e) => Padding( + padding: const EdgeInsets.only(bottom: 10), + child: OwnedSparkNameCard( + key: ValueKey(e), + name: e, + walletId: widget.walletId, + ), + ), + ), + SizedBox(height: Util.isDesktop ? 14 : 6), + ], + ); + } else { + return Container(); + } + }, ); } } diff --git a/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart index f49a5f904..ea8b89b5d 100644 --- a/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart +++ b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart @@ -1,17 +1,11 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:namecoin/namecoin.dart'; -import '../../../models/isar/models/isar_models.dart'; -import '../../../providers/global/secure_store_provider.dart'; +import '../../../db/drift/database.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../wallets/wallet/impl/namecoin_wallet.dart'; -import '../../../widgets/conditional_parent.dart'; import '../../../widgets/desktop/primary_button.dart'; import '../../../widgets/dialogs/s_dialog.dart'; import '../../../widgets/rounded_white_container.dart'; @@ -20,52 +14,34 @@ import 'spark_name_details.dart'; class OwnedSparkNameCard extends ConsumerStatefulWidget { const OwnedSparkNameCard({ super.key, - required this.opNameData, - required this.utxo, - this.firstColWidth, - this.calculatedFirstColWidth, + required this.name, + required this.walletId, }); - final OpNameData opNameData; - final UTXO utxo; - - final double? firstColWidth; - final void Function(double)? calculatedFirstColWidth; + final SparkName name; + final String walletId; @override ConsumerState createState() => _OwnedSparkNameCardState(); } class _OwnedSparkNameCardState extends ConsumerState { - String? constructedName, value; - (String, Color) _getExpiry(int currentChainHeight, StackColors theme) { final String message; final Color color; - if (widget.utxo.blockHash == null) { - message = "Expires in $blocksNameExpiration+ blocks"; - color = theme.accentColorGreen; - } else { - final remaining = widget.opNameData.expiredBlockLeft( - currentChainHeight, - false, - ); - final semiRemaining = widget.opNameData.expiredBlockLeft( - currentChainHeight, - true, - ); + final remaining = widget.name.validUntil - currentChainHeight; - if (remaining == null) { - color = theme.accentColorRed; - message = "Expired"; + if (remaining <= 0) { + color = theme.accentColorRed; + message = "Expired"; + } else { + message = "Expires in $remaining blocks"; + if (remaining < 1000) { + // todo change arbitrary 1000 to something else? + color = theme.accentColorYellow; } else { - message = "Expires in $remaining blocks"; - if (semiRemaining == null) { - color = theme.accentColorYellow; - } else { - color = theme.accentColorGreen; - } + color = theme.accentColorGreen; } } @@ -84,15 +60,15 @@ class _OwnedSparkNameCardState extends ConsumerState { builder: (context) => SDialog( child: SparkNameDetailsView( - utxoId: widget.utxo.id, - walletId: widget.utxo.walletId, + name: widget.name, + walletId: widget.walletId, ), ), ); } else { await Navigator.of(context).pushNamed( SparkNameDetailsView.routeName, - arguments: (widget.utxo.id, widget.utxo.walletId), + arguments: (name: widget.name, walletId: widget.walletId), ); } } finally { @@ -100,119 +76,34 @@ class _OwnedSparkNameCardState extends ConsumerState { } } - void _setName() { - try { - constructedName = widget.opNameData.constructedName; - value = widget.opNameData.value; - } catch (_) { - if (widget.opNameData.op == OpName.nameNew) { - ref - .read(secureStoreProvider) - .read( - key: nameSaltKeyBuilder( - widget.utxo.txid, - widget.utxo.walletId, - widget.utxo.vout, - ), - ) - .then((onValue) { - if (onValue != null) { - final data = - (jsonDecode(onValue) as Map).cast(); - WidgetsBinding.instance.addPostFrameCallback((_) { - constructedName = data["name"]!; - value = data["value"]!; - if (mounted) { - setState(() {}); - } - }); - } else { - WidgetsBinding.instance.addPostFrameCallback((_) { - constructedName = "UNKNOWN"; - value = ""; - if (mounted) { - setState(() {}); - } - }); - } - }); - } - } - } - - @override - void initState() { - super.initState(); - _setName(); - } - - double _callbackWidth = 0; - @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); final (message, color) = _getExpiry( - ref.watch(pWalletChainHeight(widget.utxo.walletId)), + ref.watch(pWalletChainHeight(widget.walletId)), Theme.of(context).extension()!, ); return RoundedWhiteContainer( + padding: + Util.isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ConditionalParent( - condition: widget.firstColWidth != null && Util.isDesktop, - builder: - (child) => ConstrainedBox( - constraints: BoxConstraints(maxWidth: widget.firstColWidth!), - child: child, - ), - child: ConditionalParent( - condition: widget.firstColWidth == null && Util.isDesktop, - builder: - (child) => LayoutBuilder( - builder: (context, constraints) { - if (widget.firstColWidth == null && - _callbackWidth != constraints.maxWidth) { - _callbackWidth = constraints.maxWidth; - widget.calculatedFirstColWidth?.call(_callbackWidth); - } - return ConstrainedBox( - constraints: BoxConstraints( - maxWidth: constraints.maxWidth, - ), - child: child, - ); - }, - ), - child: Padding( - padding: const EdgeInsets.only(right: 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SelectableText(constructedName ?? ""), - const SizedBox(height: 8), - SelectableText( - message, - style: STextStyles.w500_12( - context, - ).copyWith(color: color), - ), - ], - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SelectableText(widget.name.name), + const SizedBox(height: 8), + SelectableText( + message, + style: STextStyles.w500_12(context).copyWith(color: color), ), - ), + ], ), - if (Util.isDesktop) - Expanded( - child: SelectableText( - value ?? "", - style: STextStyles.w500_12(context), - ), - ), - if (Util.isDesktop) const SizedBox(width: 12), + const SizedBox(width: 12), PrimaryButton( label: "Details", buttonHeight: Util.isDesktop ? ButtonHeight.xs : ButtonHeight.l, diff --git a/lib/pages/spark_names/sub_widgets/spark_name_details.dart b/lib/pages/spark_names/sub_widgets/spark_name_details.dart index 3fe469cc8..3acaad8f5 100644 --- a/lib/pages/spark_names/sub_widgets/spark_name_details.dart +++ b/lib/pages/spark_names/sub_widgets/spark_name_details.dart @@ -1,37 +1,35 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:isar/isar.dart'; -import 'package:namecoin/namecoin.dart'; +import '../../../db/drift/database.dart'; import '../../../models/isar/models/isar_models.dart'; +import '../../../providers/db/drift_provider.dart'; import '../../../providers/db/main_db_provider.dart'; -import '../../../providers/global/secure_store_provider.dart'; -import '../../../providers/global/wallets_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../wallets/wallet/impl/namecoin_wallet.dart'; import '../../../widgets/background.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_buttons/simple_copy_button.dart'; import '../../../widgets/desktop/desktop_dialog_close_button.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/dialogs/s_dialog.dart'; import '../../../widgets/rounded_container.dart'; import '../../wallet_view/transaction_views/transaction_details_view.dart'; +import '../buy_spark_name_view.dart'; class SparkNameDetailsView extends ConsumerStatefulWidget { const SparkNameDetailsView({ super.key, - required this.utxoId, + required this.name, required this.walletId, }); static const routeName = "/sparkNameDetails"; - final Id utxoId; + final SparkName name; final String walletId; @override @@ -40,136 +38,117 @@ class SparkNameDetailsView extends ConsumerStatefulWidget { } class _SparkNameDetailsViewState extends ConsumerState { - late Stream streamUTXO; - UTXO? utxo; - OpNameData? opNameData; + // todo change arbitrary 1000 to something else? + static const _remainingMagic = 1000; - String? constructedName, value; + late Stream _nameStream; + late SparkName name; - Stream? streamLabel; + Stream? _labelStream; AddressLabel? label; - void setUtxo(UTXO? utxo, int currentHeight) { - if (utxo != null) { - this.utxo = utxo; - final data = jsonDecode(utxo.otherData!) as Map; - - final nameData = jsonDecode(data["nameOpData"] as String) as Map; - opNameData = OpNameData( - nameData.cast(), - utxo.blockHeight ?? currentHeight, - ); - - _setName(); - } - } - - void _setName() { - try { - constructedName = opNameData!.constructedName; - value = opNameData!.value; - } catch (_) { - if (opNameData?.op == OpName.nameNew) { - ref - .read(secureStoreProvider) - .read( - key: nameSaltKeyBuilder(utxo!.txid, widget.walletId, utxo!.vout), - ) - .then((onValue) { - if (onValue != null) { - final data = - (jsonDecode(onValue) as Map).cast(); - WidgetsBinding.instance.addPostFrameCallback((_) { - constructedName = data["name"]!; - value = data["value"]!; - if (mounted) { - setState(() {}); - } - }); - } else { - WidgetsBinding.instance.addPostFrameCallback((_) { - constructedName = "UNKNOWN"; - value = ""; - if (mounted) { - setState(() {}); - } - }); - } - }); - } - } - } - - (String, Color) _getExpiry(int currentChainHeight, StackColors theme) { + (String, Color, int) _getExpiry(int currentChainHeight, StackColors theme) { final String message; final Color color; - if (utxo?.blockHash == null) { - message = "Expires in $blocksNameExpiration+ blocks"; - color = theme.accentColorGreen; - } else { - final remaining = opNameData?.expiredBlockLeft(currentChainHeight, false); - final semiRemaining = opNameData?.expiredBlockLeft( - currentChainHeight, - true, - ); + final remaining = name.validUntil - currentChainHeight; - if (remaining == null) { - color = theme.accentColorRed; - message = "Expired"; + if (remaining <= 0) { + color = theme.accentColorRed; + message = "Expired"; + } else { + message = "Expires in $remaining blocks"; + if (remaining < _remainingMagic) { + color = theme.accentColorYellow; } else { - message = "Expires in $remaining blocks"; - if (semiRemaining == null) { - color = theme.accentColorYellow; - } else { - color = theme.accentColorGreen; - } + color = theme.accentColorGreen; } } - return (message, color); + return (message, color, remaining); } - bool _checkConfirmedUtxo(int currentHeight) { - return (ref.read(pWallets).getWallet(widget.walletId) as NamecoinWallet) - .checkUtxoConfirmed(utxo!, currentHeight); + bool _lock = false; + + Future _renew() async { + if (_lock) return; + _lock = true; + try { + if (Util.isDesktop) { + await showDialog( + context: context, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Renew name", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: BuySparkNameView( + walletId: widget.walletId, + name: name.name, + nameToRenew: name, + ), + ), + ], + ), + ), + ), + ); + } else { + await Navigator.of(context).pushNamed( + BuySparkNameView.routeName, + arguments: ( + walletId: widget.walletId, + name: name.name, + nameToRenew: name, + ), + ); + } + } finally { + _lock = false; + } } @override void initState() { super.initState(); + name = widget.name; - setUtxo( - ref - .read(mainDBProvider) - .isar - .utxos - .where() - .idEqualTo(widget.utxoId) - .findFirstSync(), - ref.read(pWalletChainHeight(widget.walletId)), - ); + label = ref + .read(mainDBProvider) + .getAddressLabelSync(widget.walletId, name.address); - _setName(); - - if (utxo?.address != null) { - label = ref - .read(mainDBProvider) - .getAddressLabelSync(widget.walletId, utxo!.address!); - - if (label != null) { - streamLabel = ref.read(mainDBProvider).watchAddressLabel(id: label!.id); - } + if (label != null) { + _labelStream = ref.read(mainDBProvider).watchAddressLabel(id: label!.id); } - streamUTXO = ref.read(mainDBProvider).watchUTXO(id: widget.utxoId); + final db = ref.read(pDrift(widget.walletId)); + + _nameStream = + (db.select(db.sparkNames) + ..where((e) => e.name.equals(name.name))).watchSingleOrNull(); } @override Widget build(BuildContext context) { final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); - final (message, color) = _getExpiry( + final (message, color, remaining) = _getExpiry( currentHeight, Theme.of(context).extension()!, ); @@ -185,7 +164,7 @@ class _SparkNameDetailsViewState extends ConsumerState { // Theme.of(context).extension()!.background, leading: const AppBarBackButton(), title: Text( - "Domain details", + "Spark name details", style: STextStyles.navBarTitle(context), ), ), @@ -221,7 +200,7 @@ class _SparkNameDetailsViewState extends ConsumerState { Padding( padding: const EdgeInsets.only(left: 32), child: Text( - "Domain details", + "Spark name details", style: STextStyles.desktopH3(context), ), ), @@ -250,239 +229,152 @@ class _SparkNameDetailsViewState extends ConsumerState { ); }, child: StreamBuilder( - stream: streamUTXO, + stream: _nameStream, builder: (context, snapshot) { if (snapshot.hasData) { - setUtxo(snapshot.data!, currentHeight); + name = snapshot.data!; } - return utxo == null - ? Center( - child: Text( - "Missing output. Was it used recently?", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.accentColorRed, - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedContainer( + padding: const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SelectableText( + name.name, + style: + Util.isDesktop + ? STextStyles.pageTitleH2(context) + : STextStyles.w500_14(context), + ), + ], ), - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // if (!isDesktop) - // const SizedBox( - // height: 10, - // ), - RoundedContainer( - padding: const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Row( + ), + + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SelectableText( - constructedName ?? "", - style: STextStyles.pageTitleH2(context), - ), - if (Util.isDesktop) - SelectableText( - opNameData!.op.name, - style: STextStyles.w500_14(context), - ), - ], - ), - if (!Util.isDesktop) - SelectableText( - opNameData!.op.name, - style: STextStyles.w500_14(context), + Text( + "Address", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), - ], - ), - ), - const _Div(), - RoundedContainer( - padding: - Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Value", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, - ), - ), - ], - ), - const SizedBox(height: 4), - SelectableText( - value ?? "", - style: STextStyles.w500_14(context), ), - ], - ), - ), - const _Div(), - RoundedContainer( - padding: Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Address", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, - ), - ), - Util.isDesktop - ? IconCopyButton(data: utxo!.address!) - : SimpleCopyButton(data: utxo!.address!), - ], - ), - const SizedBox(height: 4), - SelectableText( - utxo!.address!, - style: STextStyles.w500_14(context), - ), + ? IconCopyButton(data: name.address) + : SimpleCopyButton(data: name.address), ], ), - ), - if (label != null && label!.value.isNotEmpty) const _Div(), - if (label != null && label!.value.isNotEmpty) - RoundedContainer( - padding: - Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Address label", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - Util.isDesktop - ? IconCopyButton(data: label!.value) - : SimpleCopyButton(data: label!.value), - ], - ), - const SizedBox(height: 4), - SelectableText( - label!.value, - style: STextStyles.w500_14(context), - ), - ], - ), + const SizedBox(height: 4), + SelectableText( + name.address, + style: STextStyles.w500_14(context), ), - const _Div(), - RoundedContainer( - padding: - Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + ], + ), + ), + if (_labelStream != null) + StreamBuilder( + stream: _labelStream!, + builder: (context, snapshot) { + label = snapshot.data; + + return (label != null && label!.value.isNotEmpty) + ? Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Transaction ID", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + const _Div(), + + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Address label", + style: STextStyles.w500_14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + Util.isDesktop + ? IconCopyButton(data: label!.value) + : SimpleCopyButton( + data: label!.value, + ), + ], + ), + const SizedBox(height: 4), + SelectableText( + label!.value, + style: STextStyles.w500_14(context), + ), + ], ), ), - Util.isDesktop - ? IconCopyButton(data: utxo!.txid) - : SimpleCopyButton(data: utxo!.txid), ], - ), - const SizedBox(height: 4), - SelectableText( - utxo!.txid, - style: STextStyles.w500_14(context), - ), - ], - ), - ), - const _Div(), - RoundedContainer( - padding: - Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, - child: Column( + ) + : const SizedBox(width: 0, height: 0); + }, + ), + + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -504,42 +396,49 @@ class _SparkNameDetailsViewState extends ConsumerState { ), ], ), - ), - const _Div(), - RoundedContainer( - padding: - Util.isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - Util.isDesktop - ? Colors.transparent - : Theme.of( + if (remaining < _remainingMagic) + PrimaryButton( + label: "Renew", + buttonHeight: + Util.isDesktop ? ButtonHeight.xs : ButtonHeight.l, + onPressed: _renew, + ), + ], + ), + ), + const _Div(), + RoundedContainer( + padding: + Util.isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: + Util.isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Additional info", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( context, - ).extension()!.popupBG, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", - style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, - ), - ), - const SizedBox(height: 4), - SelectableText( - "${utxo!.getConfirmations(currentHeight)}", - style: STextStyles.w500_14(context), - ), - ], + ).extension()!.textSubtitle1, + ), ), - ), - ], - ); + const SizedBox(height: 4), + SelectableText( + name.additionalInfo ?? "", + style: STextStyles.w500_14(context), + ), + ], + ), + ), + ], + ); }, ), ), diff --git a/lib/providers/db/drift_provider.dart b/lib/providers/db/drift_provider.dart new file mode 100644 index 000000000..658dd5bc7 --- /dev/null +++ b/lib/providers/db/drift_provider.dart @@ -0,0 +1,17 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2025 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2025-05-06 + * + */ + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../db/drift/database.dart'; + +final pDrift = Provider.family( + (ref, walletId) => Drift.get(walletId), +); diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart index e6e9ef20b..0f2f12343 100644 --- a/lib/providers/providers.dart +++ b/lib/providers/providers.dart @@ -11,6 +11,8 @@ export './buy/buy_form_state_provider.dart'; export './buy/simplex_initial_load_status.dart'; export './buy/simplex_provider.dart'; +export './db/drift_provider.dart'; +export './db/main_db_provider.dart'; export './exchange/changenow_initial_load_status.dart'; export './exchange/exchange_flow_is_active_state_provider.dart'; export './exchange/exchange_form_state_provider.dart'; @@ -25,6 +27,7 @@ export './global/price_provider.dart'; export './global/should_show_lockscreen_on_resume_state_provider.dart'; export './global/wallets_provider.dart'; export './global/wallets_service_provider.dart'; +export './progress_report/xelis_table_progress_provider.dart'; export './ui/add_wallet_selected_coin_provider.dart'; export './ui/check_box_state_provider.dart'; export './ui/home_view_index_provider.dart'; @@ -32,4 +35,3 @@ export './ui/verify_recovery_phrase/correct_word_provider.dart'; export './ui/verify_recovery_phrase/random_index_provider.dart'; export './ui/verify_recovery_phrase/selected_word_provider.dart'; export './wallet/transaction_note_provider.dart'; -export './progress_report/xelis_table_progress_provider.dart'; diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 055669c54..fb0e79c86 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -13,6 +13,7 @@ import 'package:flutter/material.dart'; import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; +import 'db/drift/database.dart'; import 'models/add_wallet_list_entity/add_wallet_list_entity.dart'; import 'models/add_wallet_list_entity/sub_classes/eth_token_entity.dart'; import 'models/buy/response_objects/quote.dart'; @@ -149,6 +150,7 @@ import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_setting import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart'; import 'pages/spark_names/buy_spark_name_view.dart'; import 'pages/spark_names/spark_names_home_view.dart'; +import 'pages/spark_names/sub_widgets/spark_name_details.dart'; import 'pages/special/firo_rescan_recovery_error_dialog.dart'; import 'pages/stack_privacy_calls.dart'; import 'pages/token_view/my_tokens_view.dart'; @@ -824,6 +826,32 @@ class RouteGenerator { BuySparkNameView(walletId: args.walletId, name: args.name), settings: RouteSettings(name: settings.name), ); + } else if (args + is ({String walletId, String name, SparkName? nameToRenew})) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => BuySparkNameView( + walletId: args.walletId, + name: args.name, + nameToRenew: args.nameToRenew, + ), + settings: RouteSettings(name: settings.name), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + + case SparkNameDetailsView.routeName: + if (args is ({String walletId, SparkName name})) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => SparkNameDetailsView( + walletId: args.walletId, + name: args.name, + ), + settings: RouteSettings(name: settings.name), + ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index 795ea9720..14cb0fae0 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -96,6 +96,19 @@ abstract class StackFileSystem { } } + static Future applicationDriftDirectory() async { + final root = await applicationRootDirectory(); + if (_createSubDirs) { + final dir = Directory("${root.path}/drift"); + if (!dir.existsSync()) { + await dir.create(); + } + return dir; + } else { + return root; + } + } + // Not used in general now. See applicationFiroCacheSQLiteDirectory() // static Future applicationSQLiteDirectory() async { // final root = await applicationRootDirectory(); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index d2d0a058c..b1cd31c95 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -12,6 +12,7 @@ import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart'; import 'package:isar/isar.dart'; import 'package:logger/logger.dart'; +import '../../../db/drift/database.dart' show Drift; import '../../../db/sqlite/firo_cache.dart'; import '../../../models/balance.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; @@ -1109,6 +1110,8 @@ mixin SparkInterface .isUsedEqualTo(false) .findAll(); + final sparkNamesUpdateFuture = refreshSparkNames(); + final total = Amount( rawValue: unusedCoins .map((e) => e.value) @@ -1140,6 +1143,8 @@ mixin SparkInterface newBalance: sparkBalance, isar: mainDB.isar, ); + + await sparkNamesUpdateFuture; } catch (e, s) { Logging.instance.e( "$runtimeType $walletId ${info.name}: ", @@ -1194,6 +1199,66 @@ mixin SparkInterface } } + Future refreshSparkNames() async { + try { + Logging.instance.i("Refreshing spark names for $walletId ${info.name}"); + + final db = Drift.get(walletId); + final myNameStrings = + await db.managers.sparkNames.map((e) => e.name).get(); + final names = await electrumXClient.getSparkNames(); + final myAddresses = + await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.spark) + .and() + .subTypeEqualTo(AddressSubType.receiving) + .valueProperty() + .findAll(); + + names.retainWhere( + (e) => + myAddresses.contains(e.address) && !myNameStrings.contains(e.name), + ); + Logging.instance.d("Found $names new spark names"); + + if (names.isNotEmpty) { + final List< + ({ + String name, + String address, + int validUntil, + String? additionalInfo, + }) + > + data = []; + + for (final name in names) { + final info = await electrumXClient.getSparkNameData( + sparkName: name.name, + ); + + data.add(( + name: name.name, + address: name.address, + validUntil: info.validUntil, + additionalInfo: info.additionalInfo, + )); + } + + await db.upsertSparkNames(data); + } + } catch (e, s) { + Logging.instance.e( + "refreshing spark names for $walletId \"${info.name}\" failed", + error: e, + stackTrace: s, + ); + } + } + // modelled on CSparkWallet::CreateSparkMintTransactions https://github.com/firoorg/firo/blob/39c41e5e7ec634ced3700fe3f4f5509dc2e480d0/src/spark/sparkwallet.cpp#L752 Future> _createSparkMintTransactions({ required List availableUtxos, diff --git a/pubspec.lock b/pubspec.lock index 9d65621e5..75e0753c0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.11.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" + url: "https://pub.dev" + source: hosted + version: "0.11.3" another_flushbar: dependency: "direct main" description: @@ -665,6 +673,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + drift: + dependency: "direct main" + description: + name: drift + sha256: c2d073d35ad441730812f4ea05b5dd031fb81c5f9786a4f5fb77ecd6307b6f74 + url: "https://pub.dev" + source: hosted + version: "2.22.1" + drift_dev: + dependency: "direct dev" + description: + name: drift_dev + sha256: f4ab5d6976b1e31551ceb82ff597a505bda7818ff4f7be08a1da9d55eb6e730c + url: "https://pub.dev" + source: hosted + version: "2.22.1" + drift_flutter: + dependency: "direct main" + description: + name: drift_flutter + sha256: "9fd9b479c6187d6b3bbdfd2703df98010470a6c65c2a8c8c5a1034c620bd0a0e" + url: "https://pub.dev" + source: hosted + version: "0.2.3" dropdown_button2: dependency: "direct main" description: @@ -1475,7 +1507,7 @@ packages: source: hosted version: "3.2.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" @@ -1706,6 +1738,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.3" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" retry: dependency: transitive description: @@ -1861,18 +1901,26 @@ packages: dependency: "direct main" description: name: sqlite3 - sha256: b384f598b813b347c5a7e5ffad82cbaff1bec3d1561af267041e66f6f0899295 + sha256: fde692580bee3379374af1f624eb3e113ab2865ecb161dbe2d8ac2de9735dbdb url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.5" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "1e62698dc1ab396152ccaf3b3990d826244e9f3c8c39b51805f209adcd6dbea3" + sha256: "62bbb4073edbcdf53f40c80775f33eea01d301b7b81417e5b3fb7395416258c1" + url: "https://pub.dev" + source: hosted + version: "0.5.24" + sqlparser: + dependency: transitive + description: + name: sqlparser + sha256: "4cad4b2c5f63dc9ea1a8dcffb58cf762322bea5dd8836870164a65e913bdae41" url: "https://pub.dev" source: hosted - version: "0.5.22" + version: "0.40.0" stack_trace: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 86b62194d..4a83df02f 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -188,8 +188,8 @@ dependencies: ref: dea799c20bc917f72b18c916ca96bc99fb1bd1c5 path: packages/solana calendar_date_picker2: ^1.0.2 - sqlite3: 2.4.3 - sqlite3_flutter_libs: 0.5.22 + sqlite3: 2.4.5 + sqlite3_flutter_libs: 0.5.24 # camera_linux: ^0.0.8 camera_linux: git: @@ -218,6 +218,9 @@ dependencies: git: url: https://github.com/Cyrix126/namecoin_dart ref: 819b21164ef93cc0889049d4a8a1be2d0cc36a1b + drift: ^2.22.1 + drift_flutter: ^0.2.3 + path: ^1.9.1 dev_dependencies: flutter_test: @@ -238,6 +241,7 @@ dev_dependencies: isar_generator: version: 3.1.8 hosted: https://pub.isar-community.dev/ + drift_dev: ^2.22.1 flutter_native_splash: image: assets/icon/splash.png diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index 4ac0b9849..11c558f20 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -531,6 +531,67 @@ class MockElectrumXClient extends _i1.Mock implements _i6.ElectrumXClient { returnValue: _i9.Future>>.value(>[]), ) as _i9.Future>>); + @override + _i9.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i9.Future>.value( + <({String address, String name})>[]), + ) as _i9.Future>); + + @override + _i9.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i9.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i8.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i8.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i9.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i9.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart index a36aefef0..c840f4b50 100644 --- a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart +++ b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart @@ -527,6 +527,67 @@ class MockElectrumXClient extends _i1.Mock implements _i5.ElectrumXClient { returnValue: _i8.Future>>.value(>[]), ) as _i8.Future>>); + @override + _i8.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i8.Future>.value( + <({String address, String name})>[]), + ) as _i8.Future>); + + @override + _i8.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i8.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i8.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i8.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart index c853a3f37..50706b9cc 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart @@ -527,6 +527,67 @@ class MockElectrumXClient extends _i1.Mock implements _i5.ElectrumXClient { returnValue: _i8.Future>>.value(>[]), ) as _i8.Future>>); + @override + _i8.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i8.Future>.value( + <({String address, String name})>[]), + ) as _i8.Future>); + + @override + _i8.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i8.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i8.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i8.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index 08f884b57..93185c901 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -527,6 +527,67 @@ class MockElectrumXClient extends _i1.Mock implements _i5.ElectrumXClient { returnValue: _i8.Future>>.value(>[]), ) as _i8.Future>>); + @override + _i8.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i8.Future>.value( + <({String address, String name})>[]), + ) as _i8.Future>); + + @override + _i8.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i8.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i8.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i8.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, diff --git a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart index cd27b6654..287146e12 100644 --- a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart +++ b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart @@ -527,6 +527,67 @@ class MockElectrumXClient extends _i1.Mock implements _i5.ElectrumXClient { returnValue: _i8.Future>>.value(>[]), ) as _i8.Future>>); + @override + _i8.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i8.Future>.value( + <({String address, String name})>[]), + ) as _i8.Future>); + + @override + _i8.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i8.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i8.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i8.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, diff --git a/test/services/coins/particl/particl_wallet_test.mocks.dart b/test/services/coins/particl/particl_wallet_test.mocks.dart index 1360bd6db..8a1cce451 100644 --- a/test/services/coins/particl/particl_wallet_test.mocks.dart +++ b/test/services/coins/particl/particl_wallet_test.mocks.dart @@ -527,6 +527,67 @@ class MockElectrumXClient extends _i1.Mock implements _i5.ElectrumXClient { returnValue: _i8.Future>>.value(>[]), ) as _i8.Future>>); + @override + _i8.Future> getSparkNames( + {String? requestID}) => + (super.noSuchMethod( + Invocation.method( + #getSparkNames, + [], + {#requestID: requestID}, + ), + returnValue: _i8.Future>.value( + <({String address, String name})>[]), + ) as _i8.Future>); + + @override + _i8.Future<({String additionalInfo, String address, int validUntil})> + getSparkNameData({ + required String? sparkName, + String? requestID, + }) => + (super.noSuchMethod( + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + returnValue: _i8.Future< + ({ + String additionalInfo, + String address, + int validUntil + })>.value(( + additionalInfo: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + address: _i7.dummyValue( + this, + Invocation.method( + #getSparkNameData, + [], + { + #sparkName: sparkName, + #requestID: requestID, + }, + ), + ), + validUntil: 0 + )), + ) as _i8.Future< + ({String additionalInfo, String address, int validUntil})>); + @override _i8.Future<_i3.SparkAnonymitySetMeta> getSparkAnonymitySetMeta({ String? requestID, From c20269d615e75b8aad08ad22a0e499020beaa9a8 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 9 May 2025 11:48:24 -0600 Subject: [PATCH 045/206] fix name tx confirm send --- .../spark_names/confirm_spark_name_transaction_view.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart index 6efd2a8fd..9afc5694f 100644 --- a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart +++ b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart @@ -20,7 +20,6 @@ import '../../models/isar/models/transaction_note.dart'; import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../themes/stack_colors.dart'; @@ -33,6 +32,7 @@ import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/models/tx_data.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -74,7 +74,7 @@ class _ConfirmSparkNameTransactionViewState late final TextEditingController noteController; Future _attemptSend() async { - final wallet = ref.read(pWallets).getWallet(walletId); + final wallet = ref.read(pWallets).getWallet(walletId) as SparkInterface; final coin = wallet.info.coin; final sendProgressController = ProgressAndSuccessController(); @@ -101,7 +101,7 @@ class _ConfirmSparkNameTransactionViewState final note = noteController.text; try { - txDataFuture = wallet.confirmSend(txData: widget.txData); + txDataFuture = wallet.confirmSendSpark(txData: widget.txData); // await futures in parallel final futureResults = await Future.wait([txDataFuture, time]); From 21b8037cc82665f43ae3d7bcb6f5d6d143e7bdc4 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 9 May 2025 17:30:45 -0600 Subject: [PATCH 046/206] spark names --- .../spark_interface.dart | 78 ++++++++++++++++--- pubspec.lock | 6 +- scripts/app_config/templates/pubspec.template | 2 +- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index b1cd31c95..d725e9628 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -313,6 +313,8 @@ mixin SparkInterface serializedCoins: serializedCoins, // privateRecipientsCount: (txData.sparkRecipients?.length ?? 0), privateRecipientsCount: 1, // ROUGHLY! + utxoNum: 0, // TODO not zero? + additionalTxSize: 0, // spark name script size ); if (estimate < 0) { @@ -495,6 +497,8 @@ mixin SparkInterface subtractFeeFromAmount: true, serializedCoins: serializedCoins, privateRecipientsCount: (txData.sparkRecipients?.length ?? 0), + utxoNum: 0, // ?? + additionalTxSize: 0, // name script size ); estimatedFee = BigInt.from(estFee); } else { @@ -599,6 +603,22 @@ mixin SparkInterface ); extractedTx.setPayload(Uint8List(0)); + ({Uint8List script, int size})? noProofNameTxData; + if (txData.sparkNameInfo != null) { + noProofNameTxData = LibSpark.createSparkNameScript( + sparkNameValidityBlocks: txData.sparkNameInfo!.validBlocks, + name: txData.sparkNameInfo!.name, + additionalInfo: txData.sparkNameInfo!.additionalInfo, + scalarHex: extractedTx.getId(), + privateKeyHex: privateKey.toHex, + spendKeyIndex: kDefaultSparkIndex, + diversifier: txData.sparkNameInfo!.sparkAddress.derivationIndex, + isTestNet: cryptoCurrency.network != CryptoCurrencyNetwork.main, + ignoreProof: true, + hashFailSafe: 0, + ); + } + final spend = await computeWithLibSparkLogging(_createSparkSend, ( privateKeyHex: privateKey.toHex, index: kDefaultSparkIndex, @@ -634,6 +654,8 @@ mixin SparkInterface ) .toList(), txHash: extractedTx.getHash(), + additionalTxSize: + txData.sparkNameInfo == null ? 0 : noProofNameTxData!.size, )); for (final outputScript in spend.outputScripts) { @@ -645,19 +667,45 @@ mixin SparkInterface if (txData.sparkNameInfo != null) { // this is name reg tx - final nameScript = LibSpark.createSparkNameScript( - sparkNameValidityBlocks: txData.sparkNameInfo!.validBlocks, - name: txData.sparkNameInfo!.name, - additionalInfo: txData.sparkNameInfo!.additionalInfo, - scalarHex: extractedTx.getHash().toHex, - privateKeyHex: privateKey.toHex, - spendKeyIndex: kDefaultSparkIndex, - diversifier: txData.sparkNameInfo!.sparkAddress.derivationIndex, - isTestNet: cryptoCurrency.network != CryptoCurrencyNetwork.main, + extractedTx.setPayload( + Uint8List.fromList([ + ...spend.serializedSpendPayload, + ...noProofNameTxData!.script, + ]), ); + final hash = extractedTx.getId(); + + ({Uint8List script, int size})? nameScriptData; + int hashFailSafe = 0; + while (nameScriptData == null) { + try { + nameScriptData = LibSpark.createSparkNameScript( + sparkNameValidityBlocks: txData.sparkNameInfo!.validBlocks, + name: txData.sparkNameInfo!.name, + additionalInfo: txData.sparkNameInfo!.additionalInfo, + scalarHex: hash, + privateKeyHex: privateKey.toHex, + spendKeyIndex: kDefaultSparkIndex, + diversifier: txData.sparkNameInfo!.sparkAddress.derivationIndex, + isTestNet: cryptoCurrency.network != CryptoCurrencyNetwork.main, + ignoreProof: false, + hashFailSafe: hashFailSafe, + ); + break; + } catch (e) { + if (e.toString() != "Exception: hash fail") { + rethrow; + } + hashFailSafe++; + } + } + extractedTx.setPayload( - Uint8List.fromList([...spend.serializedSpendPayload, ...nameScript]), + Uint8List.fromList([ + ...spend.serializedSpendPayload, + ...nameScriptData.script, + ]), ); } @@ -2213,6 +2261,7 @@ _createSparkSend( allAnonymitySets, List<({int setId, Uint8List blockHash})> idAndBlockHashes, Uint8List txHash, + int additionalTxSize, }) args, ) async { @@ -2225,6 +2274,7 @@ _createSparkSend( allAnonymitySets: args.allAnonymitySets, idAndBlockHashes: args.idAndBlockHashes, txHash: args.txHash, + additionalTxSize: args.additionalTxSize, ); return spend; @@ -2343,6 +2393,8 @@ Future _asyncSparkFeesWrapper({ required bool subtractFeeFromAmount, required List serializedCoins, required int privateRecipientsCount, + required int utxoNum, + required int additionalTxSize, }) async { return await computeWithLibSparkLogging(_estSparkFeeComputeFunc, ( privateKeyHex: privateKeyHex, @@ -2351,6 +2403,8 @@ Future _asyncSparkFeesWrapper({ subtractFeeFromAmount: subtractFeeFromAmount, serializedCoins: serializedCoins, privateRecipientsCount: privateRecipientsCount, + utxoNum: utxoNum, + additionalTxSize: additionalTxSize, )); } @@ -2362,6 +2416,8 @@ int _estSparkFeeComputeFunc( bool subtractFeeFromAmount, List serializedCoins, int privateRecipientsCount, + int utxoNum, + int additionalTxSize, }) args, ) { @@ -2372,6 +2428,8 @@ int _estSparkFeeComputeFunc( subtractFeeFromAmount: args.subtractFeeFromAmount, serializedCoins: args.serializedCoins, privateRecipientsCount: args.privateRecipientsCount, + utxoNum: args.utxoNum, + additionalTxSize: args.additionalTxSize, ); return est; diff --git a/pubspec.lock b/pubspec.lock index 75e0753c0..abb45eb85 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -864,11 +864,11 @@ packages: dependency: "direct main" description: path: "." - ref: e8c502652da7836cd1a22893339838553675b464 - resolved-ref: e8c502652da7836cd1a22893339838553675b464 + ref: "66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b" + resolved-ref: "66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b" url: "https://github.com/cypherstack/flutter_libsparkmobile.git" source: git - version: "0.0.2" + version: "0.1.0" flutter_lints: dependency: "direct dev" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 4a83df02f..3019844ad 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -38,7 +38,7 @@ dependencies: flutter_libsparkmobile: git: url: https://github.com/cypherstack/flutter_libsparkmobile.git - ref: e8c502652da7836cd1a22893339838553675b464 + ref: 66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b # cs_monero compat (unpublished) compat: From 2073ab5a9db6353f85241d8cde49d92a665fbf08 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Mon, 12 May 2025 10:33:34 -0700 Subject: [PATCH 047/206] Re-order build docs, closes #1035. --- docs/building.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/building.md b/docs/building.md index 4ba1b7150..1475a7d6d 100644 --- a/docs/building.md +++ b/docs/building.md @@ -12,20 +12,6 @@ Here you will find instructions on how to install the necessary tools for buildi The following instructions are for building and running on a Linux host. Alternatively, see the [Mac](#mac-host) and/or [Windows](#windows-host) section. This entire section (except for the Android Studio section) needs to be completed in WSL if building on a Windows host. -### Flutter -Install Flutter 3.29.2 by [following their guide](https://docs.flutter.dev/get-started/install/linux/desktop?tab=download#install-the-flutter-sdk). You can also clone https://github.com/flutter/flutter, check out the `3.29.2` tag, and add its `flutter/bin` folder to your PATH as in -```sh -FLUTTER_DIR="$HOME/development/flutter" -git clone https://github.com/flutter/flutter.git "$FLUTTER_DIR" -cd "$FLUTTER_DIR" -git checkout 3.29.2 -echo 'export PATH="$PATH:'"$FLUTTER_DIR"'/bin"' >> "$HOME/.profile" -source "$HOME/.profile" -flutter precache -``` - -Run `flutter doctor` in a terminal to confirm its installation. - ### Android Studio Install Android Studio. Follow instructions here [https://developer.android.com/studio/install#linux](https://developer.android.com/studio/install#linux) or install via snap: ``` @@ -58,7 +44,7 @@ sudo apt-get install libssl-dev curl unzip automake build-essential file pkg-con For Ubuntu 20.04, ``` -sudo apt-get install valac +sudo apt-get install valac python3-pip pip3 install --upgrade meson==0.64.1 markdown==3.4.1 markupsafe==2.1.1 jinja2==3.1.2 pygments==2.13.0 toml==0.10.2 typogrify==2.0.7 tomli==2.0.1 ``` @@ -89,6 +75,20 @@ sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev pip3 install --upgrade meson==0.64.1 markdown==3.4.1 markupsafe==2.1.1 jinja2==3.1.2 pygments==2.13.0 toml==0.10.2 typogrify==2.0.7 tomli==2.0.1 ``` +### Flutter +Install Flutter 3.29.2 by [following their guide](https://docs.flutter.dev/get-started/install/linux/desktop?tab=download#install-the-flutter-sdk). You can also clone https://github.com/flutter/flutter, check out the `3.29.2` tag, and add its `flutter/bin` folder to your PATH as in +```sh +FLUTTER_DIR="$HOME/development/flutter" +git clone https://github.com/flutter/flutter.git "$FLUTTER_DIR" +cd "$FLUTTER_DIR" +git checkout 3.29.2 +echo 'export PATH="$PATH:'"$FLUTTER_DIR"'/bin"' >> "$HOME/.profile" +source "$HOME/.profile" +flutter precache +``` + +Run `flutter doctor` in a terminal to confirm its installation. + ### Clone the repository and initialize submodules After installing the prerequisites listed above, download the code and init the submodules ``` From fa538b64ccda384aa1d8c81021093c18f4d836f5 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 5 May 2025 14:53:19 -0600 Subject: [PATCH 048/206] adaptive desktop wallet features --- .../wallet_view/desktop_wallet_view.dart | 100 ++--- .../sub_widgets/desktop_wallet_features.dart | 303 +++++++++----- .../more_features/more_features_dialog.dart | 384 ++++++------------ .../static_overflow_row.dart | 84 ++-- 4 files changed, 419 insertions(+), 452 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index 2cf41f06a..e35e6ed34 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -423,73 +423,41 @@ class DesktopWalletHeaderRow extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return RoundedWhiteContainer( padding: const EdgeInsets.all(20), - child: - wallet is FiroWallet && MediaQuery.of(context).size.width < 1600 - ? Column( - children: [ - Row( - children: [ - SvgPicture.file( - File(ref.watch(coinIconProvider(wallet.info.coin))), - width: 40, - height: 40, - ), - const SizedBox(width: 10), - FiroDesktopWalletSummary( - walletId: wallet.walletId, - initialSyncStatus: - wallet.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, - ), - - const Spacer(), - ], - ), - const SizedBox(height: 10), - Row( - children: [ - DesktopWalletFeatures(walletId: wallet.walletId), - ], - ), - ], - ) - : Row( - children: [ - if (monke != null) - SvgPicture.memory( - Uint8List.fromList(monke!), - width: 60, - height: 60, - ), - if (monke == null) - SvgPicture.file( - File(ref.watch(coinIconProvider(wallet.info.coin))), - width: 40, - height: 40, - ), - const SizedBox(width: 10), - if (wallet is FiroWallet) - FiroDesktopWalletSummary( - walletId: wallet.walletId, - initialSyncStatus: - wallet.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, - ), + child: Row( + children: [ + if (monke != null) + SvgPicture.memory( + Uint8List.fromList(monke!), + width: 60, + height: 60, + ), + if (monke == null) + SvgPicture.file( + File(ref.watch(coinIconProvider(wallet.info.coin))), + width: 40, + height: 40, + ), + const SizedBox(width: 10), + if (wallet is FiroWallet) + FiroDesktopWalletSummary( + walletId: wallet.walletId, + initialSyncStatus: + wallet.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, + ), - if (wallet is! FiroWallet) - DesktopWalletSummary( - walletId: wallet.walletId, - initialSyncStatus: - wallet.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, - ), - const Spacer(), - DesktopWalletFeatures(walletId: wallet.walletId), - ], - ), + if (wallet is! FiroWallet) + DesktopWalletSummary( + walletId: wallet.walletId, + initialSyncStatus: + wallet.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, + ), + Expanded(child: DesktopWalletFeatures(walletId: wallet.walletId)), + ], + ), ); } } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 0cfab7c16..bd91540f8 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -9,6 +9,7 @@ */ import 'dart:async'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -16,6 +17,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/svg.dart'; import '../../../../app_config.dart'; +import '../../../../models/keys/view_only_wallet_data.dart'; import '../../../../notifications/show_flush_bar.dart'; import '../../../../pages/monkey/monkey_view.dart'; import '../../../../pages/namecoin_names/namecoin_names_home_view.dart'; @@ -27,6 +29,7 @@ import '../../../../providers/global/paynym_api_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../providers/wallet/my_paynym_account_state_provider.dart'; import '../../../../themes/stack_colors.dart'; +import '../../../../themes/theme_providers.dart'; import '../../../../utilities/amount/amount.dart'; import '../../../../utilities/assets.dart'; import '../../../../utilities/constants.dart'; @@ -35,16 +38,23 @@ import '../../../../utilities/text_styles.dart'; import '../../../../wallets/crypto_currency/coins/banano.dart'; import '../../../../wallets/crypto_currency/coins/firo.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; +import '../../../../wallets/wallet/impl/namecoin_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/wallet.dart' show Wallet; import '../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../../widgets/custom_loading_overlay.dart'; import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/loading_indicator.dart'; +import '../../../../widgets/static_overflow_row/static_overflow_row.dart'; import '../../../cashfusion/desktop_cashfusion_view.dart'; import '../../../churning/desktop_churning_view.dart'; import '../../../coin_control/desktop_coin_control_view.dart'; @@ -55,6 +65,35 @@ import '../../../spark_coins/spark_coins_view.dart'; import '../desktop_wallet_view.dart'; import 'more_features/more_features_dialog.dart'; +enum WalletFeature { + anonymizeFunds("Anonymize funds", "Anonymize funds"), + swap("Swap", ""), + buy("Buy", "Buy cryptocurrency"), + paynym("PayNym", "Increased address privacy using BIP47"), + coinControl( + "Coin control", + "Control, freeze, and utilize outputs at your discretion", + ), + lelantusCoins("Lelantus coins", "View wallet lelantus coins"), + sparkCoins("Spark coins", "View wallet spark coins"), + ordinals("Ordinals", "View and control your ordinals in ${AppConfig.prefix}"), + monkey("MonKey", "Generate Banano MonKey"), + fusion("Fusion", "Decentralized mixing protocol"), + churn("Churn", "Churning"), + namecoinName("Domains", "Namecoin DNS"), + sparkNames("Names", "Spark names"), + + // special cases + clearSparkCache("", ""), + lelantusScanOption("", ""), + rbf("", ""), + reuseAddress("", ""); + + final String label; + final String description; + const WalletFeature(this.label, this.description); +} + class DesktopWalletFeatures extends ConsumerStatefulWidget { const DesktopWalletFeatures({super.key, required this.walletId}); @@ -66,8 +105,6 @@ class DesktopWalletFeatures extends ConsumerStatefulWidget { } class _DesktopWalletFeaturesState extends ConsumerState { - static const double buttonWidth = 120; - Future _onSwapPressed() async { ref.read(currentDesktopMenuItemProvider.state).state = DesktopMenuItemId.exchange; @@ -76,58 +113,35 @@ class _DesktopWalletFeaturesState extends ConsumerState { } Future _onBuyPressed() async { - Navigator.of(context, rootNavigator: true).pop(); ref.read(currentDesktopMenuItemProvider.state).state = DesktopMenuItemId.buy; ref.read(prevDesktopMenuItemProvider.state).state = DesktopMenuItemId.buy; } - Future _onMorePressed() async { + Future _onMorePressed( + List<(WalletFeature, String, FutureOr Function())> options, + ) async { await showDialog( context: context, builder: - (_) => MoreFeaturesDialog( - walletId: widget.walletId, - onPaynymPressed: _onPaynymPressed, - onBuyPressed: _onBuyPressed, - onCoinControlPressed: _onCoinControlPressed, - onLelantusCoinsPressed: _onLelantusCoinsPressed, - onSparkCoinsPressedPressed: _onSparkCoinsPressed, - // onAnonymizeAllPressed: _onAnonymizeAllPressed, - onWhirlpoolPressed: _onWhirlpoolPressed, - onOrdinalsPressed: _onOrdinalsPressed, - onMonkeyPressed: _onMonkeyPressed, - onFusionPressed: _onFusionPressed, - onChurnPressed: _onChurnPressed, - onNamesPressed: _onNamesPressed, - onSparkNamesPressed: _onSparkNamesPressed, - ), + (_) => + MoreFeaturesDialog(walletId: widget.walletId, options: options), ); } - void _onWhirlpoolPressed() { - Navigator.of(context, rootNavigator: true).pop(); - } - void _onCoinControlPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(DesktopCoinControlView.routeName, arguments: widget.walletId); } void _onLelantusCoinsPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(LelantusCoinsView.routeName, arguments: widget.walletId); } void _onSparkCoinsPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(SparkCoinsView.routeName, arguments: widget.walletId); @@ -292,8 +306,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { } Future _onPaynymPressed() async { - Navigator.of(context, rootNavigator: true).pop(); - unawaited( showDialog( context: context, @@ -334,122 +346,158 @@ class _DesktopWalletFeaturesState extends ConsumerState { } Future _onMonkeyPressed() async { - Navigator.of(context, rootNavigator: true).pop(); - await (Navigator.of( context, ).pushNamed(MonkeyView.routeName, arguments: widget.walletId)); } void _onOrdinalsPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(DesktopOrdinalsView.routeName, arguments: widget.walletId); } void _onFusionPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(DesktopCashFusionView.routeName, arguments: widget.walletId); } void _onChurnPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(DesktopChurningView.routeName, arguments: widget.walletId); } void _onNamesPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(NamecoinNamesHomeView.routeName, arguments: widget.walletId); } void _onSparkNamesPressed() { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of( context, ).pushNamed(SparkNamesHomeView.routeName, arguments: widget.walletId); } + List<(WalletFeature, String, FutureOr Function())> _getOptions( + Wallet wallet, + bool showExchange, + bool showCoinControl, + bool firoAdvanced, + ) { + final coin = wallet.info.coin; + final isViewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly; + + return [ + if (!isViewOnly && coin is Firo) + ( + WalletFeature.anonymizeFunds, + Assets.svg.recycle, + _onAnonymizeAllPressed, + ), + if (!isViewOnly && + Constants.enableExchange && + AppConfig.hasFeature(AppFeature.swap) && + showExchange) + (WalletFeature.swap, Assets.svg.swap, _onSwapPressed), + + if (showExchange && AppConfig.hasFeature(AppFeature.buy)) + (WalletFeature.buy, Assets.svg.swap, _onBuyPressed), + + if (showCoinControl) + ( + WalletFeature.coinControl, + Assets.svg.coinControl.gamePad, + _onCoinControlPressed, + ), + + if (firoAdvanced && wallet is FiroWallet) + ( + WalletFeature.lelantusCoins, + Assets.svg.coinControl.gamePad, + _onLelantusCoinsPressed, + ), + + if (firoAdvanced && wallet is FiroWallet) + ( + WalletFeature.sparkCoins, + Assets.svg.coinControl.gamePad, + _onSparkCoinsPressed, + ), + + if (!isViewOnly && wallet is PaynymInterface) + (WalletFeature.paynym, Assets.svg.robotHead, _onPaynymPressed), + + if (wallet is OrdinalsInterface) + (WalletFeature.ordinals, Assets.svg.ordinal, _onOrdinalsPressed), + + if (wallet.info.coin is Banano) + (WalletFeature.monkey, Assets.svg.monkey, _onMonkeyPressed), + + if (!isViewOnly && wallet is CashFusionInterface) + (WalletFeature.fusion, Assets.svg.cashFusion, _onFusionPressed), + + if (!isViewOnly && wallet is LibMoneroWallet) + (WalletFeature.churn, Assets.svg.churn, _onChurnPressed), + + if (wallet is NamecoinWallet) + (WalletFeature.namecoinName, Assets.svg.robotHead, _onNamesPressed), + + if (wallet is SparkInterface) + (WalletFeature.sparkNames, Assets.svg.robotHead, _onSparkNamesPressed), + ]; + } + @override Widget build(BuildContext context) { final wallet = ref.watch(pWallets).getWallet(widget.walletId); - final coin = wallet.info.coin; - final prefs = ref.watch(prefsChangeNotifierProvider); - final showExchange = prefs.enableExchange; - - final showMore = - wallet is PaynymInterface || - (wallet is CoinControlInterface && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.enableCoinControl, - ), - )) || - coin is Firo || - // manager.hasWhirlpoolSupport || - coin is Banano || - wallet is OrdinalsInterface || - wallet is CashFusionInterface; + final options = _getOptions( + wallet, + ref.watch( + prefsChangeNotifierProvider.select((value) => value.enableExchange), + ), + (wallet is CoinControlInterface && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableCoinControl, + ), + )), + ref.watch( + prefsChangeNotifierProvider.select((s) => s.advancedFiroFeatures), + ), + ); final isViewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly; - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (!isViewOnly && wallet.info.coin is Firo) - SecondaryButton( - label: "Anonymize funds", - width: buttonWidth * 2, - buttonHeight: ButtonHeight.l, - icon: SvgPicture.asset( - Assets.svg.recycle, - height: 20, - width: 20, - color: - Theme.of( - context, - ).extension()!.buttonTextSecondary, - ), - onPressed: () => _onAnonymizeAllPressed(), - ), - if (!isViewOnly && wallet.info.coin is Firo) const SizedBox(width: 16), - if (!isViewOnly && - Constants.enableExchange && - AppConfig.hasFeature(AppFeature.swap) && - showExchange) - SecondaryButton( - label: "Swap", - width: buttonWidth, - buttonHeight: ButtonHeight.l, - icon: SvgPicture.asset( - Assets.svg.arrowRotate, - height: 20, - width: 20, - color: - Theme.of( - context, - ).extension()!.buttonTextSecondary, - ), - onPressed: () => _onSwapPressed(), - ), + final isViewOnlyNoAddressGen = + wallet is ViewOnlyOptionInterface && + wallet.isViewOnly && + wallet.viewOnlyType == ViewOnlyWalletType.addressOnly; + + final extraOptions = [ + if (wallet is SparkInterface && !isViewOnly) + (WalletFeature.clearSparkCache, Assets.svg.key, () => ()), + + if (wallet is LelantusInterface && !isViewOnly) + (WalletFeature.lelantusScanOption, Assets.svg.key, () => ()), - if (showMore) const SizedBox(width: 16), - if (showMore) - SecondaryButton( + if (wallet is RbfInterface) (WalletFeature.rbf, Assets.svg.key, () => ()), + + if (!isViewOnlyNoAddressGen) + (WalletFeature.reuseAddress, Assets.svg.key, () => ()), + ]; + + return StaticOverflowRow( + forcedOverflow: extraOptions.isNotEmpty, + overflowBuilder: (count) { + return Padding( + padding: const EdgeInsets.only(left: 16), + child: SecondaryButton( label: "More", - width: buttonWidth, + padding: const EdgeInsets.symmetric(horizontal: 16), buttonHeight: ButtonHeight.l, icon: SvgPicture.asset( Assets.svg.bars, @@ -460,9 +508,52 @@ class _DesktopWalletFeaturesState extends ConsumerState { context, ).extension()!.buttonTextSecondary, ), - onPressed: () => _onMorePressed(), + onPressed: + () => _onMorePressed([ + ...options.sublist(options.length - count), + ...extraOptions, + ]), ), - ], + ); + }, + + children: options + .map( + (option) => Padding( + padding: const EdgeInsets.only(left: 16), + child: SecondaryButton( + label: option.$1.label, + padding: const EdgeInsets.symmetric(horizontal: 16), + buttonHeight: ButtonHeight.l, + icon: + option.$1 == WalletFeature.buy + ? SvgPicture.file( + File( + ref.watch( + themeProvider.select((value) => value.assets.buy), + ), + ), + height: 20, + width: 20, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, + ) + : SvgPicture.asset( + option.$2, + height: 20, + width: 20, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, + ), + onPressed: () => option.$3(), + ), + ), + ) + .toList(growable: false), ); } } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index e16766deb..5a013787a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -8,6 +8,7 @@ * */ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -15,16 +16,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; -import '../../../../../app_config.dart'; import '../../../../../db/sqlite/firo_cache.dart'; -import '../../../../../models/keys/view_only_wallet_data.dart'; import '../../../../../providers/db/main_db_provider.dart'; -import '../../../../../providers/global/prefs_provider.dart'; import '../../../../../providers/global/wallets_provider.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../themes/theme_providers.dart'; import '../../../../../utilities/assets.dart'; -import '../../../../../utilities/constants.dart'; import '../../../../../utilities/logger.dart'; import '../../../../../utilities/show_loading.dart'; import '../../../../../utilities/text_styles.dart'; @@ -32,17 +29,6 @@ import '../../../../../utilities/util.dart'; import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../../../wallets/wallet/impl/firo_wallet.dart'; -import '../../../../../wallets/wallet/impl/namecoin_wallet.dart'; -import '../../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; -import '../../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../../../widgets/custom_buttons/draggable_switch_button.dart'; import '../../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../../widgets/desktop/desktop_dialog_close_button.dart'; @@ -50,40 +36,17 @@ import '../../../../../widgets/desktop/primary_button.dart'; import '../../../../../widgets/desktop/secondary_button.dart'; import '../../../../../widgets/rounded_container.dart'; import '../../../../../widgets/stack_dialog.dart'; +import '../desktop_wallet_features.dart'; class MoreFeaturesDialog extends ConsumerStatefulWidget { const MoreFeaturesDialog({ super.key, required this.walletId, - required this.onPaynymPressed, - required this.onBuyPressed, - required this.onCoinControlPressed, - required this.onLelantusCoinsPressed, - required this.onSparkCoinsPressedPressed, - // required this.onAnonymizeAllPressed, - required this.onWhirlpoolPressed, - required this.onOrdinalsPressed, - required this.onMonkeyPressed, - required this.onFusionPressed, - required this.onChurnPressed, - required this.onNamesPressed, - required this.onSparkNamesPressed, + required this.options, }); final String walletId; - final VoidCallback? onPaynymPressed; - final VoidCallback? onBuyPressed; - final VoidCallback? onCoinControlPressed; - final VoidCallback? onLelantusCoinsPressed; - final VoidCallback? onSparkCoinsPressedPressed; - // final VoidCallback? onAnonymizeAllPressed; - final VoidCallback? onWhirlpoolPressed; - final VoidCallback? onOrdinalsPressed; - final VoidCallback? onMonkeyPressed; - final VoidCallback? onFusionPressed; - final VoidCallback? onChurnPressed; - final VoidCallback? onNamesPressed; - final VoidCallback? onSparkNamesPressed; + final List<(WalletFeature, String, FutureOr Function())> options; @override ConsumerState createState() => _MoreFeaturesDialogState(); @@ -366,16 +329,6 @@ class _MoreFeaturesDialogState extends ConsumerState { pWallets.select((value) => value.getWallet(widget.walletId)), ); - final coinControlPrefEnabled = ref.watch( - prefsChangeNotifierProvider.select((value) => value.enableCoinControl), - ); - - final isViewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly; - final isViewOnlyNoAddressGen = - wallet is ViewOnlyOptionInterface && - wallet.isViewOnly && - wallet.viewOnlyType == ViewOnlyWalletType.addressOnly; - return DesktopDialog( maxHeight: double.infinity, child: Column( @@ -394,220 +347,147 @@ class _MoreFeaturesDialogState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - if (Constants.enableExchange && - AppConfig.hasFeature(AppFeature.buy) && - ref.watch(prefsChangeNotifierProvider).enableExchange) - _MoreFeaturesItem( - label: "Buy", - detail: "Buy cryptocurrency", - isSvgFile: true, - iconAsset: ref.watch( - themeProvider.select((value) => value.assets.buy), - ), - onPressed: () async => widget.onBuyPressed?.call(), - ), - // if (!isViewOnly && wallet.info.coin is Firo) - // _MoreFeaturesItem( - // label: "Anonymize funds", - // detail: "Anonymize funds", - // iconAsset: Assets.svg.recycle, - // onPressed: () async => widget.onAnonymizeAllPressed?.call(), - // ), - // TODO: [prio=med] - // if (manager.hasWhirlpoolSupport) - // _MoreFeaturesItem( - // label: "Whirlpool", - // detail: "Powerful Bitcoin privacy enhancer", - // iconAsset: Assets.svg.whirlPool, - // onPressed: () => widget.onWhirlpoolPressed?.call(), - // ), - if (wallet is CoinControlInterface && coinControlPrefEnabled) - _MoreFeaturesItem( - label: "Coin control", - detail: "Control, freeze, and utilize outputs at your discretion", - iconAsset: Assets.svg.coinControl.gamePad, - onPressed: () async => widget.onCoinControlPressed?.call(), - ), - if (wallet is FiroWallet && - ref.watch( - prefsChangeNotifierProvider.select( - (s) => s.advancedFiroFeatures, - ), - )) - _MoreFeaturesItem( - label: "Lelantus Coins", - detail: "View wallet lelantus coins", - iconAsset: Assets.svg.coinControl.gamePad, - onPressed: () async => widget.onLelantusCoinsPressed?.call(), - ), - if (wallet is FiroWallet && - ref.watch( - prefsChangeNotifierProvider.select( - (s) => s.advancedFiroFeatures, - ), - )) - _MoreFeaturesItem( - label: "Spark Coins", - detail: "View wallet spark coins", - iconAsset: Assets.svg.coinControl.gamePad, - onPressed: () async => widget.onSparkCoinsPressedPressed?.call(), - ), - if (!isViewOnly && wallet is PaynymInterface) - _MoreFeaturesItem( - label: "PayNym", - detail: "Increased address privacy using BIP47", - iconAsset: Assets.svg.robotHead, - onPressed: () async => widget.onPaynymPressed?.call(), - ), - if (wallet is OrdinalsInterface) - _MoreFeaturesItem( - label: "Ordinals", - detail: "View and control your ordinals in ${AppConfig.prefix}", - iconAsset: Assets.svg.ordinal, - onPressed: () async => widget.onOrdinalsPressed?.call(), - ), - if (wallet.info.coin is Banano) - _MoreFeaturesItem( - label: "MonKey", - detail: "Generate Banano MonKey", - iconAsset: Assets.svg.monkey, - onPressed: () async => widget.onMonkeyPressed?.call(), - ), - if (!isViewOnly && wallet is CashFusionInterface) - _MoreFeaturesItem( - label: "Fusion", - detail: "Decentralized mixing protocol", - iconAsset: Assets.svg.cashFusion, - onPressed: () async => widget.onFusionPressed?.call(), - ), - if (!isViewOnly && wallet is LibMoneroWallet) - _MoreFeaturesItem( - label: "Churn", - detail: "Churning", - iconAsset: Assets.svg.churn, - onPressed: () async => widget.onChurnPressed?.call(), - ), - if (wallet is NamecoinWallet) - _MoreFeaturesItem( - label: "Domains", - detail: "Namecoin DNS", - iconAsset: Assets.svg.robotHead, - onPressed: () async => widget.onNamesPressed?.call(), - ), - if (wallet is SparkInterface) - _MoreFeaturesItem( - label: "Names", - detail: "Spark names", - iconAsset: Assets.svg.robotHead, - onPressed: () async => widget.onSparkNamesPressed?.call(), - ), - if (wallet is SparkInterface && !isViewOnly) - _MoreFeaturesClearSparkCacheItem( - cryptoCurrency: wallet.cryptoCurrency, - ), - if (wallet is LelantusInterface && !isViewOnly) - _MoreFeaturesItemBase( - child: Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo( - widget.walletId, - ).select((value) => value.otherData), - )[WalletInfoKeys.enableLelantusScanning] - as bool? ?? - false, - onValueChanged: _switchToggled, - ), + + ...widget.options.map((option) { + switch (option.$1) { + case WalletFeature.buy: + // Buy has a special icon + return _MoreFeaturesItem( + label: option.$1.label, + detail: option.$1.description, + isSvgFile: true, + iconAsset: ref.watch( + themeProvider.select((value) => value.assets.buy), ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + onPressed: () async { + Navigator.of(context, rootNavigator: true).pop(); + option.$3(); + }, + ); + + case WalletFeature.clearSparkCache: + return _MoreFeaturesClearSparkCacheItem( + cryptoCurrency: wallet.cryptoCurrency, + ); + + case WalletFeature.lelantusScanOption: + return _MoreFeaturesItemBase( + child: Row( children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.w600_20(context), + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableLelantusScanning] + as bool? ?? + false, + onValueChanged: _switchToggled, + ), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Lelantus transactions", + style: STextStyles.w600_20(context), + ), + ], ), ], ), - ], - ), - ), - if (wallet is RbfInterface) - _MoreFeaturesItemBase( - child: Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo( - widget.walletId, - ).select((value) => value.otherData), - )[WalletInfoKeys.enableOptInRbf] - as bool? ?? - false, - onValueChanged: _switchRbfToggled, - ), - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + ); + + case WalletFeature.rbf: + return _MoreFeaturesItemBase( + child: Row( children: [ - Text( - "Flag outgoing transactions with opt-in RBF", - style: STextStyles.w600_20(context), + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableOptInRbf] + as bool? ?? + false, + onValueChanged: _switchRbfToggled, + ), ), - ], - ), - ], - ), - ), - // reuseAddress preference. - if (!isViewOnlyNoAddressGen) - _MoreFeaturesItemBase( - onPressed: _switchReuseAddressToggled, - child: Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: IgnorePointer( - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo( - widget.walletId, - ).select((value) => value.otherData), - )[WalletInfoKeys.reuseAddress] - as bool? ?? - false, - controller: _switchController, + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Flag outgoing transactions with opt-in RBF", + style: STextStyles.w600_20(context), + ), + ], ), - ), + ], ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + ); + + case WalletFeature.reuseAddress: + return _MoreFeaturesItemBase( + onPressed: _switchReuseAddressToggled, + child: Row( children: [ - Text( - "Reuse receiving address", - style: STextStyles.w600_20(context), + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.reuseAddress] + as bool? ?? + false, + controller: _switchController, + ), + ), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Reuse receiving address", + style: STextStyles.w600_20(context), + ), + ], ), ], ), - ], - ), - ), + ); + + default: + return _MoreFeaturesItem( + label: option.$1.label, + detail: option.$1.description, + iconAsset: option.$2, + onPressed: () async { + Navigator.of(context, rootNavigator: true).pop(); + option.$3(); + }, + ); + } + }), + const SizedBox(height: 28), ], ), diff --git a/lib/widgets/static_overflow_row/static_overflow_row.dart b/lib/widgets/static_overflow_row/static_overflow_row.dart index 3b3189343..77cad9ada 100644 --- a/lib/widgets/static_overflow_row/static_overflow_row.dart +++ b/lib/widgets/static_overflow_row/static_overflow_row.dart @@ -3,13 +3,17 @@ import 'package:flutter/material.dart'; import 'measure_size.dart'; class StaticOverflowRow extends StatefulWidget { - final List children; final Widget Function(int hiddenCount) overflowBuilder; + final MainAxisAlignment mainAxisAlignment; + final List children; + final bool forcedOverflow; const StaticOverflowRow({ super.key, - required this.children, required this.overflowBuilder, + this.mainAxisAlignment = MainAxisAlignment.end, + this.forcedOverflow = false, + required this.children, }); @override @@ -29,10 +33,17 @@ class _StaticOverflowRowState extends State { // Still measuring if (_itemSizes.length < childCount || _overflowSize == null) { return Row( + mainAxisAlignment: widget.mainAxisAlignment, children: [ ...List.generate(childCount, (i) { return MeasureSize( - onChange: (size) => _itemSizes[i] = size, + onChange: (size) { + if (_itemSizes[i] != size) { + setState(() { + _itemSizes[i] = size; + }); + } + }, child: KeyedSubtree( key: ValueKey("item-$i"), child: widget.children[i], @@ -40,7 +51,13 @@ class _StaticOverflowRowState extends State { ); }), MeasureSize( - onChange: (size) => _overflowSize = size, + onChange: (size) { + if (_overflowSize != size) { + setState(() { + _overflowSize = size; + }); + } + }, child: KeyedSubtree( key: const ValueKey("overflow"), child: widget.overflowBuilder(0), @@ -51,8 +68,9 @@ class _StaticOverflowRowState extends State { } final List visible = []; - double usedWidth = 0; + double usedWidth = (widget.forcedOverflow ? _overflowSize!.width : 0); + bool firstPassFailed = false; // Try first pass without overflow for (int i = 0; i < childCount; i++) { final itemSize = _itemSizes[i]!; @@ -61,36 +79,46 @@ class _StaticOverflowRowState extends State { usedWidth += itemSize.width; } else { // Not all children fit. Overflow required - visible.clear(); - usedWidth = 0; - int overflowCount = 0; - - for (int j = 0; j < childCount; j++) { - final size = _itemSizes[j]!; - final needsOverflow = j < childCount - 1; - final canFit = - usedWidth + - size.width + - (needsOverflow ? _overflowSize!.width : 0) <= - constraints.maxWidth; + firstPassFailed = true; + break; + } + } - if (canFit) { - visible.add(widget.children[j]); + if (firstPassFailed) { + visible.clear(); + usedWidth = 0; + int overflowCount = 0; + for (int i = 0; i < childCount; i++) { + final size = _itemSizes[i]!; + final needsOverflow = i < childCount - 1 || widget.forcedOverflow; + final canFit = + usedWidth + + size.width + + (needsOverflow ? _overflowSize!.width : 0) <= + constraints.maxWidth; - usedWidth += size.width; - } else { - overflowCount = childCount - j; - break; - } + if (canFit) { + visible.add(widget.children[i]); + usedWidth += size.width; + } else { + overflowCount = childCount - i; + break; } + } - // Add overflow - visible.add(widget.overflowBuilder(overflowCount)); - break; + // Add overflow + visible.add(widget.overflowBuilder(overflowCount)); + } else { + if (widget.forcedOverflow) { + // Add forced overflow + visible.add(widget.overflowBuilder(0)); } } - return Row(children: visible); + return Row( + mainAxisAlignment: widget.mainAxisAlignment, + children: visible, + ); }, ); } From 70346086640aa108b2a5add484024f1eb6d20782 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 12 May 2025 13:35:34 -0600 Subject: [PATCH 049/206] global spark name cache service --- lib/services/spark_names_service.dart | 126 ++++++++++++++++++ .../spark_interface.dart | 11 ++ 2 files changed, 137 insertions(+) create mode 100644 lib/services/spark_names_service.dart diff --git a/lib/services/spark_names_service.dart b/lib/services/spark_names_service.dart new file mode 100644 index 000000000..9a9a4aa96 --- /dev/null +++ b/lib/services/spark_names_service.dart @@ -0,0 +1,126 @@ +import 'package:mutex/mutex.dart'; + +import '../utilities/logger.dart'; +import '../wallets/crypto_currency/crypto_currency.dart'; + +class _BiMap { + final Map _byKey = {}; + final Map _byValue = {}; + + _BiMap(); + + void addAll(Map other) { + for (final e in other.entries) { + add(e.key, e.value); + } + } + + void add(K key, V value) { + _byKey[key] = value; + _byValue[value] = key; + } + + void clear() { + _byValue.clear(); + _byKey.clear(); + } + + K? getByValue(V value) => _byValue[value]; + V? getByKey(K key) => _byKey[key]; +} + +/// Basic service to track all spark names on test net and main net. +/// Data is currently stored in memory only. +abstract final class SparkNamesService { + static final _lock = { + CryptoCurrencyNetwork.main: Mutex(), + CryptoCurrencyNetwork.test: Mutex(), + }; + + static const _minUpdateInterval = Duration(seconds: 10); + static DateTime _lastUpdated = DateTime(2000); // some default + + static final _cache = { + // key is address, uppercase name is value + CryptoCurrencyNetwork.main: _BiMap(), + CryptoCurrencyNetwork.test: _BiMap(), + }; + + static final _nameMap = { + // key is uppercase, value is as entered + CryptoCurrencyNetwork.main: {}, + CryptoCurrencyNetwork.test: {}, + }; + + /// Get the address for the given spark name. + static Future getAddressFor( + String name, { + CryptoCurrencyNetwork network = CryptoCurrencyNetwork.main, + }) async { + if (_cache[network] == null) { + throw UnsupportedError( + "CryptoCurrencyNetwork \"${network.name}\" is not currently allowed.", + ); + } + + return await _lock[network]!.protect( + () async => _cache[network]?.getByValue(name.toUpperCase()), + ); + } + + /// Get the name for the given spark address. + static Future getNameFor( + String address, { + CryptoCurrencyNetwork network = CryptoCurrencyNetwork.main, + }) async { + if (_cache[network] == null) { + throw UnsupportedError( + "CryptoCurrencyNetwork \"${network.name}\" is not currently allowed.", + ); + } + + return await _lock[network]!.protect( + () async => _nameMap[network]![_cache[network]?.getByKey(address)], + ); + } + + static Future update( + List<({String name, String address})> names, { + CryptoCurrencyNetwork network = CryptoCurrencyNetwork.main, + }) async { + Logging.instance.t("SparkNamesService.update called"); + if (_cache[network] == null) { + throw UnsupportedError( + "CryptoCurrencyNetwork \"${network.name}\" is not currently allowed.", + ); + } + + final now = DateTime.now(); + if (now.difference(_lastUpdated) > _minUpdateInterval) { + _lastUpdated = now; + } else { + Logging.instance.t( + "SparkNamesService.update called too soon. Returning early.", + ); + // too soon, return; + return; + } + + await _lock[network]!.protect(() async { + Logging.instance.t( + "SparkNamesService.update lock acquired and updating cache", + ); + _cache[network]!.clear(); + _nameMap[network]!.clear(); + + for (final pair in names) { + final upperName = pair.name.toUpperCase(); + _nameMap[network]![upperName] = pair.name; + + _cache[network]!.add(pair.address, upperName); + } + + Logging.instance.t("SparkNamesService.update updating cache complete"); + }); + } +} diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index d725e9628..8ca665487 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -22,6 +22,7 @@ import '../../../models/isar/models/isar_models.dart'; import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/global_event_bus.dart'; +import '../../../services/spark_names_service.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/extensions/extensions.dart'; @@ -1255,6 +1256,13 @@ mixin SparkInterface final myNameStrings = await db.managers.sparkNames.map((e) => e.name).get(); final names = await electrumXClient.getSparkNames(); + + // start update shared cache of all names + final nameUpdateFuture = SparkNamesService.update( + names, + network: cryptoCurrency.network, + ); + final myAddresses = await mainDB.isar.addresses .where() @@ -1298,6 +1306,9 @@ mixin SparkInterface await db.upsertSparkNames(data); } + + // finally ensure shared cache update has completed + await nameUpdateFuture; } catch (e, s) { Logging.instance.e( "refreshing spark names for $walletId \"${info.name}\" failed", From 7c1e94f970265aa88676dc33849854546d5e29a5 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 12 May 2025 13:50:11 -0600 Subject: [PATCH 050/206] autoformat again --- .../exchange_step_views/step_4_view.dart | 442 +++-- lib/pages/exchange_view/send_from_view.dart | 489 +++--- lib/pages/send_view/send_view.dart | 1434 ++++++++--------- .../wallet_view/sub_widgets/desktop_send.dart | 1018 ++++++------ 4 files changed, 1594 insertions(+), 1789 deletions(-) diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index 7b867aab3..be9c3ac37 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -86,8 +86,9 @@ class _Step4ViewState extends ConsumerState { } Future _updateStatus() async { - final statusResponse = - await ref.read(efExchangeProvider).updateTrade(model.trade!); + final statusResponse = await ref + .read(efExchangeProvider) + .updateTrade(model.trade!); String status = "Waiting"; if (statusResponse.value != null) { status = statusResponse.value!.status; @@ -149,46 +150,34 @@ class _Step4ViewState extends ConsumerState { Theme.of(context).extension()!.backgroundAppBar, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius * 3, - ), + top: Radius.circular(Constants.size.circularBorderRadius * 3), ), ), builder: (context) { return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), Text( "Select Firo balance", style: STextStyles.pageTitleH2(context), ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), SecondaryButton( label: "${ref.watch(pAmountFormatter(coin)).format(balancePrivate.spendable)} (private)", onPressed: () => Navigator.of(context).pop(false), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), SecondaryButton( label: "${ref.watch(pAmountFormatter(coin)).format(balancePublic.spendable)} (public)", onPressed: () => Navigator.of(context).pop(true), ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ); @@ -237,55 +226,39 @@ class _Step4ViewState extends ConsumerState { ), ); - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); Future txDataFuture; if (wallet is FiroWallet && !firoPublicSend) { txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: [ - ( - address: address, - amount: amount, - isChange: false, - ), - ], - note: "${model.trade!.payInCurrency.toUpperCase()}/" + recipients: [(address: address, amount: amount, isChange: false)], + note: + "${model.trade!.payInCurrency.toUpperCase()}/" "${model.trade!.payOutCurrency.toUpperCase()} exchange", ), ); } else { - final memo = wallet.info.coin is Stellar - ? model.trade!.payInExtraId.isNotEmpty - ? model.trade!.payInExtraId - : null - : null; + final memo = + wallet.info.coin is Stellar + ? model.trade!.payInExtraId.isNotEmpty + ? model.trade!.payInExtraId + : null + : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: address, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: address, amount: amount, isChange: false)], memo: memo, feeRateType: FeeRateType.average, - note: "${model.trade!.payInCurrency.toUpperCase()}/" + note: + "${model.trade!.payInCurrency.toUpperCase()}/" "${model.trade!.payOutCurrency.toUpperCase()} exchange", ), ); } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); final txData = results.first as TxData; @@ -301,13 +274,14 @@ class _Step4ViewState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmChangeNowSendView( - txData: txData, - walletId: tuple.item1, - routeOnSuccessName: HomeView.routeName, - trade: model.trade!, - shouldSendPublicFiroFunds: firoPublicSend, - ), + builder: + (_) => ConfirmChangeNowSendView( + txData: txData, + walletId: tuple.item1, + routeOnSuccessName: HomeView.routeName, + trade: model.trade!, + shouldSendPublicFiroFunds: firoPublicSend, + ), settings: const RouteSettings( name: ConfirmChangeNowSendView.routeName, ), @@ -338,9 +312,10 @@ class _Step4ViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), ), onPressed: () { @@ -357,8 +332,10 @@ class _Step4ViewState extends ConsumerState { @override Widget build(BuildContext context) { - final bool isWalletCoin = - _isWalletCoinAndHasWallet(model.trade!.payInCurrency, ref); + final bool isWalletCoin = _isWalletCoinAndHasWallet( + model.trade!.payInCurrency, + ref, + ); return WillPopScope( onWillPop: () async { await _close(); @@ -379,17 +356,15 @@ class _Step4ViewState extends ConsumerState { Assets.svg.x, width: 24, height: 24, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: _close, ), ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), body: LayoutBuilder( builder: (context, constraints) { @@ -407,59 +382,51 @@ class _Step4ViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - StepRow( - count: 4, - current: 3, - width: width, - ), - const SizedBox( - height: 14, - ), + StepRow(count: 4, current: 3, width: width), + const SizedBox(height: 14), Text( "Send ${model.sendTicker.toUpperCase()} to the address below", style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Text( "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", style: STextStyles.itemSubtitle(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, + color: + Theme.of( + context, + ).extension()!.warningBackground, child: RichText( text: TextSpan( text: "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ", style: STextStyles.label700(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of(context) + .extension()! + .warningForeground, ), children: [ TextSpan( text: "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.", - style: - STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, ), ), ], ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -470,8 +437,9 @@ class _Step4ViewState extends ConsumerState { children: [ Text( "Amount", - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), GestureDetector( onTap: () async { @@ -493,14 +461,13 @@ class _Step4ViewState extends ConsumerState { children: [ SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of(context) + .extension()! + .infoItemIcons, width: 10, ), - const SizedBox( - width: 4, - ), + const SizedBox(width: 4), Text( "Copy", style: STextStyles.link2(context), @@ -510,9 +477,7 @@ class _Step4ViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", style: STextStyles.itemSubtitle12(context), @@ -520,9 +485,7 @@ class _Step4ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -533,8 +496,9 @@ class _Step4ViewState extends ConsumerState { children: [ Text( "Send ${model.sendTicker.toUpperCase()} to this address", - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), GestureDetector( onTap: () async { @@ -556,14 +520,13 @@ class _Step4ViewState extends ConsumerState { children: [ SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of(context) + .extension()! + .infoItemIcons, width: 10, ), - const SizedBox( - width: 4, - ), + const SizedBox(width: 4), Text( "Copy", style: STextStyles.link2(context), @@ -573,9 +536,7 @@ class _Step4ViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( model.trade!.payInAddress, style: STextStyles.itemSubtitle12(context), @@ -583,9 +544,7 @@ class _Step4ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), if (model.trade!.payInExtraId.isNotEmpty) RoundedWhiteContainer( child: Column( @@ -597,8 +556,9 @@ class _Step4ViewState extends ConsumerState { children: [ Text( "Memo", - style: - STextStyles.itemSubtitle(context), + style: STextStyles.itemSubtitle( + context, + ), ), GestureDetector( onTap: () async { @@ -621,39 +581,38 @@ class _Step4ViewState extends ConsumerState { children: [ SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, width: 10, ), - const SizedBox( - width: 4, - ), + const SizedBox(width: 4), Text( "Copy", - style: - STextStyles.link2(context), + style: STextStyles.link2( + context, + ), ), ], ), ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( model.trade!.payInExtraId, - style: - STextStyles.itemSubtitle12(context), + style: STextStyles.itemSubtitle12( + context, + ), ), ], ), ), if (model.trade!.payInExtraId.isNotEmpty) - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), RoundedWhiteContainer( child: Row( children: [ @@ -666,12 +625,11 @@ class _Step4ViewState extends ConsumerState { children: [ Text( model.trade!.tradeId, - style: - STextStyles.itemSubtitle12(context), - ), - const SizedBox( - width: 10, + style: STextStyles.itemSubtitle12( + context, + ), ), + const SizedBox(width: 10), GestureDetector( onTap: () async { final data = ClipboardData( @@ -690,9 +648,10 @@ class _Step4ViewState extends ConsumerState { }, child: SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of(context) + .extension()! + .infoItemIcons, width: 12, ), ), @@ -701,9 +660,7 @@ class _Step4ViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), RoundedWhiteContainer( child: Row( mainAxisAlignment: @@ -715,8 +672,9 @@ class _Step4ViewState extends ConsumerState { ), Text( _statusString, - style: STextStyles.itemSubtitle(context) - .copyWith( + style: STextStyles.itemSubtitle( + context, + ).copyWith( color: Theme.of(context) .extension()! .colorForStatus(_statusString), @@ -726,9 +684,7 @@ class _Step4ViewState extends ConsumerState { ), ), const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), TextButton( onPressed: () { showDialog( @@ -738,9 +694,7 @@ class _Step4ViewState extends ConsumerState { return StackDialogBase( child: Column( children: [ - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Center( child: Text( "Send ${model.sendTicker} to this address", @@ -749,31 +703,30 @@ class _Step4ViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Center( child: QR( // TODO: grab coin uri scheme from somewhere // data: "${coin.uriScheme}:$receivingAddress", data: model.trade!.payInAddress, - size: MediaQuery.of(context) - .size - .width / + size: + MediaQuery.of( + context, + ).size.width / 2, ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Row( children: [ const Spacer(), Expanded( child: TextButton( - onPressed: () => - Navigator.of(context) - .pop(), + onPressed: + () => + Navigator.of( + context, + ).pop(), style: Theme.of(context) .extension()! .getSecondaryEnabledButtonStyle( @@ -784,10 +737,12 @@ class _Step4ViewState extends ConsumerState { style: STextStyles.button( context, ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .buttonTextSecondary, + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonTextSecondary, ), ), ), @@ -808,76 +763,83 @@ class _Step4ViewState extends ConsumerState { style: STextStyles.button(context), ), ), - if (isWalletCoin) - const SizedBox( - height: 12, - ), + if (isWalletCoin) const SizedBox(height: 12), if (isWalletCoin) Builder( builder: (context) { String buttonTitle = "Send from ${AppConfig.appName}"; - final tuple = ref - .read( - exchangeSendFromWalletIdStateProvider - .state, - ) - .state; + final tuple = + ref + .read( + exchangeSendFromWalletIdStateProvider + .state, + ) + .state; if (tuple != null && model.sendTicker.toLowerCase() == tuple.item2.ticker.toLowerCase()) { - final walletName = ref - .read(pWallets) - .getWallet(tuple.item1) - .info - .name; + final walletName = + ref + .read(pWallets) + .getWallet(tuple.item1) + .info + .name; buttonTitle = "Send from $walletName"; } return TextButton( - onPressed: tuple != null && - model.sendTicker.toLowerCase() == - tuple.item2.ticker.toLowerCase() - ? () async { - await _confirmSend(tuple); - } - : () { - Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: - (BuildContext context) { - final coin = AppConfig.coins - .firstWhere( - (e) => - e.ticker - .toLowerCase() == - model.trade! - .payInCurrency - .toLowerCase(), - ); - - return SendFromView( - coin: coin, - amount: model.sendAmount - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - address: model - .trade!.payInAddress, - trade: model.trade!, - ); - }, - settings: const RouteSettings( - name: SendFromView.routeName, + onPressed: + tuple != null && + model.sendTicker + .toLowerCase() == + tuple.item2.ticker + .toLowerCase() + ? () async { + await _confirmSend(tuple); + } + : () { + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: ( + BuildContext context, + ) { + final coin = AppConfig.coins + .firstWhere( + (e) => + e.ticker + .toLowerCase() == + model + .trade! + .payInCurrency + .toLowerCase(), + ); + + return SendFromView( + coin: coin, + amount: model.sendAmount + .toAmount( + fractionDigits: + coin.fractionDigits, + ), + address: + model + .trade! + .payInAddress, + trade: model.trade!, + ); + }, + settings: const RouteSettings( + name: + SendFromView.routeName, + ), ), - ), - ); - }, + ); + }, style: Theme.of(context) .extension()! .getSecondaryEnabledButtonStyle( @@ -885,11 +847,13 @@ class _Step4ViewState extends ConsumerState { ), child: Text( buttonTitle, - style: - STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), ), ); diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 7e97017a3..850623031 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -91,12 +91,13 @@ class _SendFromViewState extends ConsumerState { Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final walletIds = ref - .watch(pWallets) - .wallets - .where((e) => e.info.coin == coin) - .map((e) => e.walletId) - .toList(); + final walletIds = + ref + .watch(pWallets) + .wallets + .where((e) => e.info.coin == coin) + .map((e) => e.walletId) + .toList(); final isDesktop = Util.isDesktop; @@ -113,55 +114,49 @@ class _SendFromViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Send from", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + title: Text("Send from", style: STextStyles.navBarTitle(context)), ), + body: Padding(padding: const EdgeInsets.all(16), child: child), ), ); }, child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxHeight: double.infinity, + child: Column( children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Send from ${AppConfig.prefix}", + style: STextStyles.desktopH3(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of( + context, + rootNavigator: widget.shouldPopRoot, + ).pop, + ), + ], + ), Padding( padding: const EdgeInsets.only( left: 32, + right: 32, + bottom: 32, ), - child: Text( - "Send from ${AppConfig.prefix}", - style: STextStyles.desktopH3(context), - ), - ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: widget.shouldPopRoot, - ).pop, + child: child, ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: child, - ), - ], - ), - ), + ), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -169,20 +164,17 @@ class _SendFromViewState extends ConsumerState { children: [ Text( "You need to send ${ref.watch(pAmountFormatter(coin)).format(amount)}", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.itemSubtitle(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.itemSubtitle(context), ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ListView.builder( primary: isDesktop ? false : null, shrinkWrap: isDesktop, @@ -250,14 +242,15 @@ class _SendFromCardState extends ConsumerState { builder: (context) { return ConditionalParent( condition: Util.isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 400, - maxHeight: double.infinity, - child: Padding( - padding: const EdgeInsets.all(32), - child: child, - ), - ), + builder: + (child) => DesktopDialog( + maxWidth: 400, + maxHeight: double.infinity, + child: Padding( + padding: const EdgeInsets.all(32), + child: child, + ), + ), child: BuildingTransactionDialog( coin: coin, isSpark: @@ -282,31 +275,22 @@ class _SendFromCardState extends ConsumerState { await wallet.open(); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); TxData txData; Future txDataFuture; // if not firo then do normal send if (shouldSendPublicFiroFunds == null) { - final memo = coin is Stellar - ? trade.payInExtraId.isNotEmpty - ? trade.payInExtraId - : null - : null; + final memo = + coin is Stellar + ? trade.payInExtraId.isNotEmpty + ? trade.payInExtraId + : null + : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: address, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: address, amount: amount, isChange: false)], memo: memo, feeRateType: FeeRateType.average, ), @@ -317,36 +301,21 @@ class _SendFromCardState extends ConsumerState { if (shouldSendPublicFiroFunds) { txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: address, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: address, amount: amount, isChange: false)], feeRateType: FeeRateType.average, ), ); } else { txDataFuture = firoWallet.prepareSendSpark( txData: TxData( - recipients: [ - ( - address: address, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: address, amount: amount, isChange: false)], // feeRateType: FeeRateType.average, ), ); } } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); txData = results.first as TxData; @@ -354,14 +323,12 @@ class _SendFromCardState extends ConsumerState { // pop building dialog if (mounted) { - Navigator.of( - context, - rootNavigator: Util.isDesktop, - ).pop(); + Navigator.of(context, rootNavigator: Util.isDesktop).pop(); } txData = txData.copyWith( - note: "${trade.payInCurrency.toUpperCase()}/" + note: + "${trade.payInCurrency.toUpperCase()}/" "${trade.payOutCurrency.toUpperCase()} exchange", ); @@ -369,16 +336,18 @@ class _SendFromCardState extends ConsumerState { await Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmChangeNowSendView( - txData: txData, - walletId: walletId, - routeOnSuccessName: Util.isDesktop - ? DesktopExchangeView.routeName - : HomeView.routeName, - trade: trade, - shouldSendPublicFiroFunds: shouldSendPublicFiroFunds, - fromDesktopStep4: widget.fromDesktopStep4, - ), + builder: + (_) => ConfirmChangeNowSendView( + txData: txData, + walletId: walletId, + routeOnSuccessName: + Util.isDesktop + ? DesktopExchangeView.routeName + : HomeView.routeName, + trade: trade, + shouldSendPublicFiroFunds: shouldSendPublicFiroFunds, + fromDesktopStep4: widget.fromDesktopStep4, + ), settings: const RouteSettings( name: ConfirmChangeNowSendView.routeName, ), @@ -407,9 +376,10 @@ class _SendFromCardState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), ), onPressed: () { @@ -448,86 +418,154 @@ class _SendFromCardState extends ConsumerState { padding: const EdgeInsets.all(0), child: ConditionalParent( condition: isFiro, - builder: (child) => Expandable( - header: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(12), - child: child, - ), - ), - body: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MaterialButton( - splashColor: - Theme.of(context).extension()!.highlight, - key: Key("walletsSheetItemButtonFiroPrivateKey_$walletId"), - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () async { - if (mounted) { - unawaited( - _send( - shouldSendPublicFiroFunds: false, + builder: + (child) => Expandable( + header: Container( + color: Colors.transparent, + child: Padding(padding: const EdgeInsets.all(12), child: child), + ), + body: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MaterialButton( + splashColor: + Theme.of(context).extension()!.highlight, + key: Key("walletsSheetItemButtonFiroPrivateKey_$walletId"), + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - } - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - top: 6, - left: 16, - right: 16, - bottom: 6, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + onPressed: () async { + if (mounted) { + unawaited(_send(shouldSendPublicFiroFunds: false)); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + top: 6, + left: 16, + right: 16, + bottom: 6, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Use private balance", - style: STextStyles.itemSubtitle(context), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Use private balance", + style: STextStyles.itemSubtitle(context), + ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch( + pWalletBalanceTertiary(walletId), + ) + .spendable, + ), + style: STextStyles.itemSubtitle(context), + ), + ], ), - Text( - ref.watch(pAmountFormatter(coin)).format( - ref - .watch(pWalletBalanceTertiary(walletId)) - .spendable, - ), - style: STextStyles.itemSubtitle(context), + SvgPicture.asset( + Assets.svg.chevronRight, + height: 14, + width: 7, + color: + Theme.of( + context, + ).extension()!.infoItemLabel, ), ], ), - SvgPicture.asset( - Assets.svg.chevronRight, - height: 14, - width: 7, - color: Theme.of(context) - .extension()! - .infoItemLabel, + ), + ), + ), + MaterialButton( + splashColor: + Theme.of(context).extension()!.highlight, + key: Key("walletsSheetItemButtonFiroPublicKey_$walletId"), + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () async { + if (mounted) { + unawaited(_send(shouldSendPublicFiroFunds: true)); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + top: 6, + left: 16, + right: 16, + bottom: 6, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Use public balance", + style: STextStyles.itemSubtitle(context), + ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch(pWalletBalance(walletId)) + .spendable, + ), + style: STextStyles.itemSubtitle(context), + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronRight, + height: 14, + width: 7, + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ], ), - ], + ), ), ), - ), + const SizedBox(height: 6), + ], ), - MaterialButton( + ), + child: ConditionalParent( + condition: !isFiro, + builder: + (child) => MaterialButton( splashColor: Theme.of(context).extension()!.highlight, - key: Key("walletsSheetItemButtonFiroPublicKey_$walletId"), - padding: const EdgeInsets.all(0), + key: Key("walletsSheetItemButtonKey_$walletId"), + padding: const EdgeInsets.all(8), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( @@ -536,83 +574,11 @@ class _SendFromCardState extends ConsumerState { ), onPressed: () async { if (mounted) { - unawaited( - _send( - shouldSendPublicFiroFunds: true, - ), - ); + unawaited(_send()); } }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - top: 6, - left: 16, - right: 16, - bottom: 6, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Use public balance", - style: STextStyles.itemSubtitle(context), - ), - Text( - ref.watch(pAmountFormatter(coin)).format( - ref - .watch(pWalletBalance(walletId)) - .spendable, - ), - style: STextStyles.itemSubtitle(context), - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronRight, - height: 14, - width: 7, - color: Theme.of(context) - .extension()! - .infoItemLabel, - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 6, - ), - ], - ), - ), - child: ConditionalParent( - condition: !isFiro, - builder: (child) => MaterialButton( - splashColor: Theme.of(context).extension()!.highlight, - key: Key("walletsSheetItemButtonKey_$walletId"), - padding: const EdgeInsets.all(8), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + child: child, ), - ), - onPressed: () async { - if (mounted) { - unawaited( - _send(), - ); - } - }, - child: child, - ), child: Row( children: [ Container( @@ -625,19 +591,13 @@ class _SendFromCardState extends ConsumerState { child: Padding( padding: const EdgeInsets.all(6), child: SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -647,13 +607,12 @@ class _SendFromCardState extends ConsumerState { ref.watch(pWalletName(walletId)), style: STextStyles.titleBold12(context), ), - if (!isFiro) - const SizedBox( - height: 2, - ), + if (!isFiro) const SizedBox(height: 2), if (!isFiro) Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref.watch(pWalletBalance(walletId)).spendable, ), style: STextStyles.itemSubtitle(context), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 4bdcef6e2..de49b386b 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -150,13 +150,12 @@ class _SendViewState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final Amount amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: coin.fractionDigits); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); ref.read(pSendAmount.notifier).state = amount; } @@ -244,23 +243,21 @@ class _SendViewState extends ConsumerState { if (_price == Decimal.zero) { amount = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); } else { - amount = baseAmount <= Amount.zero - ? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits) - : (baseAmount.decimal / _price) - .toDecimal( - scaleOnInfinitePrecision: coin.fractionDigits, - ) - .toAmount(fractionDigits: coin.fractionDigits); + amount = + baseAmount <= Amount.zero + ? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits) + : (baseAmount.decimal / _price) + .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) + .toAmount(fractionDigits: coin.fractionDigits); } if (_cachedAmountToSend != null && _cachedAmountToSend == amount) { return; } _cachedAmountToSend = amount; - final amountString = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final amountString = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChangeLock = true; cryptoAmountController.text = amountString; @@ -281,9 +278,9 @@ class _SendViewState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( - cryptoAmountController.text, - ); + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse(cryptoAmountController.text); final Amount? amount; if (cryptoAmount != null) { amount = cryptoAmount; @@ -297,9 +294,7 @@ class _SendViewState extends ConsumerState { if (price > Decimal.zero) { baseAmountController.text = (amount.decimal * price) - .toAmount( - fractionDigits: 2, - ) + .toAmount(fractionDigits: 2) .fiatString( locale: ref.read(localeServiceChangeNotifierProvider).locale, ); @@ -356,10 +351,12 @@ class _SendViewState extends ConsumerState { fee = fee.split(" ").first; } - final value = fee.contains(",") - ? Decimal.parse(fee.replaceFirst(",", ".")) - .toAmount(fractionDigits: coin.fractionDigits) - : Decimal.parse(fee).toAmount(fractionDigits: coin.fractionDigits); + final value = + fee.contains(",") + ? Decimal.parse( + fee.replaceFirst(",", "."), + ).toAmount(fractionDigits: coin.fractionDigits) + : Decimal.parse(fee).toAmount(fractionDigits: coin.fractionDigits); if (shouldSetState) { setState(() => _currentFee = value); @@ -368,36 +365,21 @@ class _SendViewState extends ConsumerState { } } - String? _updateInvalidAddressText(String address) { - if (_data != null && _data.contactLabel == address) { - return null; - } - - if (address.isNotEmpty && - !ref - .read(pWallets) - .getWallet(walletId) - .cryptoCurrency - .validateAddress(address)) { - return "Invalid address"; - } - return null; - } - void _setValidAddressProviders(String? address) { if (isPaynymSend) { ref.read(pValidSendToAddress.notifier).state = true; } else { final wallet = ref.read(pWallets).getWallet(walletId); if (wallet is SparkInterface) { - ref.read(pValidSparkSendToAddress.notifier).state = - SparkInterface.validateSparkAddress( + ref + .read(pValidSparkSendToAddress.notifier) + .state = SparkInterface.validateSparkAddress( address: address ?? "", isTestNet: wallet.cryptoCurrency.network.isTestNet, ); - ref.read(pIsExchangeAddress.state).state = - (coin as Firo).isExchangeAddress(address ?? ""); + ref.read(pIsExchangeAddress.state).state = (coin as Firo) + .isExchangeAddress(address ?? ""); if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && ref.read(pIsExchangeAddress) && @@ -410,8 +392,8 @@ class _SendViewState extends ConsumerState { } } - ref.read(pValidSendToAddress.notifier).state = - wallet.cryptoCurrency.validateAddress(address ?? ""); + ref.read(pValidSendToAddress.notifier).state = wallet.cryptoCurrency + .validateAddress(address ?? ""); } } @@ -486,11 +468,9 @@ class _SendViewState extends ConsumerState { } fee = await wallet.estimateFeeFor(amount, specialMoneroId.value); - cachedFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFees[amount]!; } else if (isFiro) { @@ -499,39 +479,29 @@ class _SendViewState extends ConsumerState { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case FiroType.public: fee = await firoWallet.estimateFeeFor(amount, feeRate); - cachedFiroPublicFees[amount] = - ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroPublicFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroPublicFees[amount]!; case FiroType.lelantus: fee = await firoWallet.estimateFeeForLelantus(amount); - cachedFiroLelantusFees[amount] = - ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroLelantusFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroLelantusFees[amount]!; case FiroType.spark: fee = await firoWallet.estimateFeeForSpark(amount); - cachedFiroSparkFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFiroSparkFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroSparkFees[amount]!; } } else { fee = await wallet.estimateFeeFor(amount, feeRate); - cachedFees[amount] = ref.read(pAmountFormatter(coin)).format( - fee, - withUnitName: true, - indicatePrecisionLoss: false, - ); + cachedFees[amount] = ref + .read(pAmountFormatter(coin)) + .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFees[amount]!; } @@ -540,9 +510,7 @@ class _SendViewState extends ConsumerState { Future _previewTransaction() async { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); final wallet = ref.read(pWallets).getWallet(walletId); final Amount amount = ref.read(pSendAmount)!; @@ -591,9 +559,10 @@ class _SendViewState extends ConsumerState { child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -604,10 +573,7 @@ class _SendViewState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Yes", - style: STextStyles.button(context), - ), + child: Text("Yes", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -636,7 +602,8 @@ class _SendViewState extends ConsumerState { builder: (context) { return BuildingTransactionDialog( coin: wallet.info.coin, - isSpark: wallet is FiroWallet && + isSpark: + wallet is FiroWallet && ref.read(publicPrivateBalanceStateProvider.state).state == FiroType.spark, onCancel: () { @@ -650,11 +617,7 @@ class _SendViewState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); Future txDataFuture; @@ -672,11 +635,12 @@ class _SendViewState extends ConsumerState { ], satsPerVByte: isCustomFee ? customFeeRate : null, feeRateType: feeRate, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } else if (wallet is FiroWallet) { @@ -695,26 +659,24 @@ class _SendViewState extends ConsumerState { ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (coinControlEnabled && selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } else { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (coinControlEnabled && selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (coinControlEnabled && selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } @@ -724,11 +686,7 @@ class _SendViewState extends ConsumerState { txDataFuture = wallet.prepareSendLelantus( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], ), ); @@ -737,25 +695,23 @@ class _SendViewState extends ConsumerState { case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: ref.read(pValidSparkSendToAddress) - ? null - : [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], - sparkRecipients: ref.read(pValidSparkSendToAddress) - ? [ - ( - address: _address!, - amount: amount, - memo: memoController.text, - isChange: false, - ), - ] - : null, + recipients: + ref.read(pValidSparkSendToAddress) + ? null + : [ + (address: _address!, amount: amount, isChange: false), + ], + sparkRecipients: + ref.read(pValidSparkSendToAddress) + ? [ + ( + address: _address!, + amount: amount, + memo: memoController.text, + isChange: false, + ), + ] + : null, ), ); break; @@ -764,29 +720,21 @@ class _SendViewState extends ConsumerState { final memo = coin is Stellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, ), ); } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); TxData txData = results.first as TxData; @@ -794,9 +742,10 @@ class _SendViewState extends ConsumerState { if (isPaynymSend) { txData = txData.copyWith( paynymAccountLite: widget.accountLite!, - note: noteController.text.isNotEmpty - ? noteController.text - : "PayNym send", + note: + noteController.text.isNotEmpty + ? noteController.text + : "PayNym send", ); } else { txData = txData.copyWith(note: noteController.text); @@ -810,12 +759,13 @@ class _SendViewState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: txData, - walletId: walletId, - isPaynymTransaction: isPaynymSend, - onSuccess: clearSendForm, - ), + builder: + (_) => ConfirmTransactionView( + txData: txData, + walletId: walletId, + isPaynymTransaction: isPaynymSend, + onSuccess: clearSendForm, + ), settings: const RouteSettings( name: ConfirmTransactionView.routeName, ), @@ -845,9 +795,10 @@ class _SendViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -886,10 +837,9 @@ class _SendViewState extends ConsumerState { } Amount _selectedUtxosAmount(Set utxos) => Amount( - rawValue: - utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), - fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, - ); + rawValue: utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), + fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, + ); Future _sendAllTapped(bool showCoinControl) async { final Amount amount; @@ -912,10 +862,9 @@ class _SendViewState extends ConsumerState { amount = ref.read(pWalletBalance(walletId)).spendable; } - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChanged(); } @@ -934,8 +883,9 @@ class _SendViewState extends ConsumerState { }); _currentFee = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); - _calculateFeesFuture = - calculateFees(0.toAmountAsRaw(fractionDigits: coin.fractionDigits)); + _calculateFeesFuture = calculateFees( + 0.toAmountAsRaw(fractionDigits: coin.fractionDigits), + ); _data = widget.autoFillData; walletId = widget.walletId; clipboard = widget.clipboard; @@ -962,10 +912,9 @@ class _SendViewState extends ConsumerState { fractionDigits: coin.fractionDigits, ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); } sendToController.text = _data.contactLabel; _address = _data.address.trim(); @@ -1051,7 +1000,8 @@ class _SendViewState extends ConsumerState { localeServiceChangeNotifierProvider.select((value) => value.locale), ); - final showCoinControl = wallet is CoinControlInterface && + final showCoinControl = + wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, @@ -1075,9 +1025,7 @@ class _SendViewState extends ConsumerState { }); } else { setState(() { - _calculateFeesFuture = calculateFees( - ref.read(pSendAmount)!, - ); + _calculateFeesFuture = calculateFees(ref.read(pSendAmount)!); }); } @@ -1135,11 +1083,7 @@ class _SendViewState extends ConsumerState { body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -1154,9 +1098,10 @@ class _SendViewState extends ConsumerState { children: [ Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -1166,25 +1111,20 @@ class _SendViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 22, height: 22, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context) - .copyWith(fontSize: 14), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -1194,14 +1134,16 @@ class _SendViewState extends ConsumerState { if (isFiro) Text( "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), if (coin is! Firo) Text( "Available balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), ], ), @@ -1217,33 +1159,39 @@ class _SendViewState extends ConsumerState { ) .state) { case FiroType.public: - amount = ref - .read(pWalletBalance(walletId)) - .spendable; + amount = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; break; case FiroType.lelantus: - amount = ref - .read( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; + amount = + ref + .read( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; break; case FiroType.spark: - amount = ref - .read( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; + amount = + ref + .read( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; break; } } else { - amount = ref - .read(pWalletBalance(walletId)) - .spendable; + amount = + ref + .read(pWalletBalance(walletId)) + .spendable; } return GestureDetector( @@ -1269,22 +1217,14 @@ class _SendViewState extends ConsumerState { .format(amount), style: STextStyles.titleBold12( context, - ).copyWith( - fontSize: 10, - ), + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), Text( - "${(amount.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1))).toAmount( - fractionDigits: 2, - ).fiatString( - locale: locale, - )} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + "${(amount.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1))).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", style: STextStyles.subtitle( context, - ).copyWith( - fontSize: 8, - ), + ).copyWith(fontSize: 8), textAlign: TextAlign.right, ), ], @@ -1297,9 +1237,7 @@ class _SendViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -1327,9 +1265,7 @@ class _SendViewState extends ConsumerState { // ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (isPaynymSend) TextField( key: const Key("sendViewPaynymAddressFieldKey"), @@ -1362,7 +1298,9 @@ class _SendViewState extends ConsumerState { onChanged: (newValue) { final trimmed = newValue.trim(); - if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { + if ((trimmed.length - (_address?.length ?? 0)) + .abs() > + 1) { final parsed = AddressUtils.parsePaymentUri( trimmed, logging: Logging.instance, @@ -1397,9 +1335,10 @@ class _SendViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: @@ -1407,87 +1346,93 @@ class _SendViewState extends ConsumerState { children: [ _addressToggleFlag ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Address Field Input.", - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders( - _address, - ); - setState(() { - _addressToggleFlag = - false; - }); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders( + _address, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data! - .text!.isNotEmpty) { - String content = - data.text!.trim(); - if (content - .contains("\n")) { - content = - content.substring( - 0, - content.indexOf( - "\n", - ), - ); - } + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + String content = + data.text!.trim(); + if (content.contains( + "\n", + )) { + content = content + .substring( + 0, + content.indexOf( + "\n", + ), + ); + } - if (coin is Epiccash) { - // strip http:// and https:// if content contains @ - content = AddressUtils() - .formatAddress( - content, - ); - } + if (coin is Epiccash) { + // strip http:// and https:// if content contains @ + content = AddressUtils() + .formatAddress( + content, + ); + } - final trimmed = content.trim(); - final parsed = AddressUtils.parsePaymentUri( - trimmed, - logging: Logging.instance, + final trimmed = + content.trim(); + final parsed = + AddressUtils.parsePaymentUri( + trimmed, + logging: + Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + sendToController.text = + content; + _address = content; + + _setValidAddressProviders( + _address, ); - if (parsed != null) { - _applyUri(parsed); - } else { - sendToController.text = - content; - _address = content; - - _setValidAddressProviders(_address,); - setState(() { - _addressToggleFlag = - sendToController - .text - .isNotEmpty; - }); - } + setState(() { + _addressToggleFlag = + sendToController + .text + .isNotEmpty; + }); } - }, - child: sendToController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + } + }, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( semanticsLabel: @@ -1520,9 +1465,7 @@ class _SendViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (isStellar || (ref.watch(pValidSparkSendToAddress) && ref.watch( @@ -1558,9 +1501,10 @@ class _SendViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: @@ -1568,42 +1512,41 @@ class _SendViewState extends ConsumerState { children: [ memoController.text.isNotEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Memo Field Input.", - key: const Key( - "sendViewClearMemoFieldButtonKey", - ), - onTap: () { - memoController.text = ""; - setState(() {}); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Memo Field Input.", + key: const Key( + "sendViewClearMemoFieldButtonKey", + ), + onTap: () { + memoController.text = ""; + setState(() {}); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Memo Field Input.", - key: const Key( - "sendViewPasteMemoFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data! - .text!.isNotEmpty) { - final String content = - data.text!.trim(); - - memoController.text = - content.trim(); - - setState(() {}); - } - }, - child: const ClipboardIcon(), + semanticsLabel: + "Paste Button. Pastes From Clipboard To Memo Field Input.", + key: const Key( + "sendViewPasteMemoFieldButtonKey", ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + final String content = + data.text!.trim(); + + memoController.text = + content.trim(); + + setState(() {}); + } + }, + child: const ClipboardIcon(), + ), ], ), ), @@ -1624,20 +1567,24 @@ class _SendViewState extends ConsumerState { FiroType.lelantus) { if (_data != null && _data.contactLabel == _address) { - error = SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: coin.network == - CryptoCurrencyNetwork.test, - ) - ? "Unsupported" - : null; - } else if (ref - .watch(pValidSparkSendToAddress)) { + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: + coin.network == + CryptoCurrencyNetwork.test, + ) + ? "Unsupported" + : null; + } else if (ref.watch( + pValidSparkSendToAddress, + )) { error = "Unsupported"; } else { - error = ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; } } else { if (_data != null && @@ -1674,11 +1621,13 @@ class _SendViewState extends ConsumerState { child: Text( error, textAlign: TextAlign.left, - style: - STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, ), ), ), @@ -1686,20 +1635,14 @@ class _SendViewState extends ConsumerState { } }, ), - if (isFiro) - const SizedBox( - height: 12, - ), + if (isFiro) const SizedBox(height: 12), if (isFiro) Text( "Send from", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (isFiro) - const SizedBox( - height: 8, - ), + if (isFiro) const SizedBox(height: 8), if (isFiro) Stack( children: [ @@ -1715,9 +1658,10 @@ class _SendViewState extends ConsumerState { horizontal: 12, ), child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, + splashColor: + Theme.of( + context, + ).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1732,10 +1676,10 @@ class _SendViewState extends ConsumerState { top: Radius.circular(20), ), ), - builder: (_) => - FiroBalanceSelectionSheet( - walletId: walletId, - ), + builder: + (_) => FiroBalanceSelectionSheet( + walletId: walletId, + ), ); }, child: Row( @@ -1750,9 +1694,7 @@ class _SendViewState extends ConsumerState { context, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Builder( builder: (_) { final Amount amount; @@ -1763,31 +1705,34 @@ class _SendViewState extends ConsumerState { ) .state) { case FiroType.public: - amount = ref - .watch( - pWalletBalance( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalance( + walletId, + ), + ) + .spendable; break; case FiroType.lelantus: - amount = ref - .watch( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; break; case FiroType.spark: - amount = ref - .watch( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; + amount = + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; break; } @@ -1796,13 +1741,11 @@ class _SendViewState extends ConsumerState { .watch( pAmountFormatter(coin), ) - .format( - amount, - ), + .format(amount), style: STextStyles.itemSubtitle( - context, - ), + context, + ), ); }, ), @@ -1812,9 +1755,10 @@ class _SendViewState extends ConsumerState { Assets.svg.chevronDown, width: 8, height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of(context) + .extension()! + .textSubtitle2, ), ], ), @@ -1822,9 +1766,7 @@ class _SendViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -1843,27 +1785,28 @@ class _SendViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldCryptoTextFieldKey", ), - key: - const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1888,10 +1831,9 @@ class _SendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( @@ -1900,11 +1842,13 @@ class _SendViewState extends ConsumerState { ref .watch(pAmountUnit(coin)) .unitForCoin(coin), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -1912,28 +1856,29 @@ class _SendViewState extends ConsumerState { ), ), if (Prefs.instance.externalCalls) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", ), - key: - const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1956,34 +1901,33 @@ class _SendViewState extends ConsumerState { right: 12, ), hintText: "0", - hintStyle: - STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), - style: STextStyles.smallMed14(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), ), ), ), - if (showCoinControl) - const SizedBox( - height: 8, - ), + if (showCoinControl) const SizedBox(height: 8), if (showCoinControl) RoundedWhiteContainer( child: Row( @@ -1992,17 +1936,20 @@ class _SendViewState extends ConsumerState { children: [ Text( "Coin control", - style: - STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + style: STextStyles.w500_14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ), CustomTextButton( - text: selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", onTap: () async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); @@ -2012,9 +1959,10 @@ class _SendViewState extends ConsumerState { } if (context.mounted) { - final spendable = ref - .read(pWalletBalance(walletId)) - .spendable; + final spendable = + ref + .read(pWalletBalance(walletId)) + .spendable; Amount? amount; if (ref.read(pSendAmount) != null) { @@ -2027,9 +1975,9 @@ class _SendViewState extends ConsumerState { } } - final result = - await Navigator.of(context) - .pushNamed( + final result = await Navigator.of( + context, + ).pushNamed( CoinControlView.routeName, arguments: Tuple4( walletId, @@ -2050,19 +1998,14 @@ class _SendViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is Epiccash) Text( "On chain Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) - const SizedBox( - height: 8, - ), + if (coin is Epiccash) const SizedBox(height: 8), if (coin is Epiccash) ClipRRect( borderRadius: BorderRadius.circular( @@ -2082,35 +2025,33 @@ class _SendViewState extends ConsumerState { _onChainNoteFocusNode, context, ).copyWith( - suffixIcon: onChainNoteController - .text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - onChainNoteController - .text = ""; - }); - }, - ), - ], + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController + .text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), - if (coin is Epiccash) - const SizedBox( - height: 12, - ), + if (coin is Epiccash) const SizedBox(height: 12), Text( (coin is Epiccash) ? "Local Note (optional)" @@ -2118,9 +2059,7 @@ class _SendViewState extends ConsumerState { style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -2137,32 +2076,32 @@ class _SendViewState extends ConsumerState { _noteFocusNode, context, ).copyWith( - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) @@ -2174,9 +2113,7 @@ class _SendViewState extends ConsumerState { if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos) @@ -2195,193 +2132,212 @@ class _SendViewState extends ConsumerState { horizontal: 12, ), child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, + splashColor: + Theme.of( + context, + ).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), - onPressed: isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public - ? null - : () { - showModalBottomSheet( - backgroundColor: - Colors.transparent, - context: context, - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - TransactionFeeSelectionSheet( - walletId: walletId, - amount: (Decimal.tryParse( - cryptoAmountController - .text, - ) ?? - ref - .watch(pSendAmount) - ?.decimal ?? - Decimal.zero) - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - updateChosen: (String fee) { - if (fee == "custom") { - if (!isCustomFee) { - setState(() { - isCustomFee = true; - }); - } - return; - } - - _setCurrentFee( - fee, - true, - ); - setState(() { - _calculateFeesFuture = - Future(() => fee); - if (isCustomFee) { - isCustomFee = false; - } - }); - }, - ), - ); - }, - child: (isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public) - ? Row( - children: [ - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - "~${snapshot.data!}", - style: STextStyles - .itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: STextStyles - .itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ) - : Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - ref + onPressed: + isFiro && + ref .watch( - feeRateTypeStateProvider + publicPrivateBalanceStateProvider .state, ) - .state - .prettyName, - style: STextStyles - .itemSubtitle12( - context, + .state != + FiroType.public + ? null + : () { + showModalBottomSheet( + backgroundColor: + Colors.transparent, + context: context, + shape: + const RoundedRectangleBorder( + borderRadius: + BorderRadius.vertical( + top: + Radius.circular( + 20, + ), + ), ), - ), - const SizedBox( - width: 10, - ), - FutureBuilder( - future: - _calculateFeesFuture, - builder: - (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - isCustomFee - ? "" - : "~${snapshot.data!}", - style: STextStyles - .itemSubtitle( - context, + builder: + ( + _, + ) => TransactionFeeSelectionSheet( + walletId: walletId, + amount: (Decimal.tryParse( + cryptoAmountController + .text, + ) ?? + ref + .watch( + pSendAmount, + ) + ?.decimal ?? + Decimal.zero) + .toAmount( + fractionDigits: + coin.fractionDigits, ), + updateChosen: ( + String fee, + ) { + if (fee == "custom") { + if (!isCustomFee) { + setState(() { + isCustomFee = + true; + }); + } + return; + } + + _setCurrentFee( + fee, + true, ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: STextStyles - .itemSubtitle( + setState(() { + _calculateFeesFuture = + Future(() => fee); + if (isCustomFee) { + isCustomFee = false; + } + }); + }, + ), + ); + }, + child: + (isFiro && + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) + ? Row( + children: [ + FutureBuilder( + future: _calculateFeesFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ) + : Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeStateProvider + .state, + ) + .state + .prettyName, + style: + STextStyles.itemSubtitle12( context, ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - ], - ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + isCustomFee + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textSubtitle2, + ), + ], + ), ), ), ], @@ -2400,28 +2356,26 @@ class _SendViewState extends ConsumerState { ), ), const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), TextButton( - onPressed: ref.watch(pPreviewTxButtonEnabled(coin)) - ? _previewTransaction - : null, - style: ref.watch(pPreviewTxButtonEnabled(coin)) - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + onPressed: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? _previewTransaction + : null, + style: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), child: Text( "Preview", style: STextStyles.button(context), ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ], ), ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 009893e7e..5c5b68c0f 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -155,13 +155,19 @@ class _DesktopSendState extends ConsumerState { try { _processQrCodeData(qrResult); } catch (e, s) { - Logging.instance - .e("Error processing QR code data", error: e, stackTrace: s); + Logging.instance.e( + "Error processing QR code data", + error: e, + stackTrace: s, + ); } } } catch (e, s) { - Logging.instance - .e("Error opening QR code scanner dialog", error: e, stackTrace: s); + Logging.instance.e( + "Error opening QR code scanner dialog", + error: e, + stackTrace: s, + ); } } @@ -204,10 +210,7 @@ class _DesktopSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -221,29 +224,20 @@ class _DesktopSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Text( "You are about to send your entire balance. Would you like to continue?", textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Row( children: [ Expanded( @@ -255,9 +249,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: ButtonHeight.l, @@ -301,7 +293,8 @@ class _DesktopSendState extends ConsumerState { padding: const EdgeInsets.all(32), child: BuildingTransactionDialog( coin: wallet.info.coin, - isSpark: wallet is FiroWallet && + isSpark: + wallet is FiroWallet && ref .read(publicPrivateBalanceStateProvider.state) .state == @@ -319,11 +312,7 @@ class _DesktopSendState extends ConsumerState { ); } - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); TxData txData; Future txDataFuture; @@ -344,11 +333,12 @@ class _DesktopSendState extends ConsumerState { ], satsPerVByte: isCustomFee ? customFeeRate : null, feeRateType: feeRate, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } else if (wallet is FiroWallet) { @@ -367,30 +357,28 @@ class _DesktopSendState extends ConsumerState { ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } else { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } @@ -400,11 +388,7 @@ class _DesktopSendState extends ConsumerState { txDataFuture = wallet.prepareSendLelantus( txData: TxData( recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), + (address: _address!, amount: amount, isChange: false), ], ), ); @@ -413,25 +397,23 @@ class _DesktopSendState extends ConsumerState { case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: ref.read(pValidSparkSendToAddress) - ? null - : [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], - sparkRecipients: ref.read(pValidSparkSendToAddress) - ? [ - ( - address: _address!, - amount: amount, - memo: memoController.text, - isChange: false, - ), - ] - : null, + recipients: + ref.read(pValidSparkSendToAddress) + ? null + : [ + (address: _address!, amount: amount, isChange: false), + ], + sparkRecipients: + ref.read(pValidSparkSendToAddress) + ? [ + ( + address: _address!, + amount: amount, + memo: memoController.text, + isChange: false, + ), + ] + : null, ), ); break; @@ -440,29 +422,21 @@ class _DesktopSendState extends ConsumerState { final memo = isStellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - ( - address: _address!, - amount: amount, - isChange: false, - ), - ], + recipients: [(address: _address!, amount: amount, isChange: false)], memo: memo, feeRateType: ref.read(feeRateTypeStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) - : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, ), ); } - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); txData = results.first as TxData; @@ -473,35 +447,29 @@ class _DesktopSendState extends ConsumerState { note: _note ?? "PayNym send", ); } else { - txData = txData.copyWith( - note: _note ?? "", - ); + txData = txData.copyWith(note: _note ?? ""); if (coin is Epiccash) { - txData = txData.copyWith( - noteOnChain: _onChainNote ?? "", - ); + txData = txData.copyWith(noteOnChain: _onChainNote ?? ""); } } // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: MediaQuery.of(context).size.height - 64, - maxWidth: 580, - child: ConfirmTransactionView( - txData: txData, - walletId: walletId, - onSuccess: clearSendForm, - isPaynymTransaction: isPaynymSend, - routeOnSuccessName: DesktopHomeView.routeName, - ), - ), + builder: + (context) => DesktopDialog( + maxHeight: MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: ConfirmTransactionView( + txData: txData, + walletId: walletId, + onSuccess: clearSendForm, + isPaynymTransaction: isPaynymSend, + routeOnSuccessName: DesktopHomeView.routeName, + ), + ), ), ); } @@ -509,10 +477,7 @@ class _DesktopSendState extends ConsumerState { Logging.instance.e("Desktop send: ", error: e, stackTrace: s); if (mounted) { // pop building dialog - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); unawaited( showDialog( @@ -522,10 +487,7 @@ class _DesktopSendState extends ConsumerState { maxWidth: 450, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -539,25 +501,18 @@ class _DesktopSendState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - right: 32, - ), + padding: const EdgeInsets.only(right: 32), child: Text( e.toString(), textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith(fontSize: 18), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), Row( children: [ Expanded( @@ -572,9 +527,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), ], ), ], @@ -602,9 +555,9 @@ class _DesktopSendState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse( - cryptoAmountController.text, - ); + final cryptoAmount = ref + .read(pAmountFormatter(coin)) + .tryParse(cryptoAmountController.text); final Amount? amount; if (cryptoAmount != null) { amount = cryptoAmount; @@ -685,14 +638,15 @@ class _DesktopSendState extends ConsumerState { } else { final wallet = ref.read(pWallets).getWallet(walletId); if (wallet is SparkInterface) { - ref.read(pValidSparkSendToAddress.notifier).state = - SparkInterface.validateSparkAddress( + ref + .read(pValidSparkSendToAddress.notifier) + .state = SparkInterface.validateSparkAddress( address: address ?? "", isTestNet: wallet.cryptoCurrency.network.isTestNet, ); - ref.read(pIsExchangeAddress.state).state = - (coin as Firo).isExchangeAddress(address ?? ""); + ref.read(pIsExchangeAddress.state).state = (coin as Firo) + .isExchangeAddress(address ?? ""); if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && ref.read(pIsExchangeAddress) && @@ -705,8 +659,8 @@ class _DesktopSendState extends ConsumerState { } } - ref.read(pValidSendToAddress.notifier).state = - wallet.cryptoCurrency.validateAddress(address ?? ""); + ref.read(pValidSendToAddress.notifier).state = wallet.cryptoCurrency + .validateAddress(address ?? ""); } } @@ -725,9 +679,9 @@ class _DesktopSendState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); + final amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: coin.fractionDigits); cryptoAmountController.text = ref .read(pAmountFormatter(coin)) .format(amount, withUnitName: false); @@ -823,21 +777,21 @@ class _DesktopSendState extends ConsumerState { if (_price == Decimal.zero) { amount = Decimal.zero.toAmount(fractionDigits: coin.fractionDigits); } else { - amount = baseAmount <= Amount.zero - ? Decimal.zero.toAmount(fractionDigits: coin.fractionDigits) - : (baseAmount.decimal / _price) - .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) - .toAmount(fractionDigits: coin.fractionDigits); + amount = + baseAmount <= Amount.zero + ? Decimal.zero.toAmount(fractionDigits: coin.fractionDigits) + : (baseAmount.decimal / _price) + .toDecimal(scaleOnInfinitePrecision: coin.fractionDigits) + .toAmount(fractionDigits: coin.fractionDigits); } if (_cachedAmountToSend != null && _cachedAmountToSend == amount) { return; } _cachedAmountToSend = amount; - final amountString = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + final amountString = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); _cryptoAmountChangeLock = true; cryptoAmountController.text = amountString; @@ -865,10 +819,9 @@ class _DesktopSendState extends ConsumerState { } Amount _selectedUtxosAmount(Set utxos) => Amount( - rawValue: - utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), - fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, - ); + rawValue: utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), + fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, + ); Future _sendAllTapped(bool showCoinControl) async { final Amount amount; @@ -891,20 +844,20 @@ class _DesktopSendState extends ConsumerState { amount = ref.read(pWalletBalance(walletId)).spendable; } - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); } void _showDesktopCoinControl() async { final amount = ref.read(pSendAmount); await showDialog( context: context, - builder: (context) => DesktopCoinControlUseDialog( - walletId: widget.walletId, - amountToSend: amount, - ), + builder: + (context) => DesktopCoinControlUseDialog( + walletId: widget.walletId, + amountToSend: amount, + ), ); } @@ -1033,7 +986,8 @@ class _DesktopSendState extends ConsumerState { } }); - final showCoinControl = ref.watch( + final showCoinControl = + ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, ), @@ -1044,23 +998,19 @@ class _DesktopSendState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), if (coin is Firo) Text( "Send from", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - if (coin is Firo) - const SizedBox( - height: 10, - ), + if (coin is Firo) const SizedBox(height: 10), if (coin is Firo) DropdownButtonHideUnderline( child: DropdownButton2( @@ -1075,11 +1025,11 @@ class _DesktopSendState extends ConsumerState { "Spark balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalanceTertiary(walletId)) .spendable, @@ -1099,11 +1049,11 @@ class _DesktopSendState extends ConsumerState { "Lelantus balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalanceSecondary(walletId)) .spendable, @@ -1121,11 +1071,11 @@ class _DesktopSendState extends ConsumerState { "Public balance", style: STextStyles.itemSubtitle12(context), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref.watch(pWalletBalance(walletId)).spendable, ), style: STextStyles.itemSubtitle(context), @@ -1157,45 +1107,37 @@ class _DesktopSendState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), ), ), - if (coin is Firo) - const SizedBox( - height: 20, - ), + if (coin is Firo) const SizedBox(height: 20), if (isPaynymSend) Text( "Send to PayNym address", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (isPaynymSend) - const SizedBox( - height: 10, - ), + if (isPaynymSend) const SizedBox(height: 10), if (isPaynymSend) TextField( key: const Key("sendViewPaynymAddressFieldKey"), controller: sendToController, enabled: false, readOnly: true, - style: STextStyles.desktopTextFieldLabel(context).copyWith( - fontSize: 16, - ), + style: STextStyles.desktopTextFieldLabel( + context, + ).copyWith(fontSize: 16), decoration: const InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 18, @@ -1203,19 +1145,17 @@ class _DesktopSendState extends ConsumerState { ), ), ), - if (isPaynymSend) - const SizedBox( - height: 20, - ), + if (isPaynymSend) const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Amount", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), @@ -1229,9 +1169,7 @@ class _DesktopSendState extends ConsumerState { ), ], ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1241,12 +1179,13 @@ class _DesktopSendState extends ConsumerState { key: const Key("amountInputFieldCryptoTextFieldKey"), controller: cryptoAmountController, focusNode: _cryptoFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -1270,9 +1209,10 @@ class _DesktopSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -1281,19 +1221,17 @@ class _DesktopSendState extends ConsumerState { child: Text( ref.watch(pAmountUnit(coin)).unitForCoin(coin), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - if (Prefs.instance.externalCalls) - const SizedBox( - height: 10, - ), + if (Prefs.instance.externalCalls) const SizedBox(height: 10), if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, @@ -1304,18 +1242,16 @@ class _DesktopSendState extends ConsumerState { key: const Key("amountInputFieldFiatTextFieldKey"), controller: baseAmountController, focusNode: _baseFocus, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ - AmountInputFormatter( - decimals: 2, - locale: locale, - ), + AmountInputFormatter(decimals: 2, locale: locale), // // regex to validate a fiat amount with 2 decimal places // TextInputFormatter.withFunction((oldValue, newValue) => // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') @@ -1332,9 +1268,10 @@ class _DesktopSendState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -1342,23 +1279,22 @@ class _DesktopSendState extends ConsumerState { padding: const EdgeInsets.all(12), child: Text( ref.watch( - prefsChangeNotifierProvider - .select((value) => value.currency), + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), ), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), ), ), ), - if (showCoinControl) - const SizedBox( - height: 10, - ), + if (showCoinControl) const SizedBox(height: 10), if (showCoinControl) RoundedContainer( color: Colors.transparent, @@ -1372,31 +1308,28 @@ class _DesktopSendState extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall(context), ), CustomTextButton( - text: ref.watch(desktopUseUTXOs.state).state.isEmpty - ? "Select coins" - : "Selected coins (${ref.watch(desktopUseUTXOs.state).state.length})", + text: + ref.watch(desktopUseUTXOs.state).state.isEmpty + ? "Select coins" + : "Selected coins (${ref.watch(desktopUseUTXOs.state).state.length})", onTap: _showDesktopCoinControl, ), ], ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), if (!isPaynymSend) Text( "Send to", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), - if (!isPaynymSend) - const SizedBox( - height: 10, - ), + if (!isPaynymSend) const SizedBox(height: 10), if (!isPaynymSend) ClipRRect( borderRadius: BorderRadius.circular( @@ -1424,7 +1357,10 @@ class _DesktopSendState extends ConsumerState { final trimmed = newValue; if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { - final parsed = AddressUtils.parsePaymentUri(trimmed, logging: Logging.instance); + final parsed = AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); if (parsed != null) { _applyUri(parsed); } else { @@ -1443,9 +1379,10 @@ class _DesktopSendState extends ConsumerState { }, focusNode: _addressFocusNode, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -1461,76 +1398,80 @@ class _DesktopSendState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _addressToggleFlag ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: pasteAddress, - child: sendToController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + key: const Key( + "sendViewPasteAddressFieldButtonKey", ), + onTap: pasteAddress, + child: + sendToController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (sendToController.text.isEmpty) TextFieldIconButton( key: const Key("sendViewAddressBookButtonKey"), onTap: () async { - final entry = - await showDialog( + final entry = await showDialog< + ContactAddressEntry? + >( context: context, - builder: (context) => DesktopDialog( - maxWidth: 696, - maxHeight: 600, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 696, + maxHeight: 600, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: STextStyles.desktopH3( - context, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Address book", + style: STextStyles.desktopH3( + context, + ), + ), ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: AddressBookAddressChooser( + coin: coin, ), ), - const DesktopDialogCloseButton(), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: coin, - ), - ), - ], - ), - ), + ), ); if (entry != null) { @@ -1552,9 +1493,7 @@ class _DesktopSendState extends ConsumerState { TextFieldIconButton( semanticsLabel: "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key( - "sendViewScanQrButtonKey", - ), + key: const Key("sendViewScanQrButtonKey"), onTap: scanWebcam, child: const QrCodeIcon(), ), @@ -1575,18 +1514,20 @@ class _DesktopSendState extends ConsumerState { } else if (coin is Firo) { if (firoType == FiroType.lelantus) { if (_data != null && _data.contactLabel == _address) { - error = SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: coin.network.isTestNet, - ) - ? "Lelantus to Spark not supported" - : null; + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: coin.network.isTestNet, + ) + ? "Lelantus to Spark not supported" + : null; } else if (ref.watch(pValidSparkSendToAddress)) { error = "Lelantus to Spark not supported"; } else { - error = ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; } } else { if (_data != null && _data.contactLabel == _address) { @@ -1614,17 +1555,15 @@ class _DesktopSendState extends ConsumerState { return Align( alignment: Alignment.topLeft, child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), + padding: const EdgeInsets.only(left: 12.0, top: 4.0), child: Text( error, textAlign: TextAlign.left, style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + color: + Theme.of( + context, + ).extension()!.textError, ), ), ), @@ -1635,9 +1574,7 @@ class _DesktopSendState extends ConsumerState { if (isStellar || (ref.watch(pValidSparkSendToAddress) && firoType != FiroType.lelantus)) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (isStellar || (ref.watch(pValidSparkSendToAddress) && firoType != FiroType.lelantus)) @@ -1659,9 +1596,10 @@ class _DesktopSendState extends ConsumerState { setState(() {}); }, style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -1678,9 +1616,10 @@ class _DesktopSendState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -1688,9 +1627,10 @@ class _DesktopSendState extends ConsumerState { TextFieldIconButton( key: const Key("sendViewPasteMemoButtonKey"), onTap: pasteMemo, - child: memoController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + child: + memoController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), ), ], ), @@ -1699,14 +1639,11 @@ class _DesktopSendState extends ConsumerState { ), ), ), - if (!isPaynymSend) - const SizedBox( - height: 20, - ), + if (!isPaynymSend) const SizedBox(height: 20), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) ConditionalParent( - condition: ref.watch(pWallets).getWallet(walletId) - is ElectrumXInterface && + condition: + ref.watch(pWallets).getWallet(walletId) is ElectrumXInterface && !(((coin is Firo) && (ref.watch(publicPrivateBalanceStateProvider.state).state == FiroType.lelantus || @@ -1714,165 +1651,163 @@ class _DesktopSendState extends ConsumerState { .watch(publicPrivateBalanceStateProvider.state) .state == FiroType.spark))), - builder: (child) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - child, - CustomTextButton( - text: "Edit", - onTap: () async { - feeSelectionResult = await showDialog< - ( - FeeRateType, - String?, - String?, - )?>( - context: context, - builder: (_) => DesktopFeeDialog( - walletId: walletId, - ), - ); - - if (feeSelectionResult != null) { - if (isCustomFee && - feeSelectionResult!.$1 != FeeRateType.custom) { - isCustomFee = false; - } else if (!isCustomFee && - feeSelectionResult!.$1 == FeeRateType.custom) { - isCustomFee = true; - } - } - - setState(() {}); - }, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + child, + CustomTextButton( + text: "Edit", + onTap: () async { + feeSelectionResult = + await showDialog<(FeeRateType, String?, String?)?>( + context: context, + builder: + (_) => DesktopFeeDialog(walletId: walletId), + ); + + if (feeSelectionResult != null) { + if (isCustomFee && + feeSelectionResult!.$1 != FeeRateType.custom) { + isCustomFee = false; + } else if (!isCustomFee && + feeSelectionResult!.$1 == FeeRateType.custom) { + isCustomFee = true; + } + } + + setState(() {}); + }, + ), + ], ), - ], - ), child: Text( "Transaction fee" "${isCustomFee ? "" : " (${coin is Ethereum ? "max" : "estimated"})"}", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldActiveSearchIconRight, ), textAlign: TextAlign.left, ), ), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos) if (!isCustomFee) Padding( padding: const EdgeInsets.all(10), - child: (feeSelectionResult?.$2 == null) - ? FutureBuilder( - future: ref.watch( - pWallets.select( - (value) => value.getWallet(walletId).fees, + child: + (feeSelectionResult?.$2 == null) + ? FutureBuilder( + future: ref.watch( + pWallets.select( + (value) => value.getWallet(walletId).fees, + ), ), - ), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - return DesktopFeeItem( - feeObject: snapshot.data, - feeRateType: FeeRateType.average, - walletId: walletId, - isButton: false, - feeFor: ({ - required Amount amount, - required FeeRateType feeRateType, - required int feeRate, - required CryptoCurrency coin, - }) async { - if (ref - .read(feeSheetSessionCacheProvider) - .average[amount] == - null) { - final wallet = - ref.read(pWallets).getWallet(walletId); - - if (coin is Monero || coin is Wownero) { - final fee = await wallet.estimateFeeFor( - amount, - lib_monero.TransactionPriority.medium.value, - ); - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = fee; - } else if ((coin is Firo) && + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + return DesktopFeeItem( + feeObject: snapshot.data, + feeRateType: FeeRateType.average, + walletId: walletId, + isButton: false, + feeFor: ({ + required Amount amount, + required FeeRateType feeRateType, + required int feeRate, + required CryptoCurrency coin, + }) async { + if (ref + .read(feeSheetSessionCacheProvider) + .average[amount] == + null) { + final wallet = ref + .read(pWallets) + .getWallet(walletId); + + if (coin is Monero || coin is Wownero) { + final fee = await wallet.estimateFeeFor( + amount, + lib_monero + .TransactionPriority + .medium + .value, + ); ref + .read(feeSheetSessionCacheProvider) + .average[amount] = + fee; + } else if ((coin is Firo) && + ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) { + final firoWallet = wallet as FiroWallet; + + if (ref .read( publicPrivateBalanceStateProvider .state, ) - .state != - FiroType.public) { - final firoWallet = wallet as FiroWallet; - - if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.lelantus) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await firoWallet - .estimateFeeForLelantus(amount); - } else if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == - FiroType.spark) { + .state == + FiroType.lelantus) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForLelantus(amount); + } else if (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state == + FiroType.spark) { + ref + .read(feeSheetSessionCacheProvider) + .average[amount] = await firoWallet + .estimateFeeForSpark(amount); + } + } else { ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await firoWallet - .estimateFeeForSpark(amount); + .read(feeSheetSessionCacheProvider) + .average[amount] = await wallet + .estimateFeeFor(amount, feeRate); } - } else { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = - await wallet.estimateFeeFor( - amount, - feeRate, - ); } - } - return ref - .read(feeSheetSessionCacheProvider) - .average[amount]!; - }, - isSelected: true, - ); - } else { - return Row( - children: [ - AnimatedText( - stringsToLoopThrough: stringsToLoopThrough, - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + return ref + .read(feeSheetSessionCacheProvider) + .average[amount]!; + }, + isSelected: true, + ); + } else { + return Row( + children: [ + AnimatedText( + stringsToLoopThrough: stringsToLoopThrough, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + ), ), - ), - ], - ); - } - }, - ) - : (coin is Firo) && + ], + ); + } + }, + ) + : (coin is Firo) && ref .watch( publicPrivateBalanceStateProvider.state, @@ -1880,54 +1815,49 @@ class _DesktopSendState extends ConsumerState { .state == FiroType.lelantus ? Text( - "~${ref.watch(pAmountFormatter(coin)).format( - Amount( - rawValue: BigInt.parse("3794"), - fractionDigits: coin.fractionDigits, - ), - indicatePrecisionLoss: false, - )}", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, - ) - : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - feeSelectionResult?.$2 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( + "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - ), - textAlign: TextAlign.left, + ).extension()!.textFieldActiveText, + ), + textAlign: TextAlign.left, + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + feeSelectionResult?.$2 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, ), - Text( - feeSelectionResult?.$3 ?? "", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ), + textAlign: TextAlign.left, + ), + Text( + feeSelectionResult?.$3 ?? "", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), - ], - ), + ), + ], + ), ), if (isCustomFee) Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, - ), + padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( coin: coin, onSatVByteChanged: (rate) { @@ -1935,9 +1865,7 @@ class _DesktopSendState extends ConsumerState { }, ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), PrimaryButton( buttonHeight: ButtonHeight.l, label: "Preview send", From 47d46461c52c40abae2c6838b294f69e9e43f5ff Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 12 May 2025 14:38:22 -0600 Subject: [PATCH 051/206] allow sending to spark names** --- lib/pages/send_view/send_view.dart | 147 ++++++++++-------- .../buy_spark_name_option_widget.dart | 15 +- .../wallet_view/sub_widgets/desktop_send.dart | 46 +++++- 3 files changed, 138 insertions(+), 70 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index de49b386b..57a78ad08 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -27,6 +27,7 @@ import '../../providers/ui/fee_rate_type_state_provider.dart'; import '../../providers/ui/preview_tx_button_state_provider.dart'; import '../../providers/wallet/public_private_balance_state_provider.dart'; import '../../route_generator.dart'; +import '../../services/spark_names_service.dart'; import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/address_utils.dart'; @@ -172,6 +173,82 @@ class _SendViewState extends ConsumerState { } } + Future _checkSparkNameAndOrSetAddress( + String content, { + bool setController = true, + }) async { + void setContent() { + if (setController) { + sendToController.text = content; + } + _address = content; + } + + // check for spark name + if (coin is Firo) { + final address = await SparkNamesService.getAddressFor( + content, + network: coin.network, + ); + if (address != null) { + // found a spark name + sendToController.text = content; + _address = address; + } else { + setContent(); + } + } else { + setContent(); + } + } + + Future _pasteAddress() async { + final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); + if (data?.text != null && data!.text!.isNotEmpty) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring(0, content.indexOf("\n")).trim(); + } + + try { + final paymentData = AddressUtils.parsePaymentUri( + content, + logging: Logging.instance, + ); + + if (paymentData != null && + paymentData.coin?.uriScheme == coin.uriScheme) { + _applyUri(paymentData); + } else { + if (coin is Epiccash) { + content = AddressUtils().formatAddress(content); + } + + sendToController.text = content; + _address = content; + + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = sendToController.text.isNotEmpty; + }); + } + } catch (e) { + if (coin is Epiccash) { + // strip http:// and https:// if content contains @ + content = AddressUtils().formatAddress(content); + } + + await _checkSparkNameAndOrSetAddress(content); + + // Trigger validation after pasting. + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = sendToController.text.isNotEmpty; + }); + } + } + } + Future _scanQr() async { try { // ref @@ -1295,7 +1372,7 @@ class _SendViewState extends ConsumerState { paste: true, selectAll: false, ), - onChanged: (newValue) { + onChanged: (newValue) async { final trimmed = newValue.trim(); if ((trimmed.length - (_address?.length ?? 0)) @@ -1308,11 +1385,15 @@ class _SendViewState extends ConsumerState { if (parsed != null) { _applyUri(parsed); } else { - _address = newValue; - sendToController.text = newValue; + await _checkSparkNameAndOrSetAddress( + newValue, + ); } } else { - _address = newValue; + await _checkSparkNameAndOrSetAddress( + newValue, + setController: false, + ); } _setValidAddressProviders(_address); @@ -1369,63 +1450,7 @@ class _SendViewState extends ConsumerState { key: const Key( "sendViewPasteAddressFieldButtonKey", ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = - data.text!.trim(); - if (content.contains( - "\n", - )) { - content = content - .substring( - 0, - content.indexOf( - "\n", - ), - ); - } - - if (coin is Epiccash) { - // strip http:// and https:// if content contains @ - content = AddressUtils() - .formatAddress( - content, - ); - } - - final trimmed = - content.trim(); - final parsed = - AddressUtils.parsePaymentUri( - trimmed, - logging: - Logging.instance, - ); - if (parsed != null) { - _applyUri(parsed); - } else { - sendToController.text = - content; - _address = content; - - _setValidAddressProviders( - _address, - ); - - setState(() { - _addressToggleFlag = - sendToController - .text - .isNotEmpty; - }); - } - } - }, + onTap: _pasteAddress, child: sendToController .text diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart index 4ea12ae64..0da2b4cf9 100644 --- a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -50,6 +50,11 @@ class _BuySparkNameWidgetState extends ConsumerState { // name exists return false; } catch (e) { + if (e.toString().contains( + "(method not found): unknown method \"spark.getsparknamedata\"", + )) { + rethrow; + } // name not found return true; } @@ -80,7 +85,15 @@ class _BuySparkNameWidgetState extends ConsumerState { Logging.instance.i("LOOKUP RESULT: $result"); } catch (e, s) { - const message = "Spark name lookup failed"; + final String message; + if (e.toString().contains( + "(method not found): unknown method \"spark.getsparknamedata\"", + )) { + message = e.toString(); + } else { + message = "Spark name lookup failed"; + } + Logging.instance.e(message, error: e, stackTrace: s); if (mounted) { diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 5c5b68c0f..fe65a90f0 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -29,6 +29,7 @@ import '../../../../providers/providers.dart'; import '../../../../providers/ui/fee_rate_type_state_provider.dart'; import '../../../../providers/ui/preview_tx_button_state_provider.dart'; import '../../../../providers/wallet/public_private_balance_state_provider.dart'; +import '../../../../services/spark_names_service.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/address_utils.dart'; import '../../../../utilities/amount/amount.dart'; @@ -698,12 +699,41 @@ class _DesktopSendState extends ConsumerState { } } + Future _checkSparkNameAndOrSetAddress( + String content, { + bool setController = true, + }) async { + void setContent() { + if (setController) { + sendToController.text = content; + } + _address = content; + } + + // check for spark name + if (coin is Firo) { + final address = await SparkNamesService.getAddressFor( + content, + network: coin.network, + ); + if (address != null) { + // found a spark name + sendToController.text = content; + _address = address; + } else { + setContent(); + } + } else { + setContent(); + } + } + Future pasteAddress() async { final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); if (data?.text != null && data!.text!.isNotEmpty) { String content = data.text!.trim(); if (content.contains("\n")) { - content = content.substring(0, content.indexOf("\n")); + content = content.substring(0, content.indexOf("\n")).trim(); } try { @@ -715,7 +745,6 @@ class _DesktopSendState extends ConsumerState { paymentData.coin?.uriScheme == coin.uriScheme) { _applyUri(paymentData); } else { - content = content.split("\n").first.trim(); if (coin is Epiccash) { content = AddressUtils().formatAddress(content); } @@ -735,8 +764,7 @@ class _DesktopSendState extends ConsumerState { content = AddressUtils().formatAddress(content); } - sendToController.text = content; - _address = content; + await _checkSparkNameAndOrSetAddress(content); // Trigger validation after pasting. _setValidAddressProviders(_address); @@ -1353,7 +1381,7 @@ class _DesktopSendState extends ConsumerState { paste: true, selectAll: false, ), - onChanged: (newValue) { + onChanged: (newValue) async { final trimmed = newValue; if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { @@ -1364,11 +1392,13 @@ class _DesktopSendState extends ConsumerState { if (parsed != null) { _applyUri(parsed); } else { - _address = newValue; - sendToController.text = newValue; + await _checkSparkNameAndOrSetAddress(newValue); } } else { - _address = newValue; + await _checkSparkNameAndOrSetAddress( + newValue, + setController: false, + ); } _setValidAddressProviders(_address); From b52830ecf513a6a75920c19ef579afd6b631fd0a Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 12 May 2025 15:04:24 -0600 Subject: [PATCH 052/206] do some look ahead for spark name lookups --- .../spark_interface.dart | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 8ca665487..4768bebb0 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -1264,15 +1264,54 @@ mixin SparkInterface ); final myAddresses = - await mainDB.isar.addresses - .where() - .walletIdEqualTo(walletId) - .filter() - .typeEqualTo(AddressType.spark) - .and() - .subTypeEqualTo(AddressSubType.receiving) - .valueProperty() - .findAll(); + (await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.spark) + .and() + .subTypeEqualTo(AddressSubType.receiving) + .valueProperty() + .findAll()) + .toSet(); + + // some look ahead + // TODO revisit this and clean up (track pre gen'd addresses instead of generating every time) + // arbitrary number of addresses + const lookAheadCount = 100; + final highestStoredDiversifier = + (await getCurrentReceivingSparkAddress())?.derivationIndex; + + final root = await getRootHDNode(); + final String derivationPath; + if (cryptoCurrency.network.isTestNet) { + derivationPath = "$kSparkBaseDerivationPathTestnet$kDefaultSparkIndex"; + } else { + derivationPath = "$kSparkBaseDerivationPath$kDefaultSparkIndex"; + } + final keys = root.derivePath(derivationPath); + + // default to starting at 1 if none found + int diversifier = (highestStoredDiversifier ?? 0) + 1; + + final maxDiversifier = diversifier + lookAheadCount; + + while (diversifier < maxDiversifier) { + // change address check + if (diversifier == kSparkChange) { + diversifier++; + } + final addressString = await LibSpark.getAddress( + privateKey: keys.privateKey.data, + index: kDefaultSparkIndex, + diversifier: diversifier, + isTestNet: cryptoCurrency.network.isTestNet, + ); + + myAddresses.add(addressString); + + diversifier++; + } names.retainWhere( (e) => From 8b7e4e66cc83d632cf57324c0f2702f90309cc3c Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 13 May 2025 10:29:34 -0600 Subject: [PATCH 053/206] spark name ui tweaks --- lib/pages/spark_names/buy_spark_name_view.dart | 2 +- .../sub_widgets/buy_spark_name_option_widget.dart | 1 + .../spark_names/sub_widgets/owned_spark_name_card.dart | 1 + .../wallet_view/sub_widgets/desktop_wallet_features.dart | 6 +++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart index 1ce0513d1..94c868e9d 100644 --- a/lib/pages/spark_names/buy_spark_name_view.dart +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -377,7 +377,7 @@ class _BuySparkNameViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "${isRenewal ? "Register" : "Renew"} for", + "${isRenewal ? "Renew" : "Register"} for", style: Util.isDesktop ? STextStyles.w500_14(context).copyWith( diff --git a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart index 0da2b4cf9..18b6bb6f4 100644 --- a/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart +++ b/lib/pages/spark_names/sub_widgets/buy_spark_name_option_widget.dart @@ -306,6 +306,7 @@ class _NameCard extends ConsumerWidget { ), ), Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ PrimaryButton( label: "Buy name", diff --git a/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart index ea8b89b5d..fc813efb9 100644 --- a/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart +++ b/lib/pages/spark_names/sub_widgets/owned_spark_name_card.dart @@ -106,6 +106,7 @@ class _OwnedSparkNameCardState extends ConsumerState { const SizedBox(width: 12), PrimaryButton( label: "Details", + width: Util.isDesktop ? 90 : null, buttonHeight: Util.isDesktop ? ButtonHeight.xs : ButtonHeight.l, onPressed: _showDetails, ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index bd91540f8..814af0cd2 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -406,6 +406,9 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (showExchange && AppConfig.hasFeature(AppFeature.buy)) (WalletFeature.buy, Assets.svg.swap, _onBuyPressed), + if (wallet is SparkInterface) + (WalletFeature.sparkNames, Assets.svg.robotHead, _onSparkNamesPressed), + if (showCoinControl) ( WalletFeature.coinControl, @@ -444,9 +447,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (wallet is NamecoinWallet) (WalletFeature.namecoinName, Assets.svg.robotHead, _onNamesPressed), - - if (wallet is SparkInterface) - (WalletFeature.sparkNames, Assets.svg.robotHead, _onSparkNamesPressed), ]; } From f873758c39911758254bc87aae608bd6082b0120 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 13 May 2025 11:47:43 -0600 Subject: [PATCH 054/206] fix issues from mergefest --- lib/pages/exchange_view/confirm_change_now_send.dart | 1 - lib/pages/send_view/confirm_transaction_view.dart | 2 +- .../confirm_spark_name_transaction_view.dart | 4 ++-- .../wallet/intermediate/lib_monero_wallet.dart | 12 ++++++++++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index ce1a0cf4b..d28bc8277 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -19,7 +19,6 @@ import '../../models/isar/models/isar_models.dart'; import '../../models/trade_wallet_lookup.dart'; import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../themes/stack_colors.dart'; diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index d282d7004..1e0242cbc 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -21,7 +21,6 @@ import '../../models/isar/models/transaction_note.dart'; import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../providers/wallet/public_private_balance_state_provider.dart'; import '../../route_generator.dart'; @@ -33,6 +32,7 @@ import '../../utilities/constants.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/coins/epiccash.dart'; +import '../../wallets/crypto_currency/coins/ethereum.dart'; import '../../wallets/crypto_currency/intermediate/nano_currency.dart'; import '../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; diff --git a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart index 9afc5694f..011532708 100644 --- a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart +++ b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart @@ -693,8 +693,8 @@ class _ConfirmSparkNameTransactionViewState ref .read(priceAnd24hChangeNotifierProvider) .getPrice(coin) - .item1; - if (price > Decimal.zero) { + ?.value; + if (price != null && price > Decimal.zero) { fiatAmount = (amountWithoutChange.decimal * price) .toAmount(fractionDigits: 2) .fiatString( diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index 8e9e94f9b..b81a10d97 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -520,7 +520,11 @@ abstract class LibMoneroWallet trusted: node.trusted ?? false, useSSL: node.useSSL, socksProxyAddress: - node.forceNoTor ? null : proxy == null ? null : "${proxy.host.address}:${proxy.port}", + node.forceNoTor + ? null + : proxy == null + ? null + : "${proxy.host.address}:${proxy.port}", ); }); } else { @@ -531,7 +535,11 @@ abstract class LibMoneroWallet trusted: node.trusted ?? false, useSSL: node.useSSL, socksProxyAddress: - node.forceNoTor ? null : proxy == null ? null : "${proxy.host.address}:${proxy.port}", + node.forceNoTor + ? null + : proxy == null + ? null + : "${proxy.host.address}:${proxy.port}", ); } libMoneroWallet?.startSyncing(); From a1467a09e2a01d0561ee6b375ae396641d2448cd Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 13 May 2025 15:57:51 -0600 Subject: [PATCH 055/206] update flutter_libsparkmobile --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index abb45eb85..16e439300 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -864,8 +864,8 @@ packages: dependency: "direct main" description: path: "." - ref: "66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b" - resolved-ref: "66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b" + ref: f5fd2238fca4ffe82f7e14646a613a04d2c243d6 + resolved-ref: f5fd2238fca4ffe82f7e14646a613a04d2c243d6 url: "https://github.com/cypherstack/flutter_libsparkmobile.git" source: git version: "0.1.0" diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 3019844ad..d086b0f94 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -38,7 +38,7 @@ dependencies: flutter_libsparkmobile: git: url: https://github.com/cypherstack/flutter_libsparkmobile.git - ref: 66dab036ed7332fd4b0609e5eb59b0c1ac3eb98b + ref: f5fd2238fca4ffe82f7e14646a613a04d2c243d6 # cs_monero compat (unpublished) compat: From d090eaea7128d5616b0470ce07d3d1b092c9a78c Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 14 May 2025 08:26:22 -0600 Subject: [PATCH 056/206] disable spark name transactions before they are enabled on chain --- .../wallet/wallet_mixin_interfaces/spark_interface.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 4768bebb0..c22429d10 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -2165,6 +2165,14 @@ mixin SparkInterface required int years, required String additionalInfo, }) async { + // TODO remove after block 1104500 + if (cryptoCurrency.network == CryptoCurrencyNetwork.main) { + final height = await fetchChainHeight(); + if (height < 1104500) { + throw Exception("Spark names not enabled on main net yet"); + } + } + if (years < 1 || years > kMaxNameRegistrationLengthYears) { throw Exception("Invalid spark name registration period years: $years"); } From 5db3c639c6d69b589b5824d6b8971211fd893e8a Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 14 May 2025 10:16:01 -0600 Subject: [PATCH 057/206] add mounted check --- lib/pages/send_view/token_send_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 2cb873951..7eaaa43f4 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -317,7 +317,7 @@ class _TokenSendViewState extends ConsumerState { _cryptoAmountChangedFeeUpdateTimer?.cancel(); _cryptoAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () { - if (coin is! Epiccash && !_baseFocus.hasFocus) { + if (mounted && coin is! Epiccash && !_baseFocus.hasFocus) { setState(() { _calculateFeesFuture = calculateFees(); }); @@ -329,7 +329,7 @@ class _TokenSendViewState extends ConsumerState { void _baseAmountChanged() { _baseAmountChangedFeeUpdateTimer?.cancel(); _baseAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () { - if (coin is! Epiccash && !_cryptoFocus.hasFocus) { + if (mounted && coin is! Epiccash && !_cryptoFocus.hasFocus) { setState(() { _calculateFeesFuture = calculateFees(); }); From ace8a132d97306cd9a49e313caec2726a409de68 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 14 May 2025 10:57:47 -0600 Subject: [PATCH 058/206] transaction broadcast error logging --- .../send_view/confirm_transaction_view.dart | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 1e0242cbc..57a6549ca 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -29,6 +29,7 @@ import '../../themes/theme_providers.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/amount/amount_formatter.dart'; import '../../utilities/constants.dart'; +import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/coins/epiccash.dart'; @@ -227,8 +228,8 @@ class _ConfirmTransactionViewState return; } } catch (e, s) { - //todo: comeback to this - debugPrint("$e\n$s"); + const message = "Broadcast transaction failed"; + Logging.instance.e(message, error: e, stackTrace: s); // pop sending dialog if (context.mounted) { Navigator.of(context).pop(); @@ -247,10 +248,7 @@ class _ConfirmTransactionViewState mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Broadcast transaction failed", - style: STextStyles.desktopH3(context), - ), + Text(message, style: STextStyles.desktopH3(context)), const SizedBox(height: 24), Flexible( child: SingleChildScrollView( @@ -279,7 +277,7 @@ class _ConfirmTransactionViewState ); } else { return StackDialog( - title: "Broadcast transaction failed", + title: message, message: e.toString(), rightButton: TextButton( style: Theme.of(context) @@ -1266,9 +1264,10 @@ class _ConfirmTransactionViewState unawaited( showFloatingFlushBar( type: FlushBarType.warning, - message: Util.isDesktop - ? "Invalid passphrase" - : "Invalid PIN", + message: + Util.isDesktop + ? "Invalid passphrase" + : "Invalid PIN", context: context, ), ); From 37435905f56d04952c6daeb3ad59f4b5d7cfeabc Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 14 May 2025 13:46:37 -0600 Subject: [PATCH 059/206] get more info from eth rpc errors on send --- lib/wallets/wallet/impl/ethereum_wallet.dart | 27 ++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index 1bb5ec7c7..35e0bc174 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -5,6 +5,7 @@ import 'package:decimal/decimal.dart'; import 'package:ethereum_addresses/ethereum_addresses.dart'; import 'package:http/http.dart'; import 'package:isar/isar.dart'; +import 'package:web3dart/json_rpc.dart' show RPCError; import 'package:web3dart/web3dart.dart' as web3; import '../../../dto/ethereum/eth_tx_dto.dart'; @@ -556,18 +557,24 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { await _initCredentials(); } - final txid = await client.sendTransaction( - _credentials!, - txData.web3dartTransaction!, - chainId: txData.chainId!.toInt(), - ); + try { + final txid = await client.sendTransaction( + _credentials!, + txData.web3dartTransaction!, + chainId: txData.chainId!.toInt(), + ); - final data = (prepareTempTx ?? _prepareTempTx)( - txData.copyWith(txid: txid, txHash: txid), - (await getCurrentReceivingAddress())!.value, - ); + final data = (prepareTempTx ?? _prepareTempTx)( + txData.copyWith(txid: txid, txHash: txid), + (await getCurrentReceivingAddress())!.value, + ); - return await updateSentCachedTxData(txData: data); + return await updateSentCachedTxData(txData: data); + } on RPCError catch (e) { + final message = + "${e.toString()}${e.data == null ? "" : e.data.toString()}"; + throw Exception(message); + } } @override From 90486f6839c68aa1ddff59b68b3ca5c2f0f74c62 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 14 May 2025 16:12:03 -0600 Subject: [PATCH 060/206] initial duress pin integration --- lib/main.dart | 29 +- .../new/steps/frost_create_step_5.dart | 55 +- .../reshare/frost_reshare_step_5.dart | 114 ++- .../restore/restore_frost_ms_wallet_view.dart | 329 ++++---- ...w_wallet_recovery_phrase_warning_view.dart | 714 +++++++++--------- .../restore_view_only_wallet_view.dart | 197 +++-- .../restore_wallet_view.dart | 560 +++++++------- .../verify_recovery_phrase_view.dart | 334 ++++---- lib/pages/pinpad_views/create_pin_view.dart | 123 ++- lib/pages/pinpad_views/lock_screen_view.dart | 380 ++++++---- lib/pages/pinpad_views/pinpad_dialog.dart | 44 +- .../change_pin_view/change_pin_view.dart | 119 +-- .../create_duress_pin_view.dart | 257 +++++++ .../security_views/security_view.dart | 328 +++++++- .../wallet_settings_view.dart | 303 ++++---- .../wallet_settings_wallet_settings_view.dart | 251 +++--- lib/providers/global/duress_provider.dart | 4 + lib/providers/providers.dart | 1 + lib/route_generator.dart | 8 + lib/services/wallets.dart | 194 ++--- lib/utilities/prefs.dart | 457 ++++++----- lib/wallets/isar/models/wallet_info.dart | 107 ++- .../providers/all_wallets_info_provider.dart | 48 +- .../draggable_switch_button.dart | 104 ++- 24 files changed, 2899 insertions(+), 2161 deletions(-) create mode 100644 lib/pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart create mode 100644 lib/providers/global/duress_provider.dart diff --git a/lib/main.dart b/lib/main.dart index ba3583668..c521236fb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -50,7 +50,6 @@ import 'pages/pinpad_views/create_pin_view.dart'; import 'pages/pinpad_views/lock_screen_view.dart'; import 'pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart'; import 'pages_desktop_specific/password/desktop_login_view.dart'; -import 'providers/db/main_db_provider.dart'; import 'providers/desktop/storage_crypto_handler_provider.dart'; import 'providers/global/auto_swb_service_provider.dart'; import 'providers/global/base_currencies_provider.dart'; @@ -357,7 +356,7 @@ class _MaterialAppWithThemeState extends ConsumerState } } - Future load() async { + Future load(bool loadWallets) async { try { if (didLoad) { return; @@ -387,12 +386,15 @@ class _MaterialAppWithThemeState extends ConsumerState prefs: ref.read(prefsChangeNotifierProvider), ); ref.read(priceAnd24hChangeNotifierProvider).start(true); - await ref - .read(pWallets) - .load( - ref.read(prefsChangeNotifierProvider), - ref.read(mainDBProvider), - ); + if (loadWallets) { + await ref + .read(pWallets) + .load( + ref.read(prefsChangeNotifierProvider), + ref.read(mainDBProvider), + false, + ); + } loadingCompleter.complete(); // TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet // unawaited(_nodeService.updateCommunityNodes()); @@ -445,6 +447,13 @@ class _MaterialAppWithThemeState extends ConsumerState @override void initState() { + if (Util.isDesktop) { + // set to false for desktop + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(pDuress.notifier).state = false; + }); + } + String themeId; if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) { final brightness = WidgetsBinding.instance.window.platformBrightness; @@ -781,7 +790,7 @@ class _MaterialAppWithThemeState extends ConsumerState return DesktopLoginView( startupWalletId: startupWalletId, - load: load, + load: () => load(true), ); } else { return const IntroView(); @@ -792,7 +801,7 @@ class _MaterialAppWithThemeState extends ConsumerState }, ) : FutureBuilder( - future: load(), + future: load(false), builder: ( BuildContext context, AsyncSnapshot snapshot, diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart index 3c59c7524..9d835ea4e 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart @@ -8,12 +8,9 @@ import '../../../../../app_config.dart'; import '../../../../../frost_route_generator.dart'; import '../../../../../notifications/show_flush_bar.dart'; import '../../../../../pages_desktop_specific/desktop_home_view.dart'; -import '../../../../../providers/db/main_db_provider.dart'; import '../../../../../providers/frost_wallet/frost_wallet_providers.dart'; -import '../../../../../providers/global/node_service_provider.dart'; -import '../../../../../providers/global/prefs_provider.dart'; import '../../../../../providers/global/secure_store_provider.dart'; -import '../../../../../providers/global/wallets_provider.dart'; +import '../../../../../providers/providers.dart'; import '../../../../../services/frost.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../utilities/assets.dart'; @@ -43,7 +40,8 @@ class FrostCreateStep5 extends ConsumerStatefulWidget { } class _FrostCreateStep5State extends ConsumerState { - static const _warning = "These are your private keys. Please back them up, " + static const _warning = + "These are your private keys. Please back them up, " "keep them safe and never share it with anyone. Your private keys are the" " only way you can access your funds if you forget PIN, lose your phone, " "etc. ${AppConfig.prefix} does not keep nor is able to restore your private keys" @@ -79,9 +77,10 @@ class _FrostCreateStep5State extends ConsumerState { child: Text( _warning, style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of( + context, + ).extension()!.warningForeground, ), ), ), @@ -89,25 +88,19 @@ class _FrostCreateStep5State extends ConsumerState { DetailItem( title: "Multisig Config", detail: multisigConfig, - button: Util.isDesktop - ? IconCopyButton( - data: multisigConfig, - ) - : SimpleCopyButton( - data: multisigConfig, - ), + button: + Util.isDesktop + ? IconCopyButton(data: multisigConfig) + : SimpleCopyButton(data: multisigConfig), ), const SizedBox(height: 12), DetailItem( title: "Keys", detail: serializedKeys, - button: Util.isDesktop - ? IconCopyButton( - data: serializedKeys, - ) - : SimpleCopyButton( - data: serializedKeys, - ), + button: + Util.isDesktop + ? IconCopyButton(data: serializedKeys) + : SimpleCopyButton(data: serializedKeys), ), if (!Util.isDesktop) const Spacer(), const SizedBox(height: 12), @@ -133,10 +126,7 @@ class _FrostCreateStep5State extends ConsumerState { useSafeArea: true, builder: (ctx) { return const Center( - child: LoadingIndicator( - width: 50, - height: 50, - ), + child: LoadingIndicator(width: 50, height: 50), ); }, ), @@ -177,6 +167,13 @@ class _FrostCreateStep5State extends ConsumerState { isar: ref.read(mainDBProvider).isar, ); + if (ref.read(pDuress)) { + await wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } + ref.read(pWallets).addWallet(wallet); // pop progress dialog @@ -191,9 +188,7 @@ class _FrostCreateStep5State extends ConsumerState { if (Util.isDesktop) { nav.popUntil( - ModalRoute.withName( - DesktopHomeView.routeName, - ), + ModalRoute.withName(DesktopHomeView.routeName), ); } else { unawaited( @@ -219,7 +214,7 @@ class _FrostCreateStep5State extends ConsumerState { ); } } catch (e, s) { - Logging.instance.f("$e\n$s", error: e, stackTrace: s,); + Logging.instance.f("$e\n$s", error: e, stackTrace: s); // pop progress dialog if (context.mounted && !progressPopped) { diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_5.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_5.dart index 83fa55944..356edef59 100644 --- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_5.dart +++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_5.dart @@ -4,12 +4,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../frost_route_generator.dart'; import '../../../../pages_desktop_specific/desktop_home_view.dart'; import '../../../../pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart'; -import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/frost_wallet/frost_wallet_providers.dart'; -import '../../../../providers/global/node_service_provider.dart'; -import '../../../../providers/global/prefs_provider.dart'; import '../../../../providers/global/secure_store_provider.dart'; -import '../../../../providers/global/wallets_provider.dart'; +import '../../../../providers/providers.dart'; import '../../../../utilities/logger.dart'; import '../../../../utilities/show_loading.dart'; import '../../../../utilities/text_styles.dart'; @@ -68,12 +65,20 @@ class _FrostReshareStep5State extends ConsumerState { isar: ref.read(mainDBProvider).isar, ); + if (ref.read(pDuress)) { + await wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } + ref.read(pWallets).addWallet(wallet); } else { - wallet = ref - .read(pWallets) - .getWallet(ref.read(pFrostScaffoldArgs)!.walletId!) - as BitcoinFrostWallet; + wallet = + ref + .read(pWallets) + .getWallet(ref.read(pFrostScaffoldArgs)!.walletId!) + as BitcoinFrostWallet; } if (mounted) { @@ -96,22 +101,19 @@ class _FrostReshareStep5State extends ConsumerState { if (mounted) { ref.read(pFrostResharingData).reset(); ref.read(pFrostScaffoldCanPopDesktop.notifier).state = true; - ref.read(pFrostScaffoldArgs)?.parentNav.popUntil( - ModalRoute.withName( - _popUntilPath, - ), - ); + ref + .read(pFrostScaffoldArgs) + ?.parentNav + .popUntil(ModalRoute.withName(_popUntilPath)); } } } catch (e, s) { - Logging.instance.f("$e\n$s", error: e, stackTrace: s,); + Logging.instance.f("$e\n$s", error: e, stackTrace: s); if (mounted) { await showDialog( context: context, - builder: (_) => FrostErrorDialog( - title: "Error", - message: e.toString(), - ), + builder: + (_) => FrostErrorDialog(title: "Error", message: e.toString()), ); } } finally { @@ -119,11 +121,12 @@ class _FrostReshareStep5State extends ConsumerState { } } - String get _popUntilPath => isNew - ? Util.isDesktop - ? DesktopHomeView.routeName - : HomeView.routeName - : Util.isDesktop + String get _popUntilPath => + isNew + ? Util.isDesktop + ? DesktopHomeView.routeName + : HomeView.routeName + : Util.isDesktop ? DesktopWalletView.routeName : WalletView.routeName; @@ -134,7 +137,8 @@ class _FrostReshareStep5State extends ConsumerState { ref.read(pFrostResharingData).newWalletData!.serializedKeys; reshareId = ref.read(pFrostResharingData).newWalletData!.resharedId; - isNew = ref.read(pFrostResharingData).incompleteWallet != null && + isNew = + ref.read(pFrostResharingData).incompleteWallet != null && ref.read(pFrostResharingData).incompleteWallet!.walletId == ref.read(pFrostScaffoldArgs)!.walletId!; @@ -151,66 +155,42 @@ class _FrostReshareStep5State extends ConsumerState { "Ensure your reshare ID matches that of each other participant", style: STextStyles.pageTitleH2(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), DetailItem( title: "ID", detail: reshareId, - button: Util.isDesktop - ? IconCopyButton( - data: reshareId, - ) - : SimpleCopyButton( - data: reshareId, - ), - ), - const SizedBox( - height: 12, - ), - const SizedBox( - height: 12, + button: + Util.isDesktop + ? IconCopyButton(data: reshareId) + : SimpleCopyButton(data: reshareId), ), + const SizedBox(height: 12), + const SizedBox(height: 12), Text( "Back up your keys and config", style: STextStyles.pageTitleH2(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), DetailItem( title: "Config", detail: config, - button: Util.isDesktop - ? IconCopyButton( - data: config, - ) - : SimpleCopyButton( - data: config, - ), - ), - const SizedBox( - height: 12, + button: + Util.isDesktop + ? IconCopyButton(data: config) + : SimpleCopyButton(data: config), ), + const SizedBox(height: 12), DetailItem( title: "Keys", detail: serializedKeys, - button: Util.isDesktop - ? IconCopyButton( - data: serializedKeys, - ) - : SimpleCopyButton( - data: serializedKeys, - ), + button: + Util.isDesktop + ? IconCopyButton(data: serializedKeys) + : SimpleCopyButton(data: serializedKeys), ), if (!Util.isDesktop) const Spacer(), - const SizedBox( - height: 12, - ), - PrimaryButton( - label: "Confirm", - onPressed: _onPressed, - ), + const SizedBox(height: 12), + PrimaryButton(label: "Confirm", onPressed: _onPressed), ], ), ); diff --git a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart index 88f7c3b26..64deee9be 100644 --- a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart @@ -9,11 +9,8 @@ import 'package:frostdart/frostdart.dart' as frost; import '../../../../notifications/show_flush_bar.dart'; import '../../../../pages_desktop_specific/desktop_home_view.dart'; -import '../../../../providers/db/main_db_provider.dart'; -import '../../../../providers/global/node_service_provider.dart'; -import '../../../../providers/global/prefs_provider.dart'; import '../../../../providers/global/secure_store_provider.dart'; -import '../../../../providers/global/wallets_provider.dart'; +import '../../../../providers/providers.dart'; import '../../../../services/frost.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; @@ -95,9 +92,7 @@ class _RestoreFrostMsWalletViewState knownSalts: [], participants: participants, myName: myName, - threshold: frost.multisigThreshold( - multisigConfig: config, - ), + threshold: frost.multisigThreshold(multisigConfig: config), ); await ref.read(mainDBProvider).isar.writeTxn(() async { @@ -110,9 +105,14 @@ class _RestoreFrostMsWalletViewState isRescan: false, ); - await info.setMnemonicVerified( - isar: ref.read(mainDBProvider).isar, - ); + await info.setMnemonicVerified(isar: ref.read(mainDBProvider).isar); + + if (ref.read(pDuress)) { + await wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } return wallet; } @@ -147,17 +147,14 @@ class _RestoreFrostMsWalletViewState if (mounted) { if (Util.isDesktop) { - Navigator.of(context).popUntil( - ModalRoute.withName( - DesktopHomeView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { unawaited( - Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, - ), + Navigator.of( + context, + ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false), ); } @@ -171,20 +168,17 @@ class _RestoreFrostMsWalletViewState ); } } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); + Logging.instance.e("", error: e, stackTrace: s); if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Failed to restore", - message: e.toString(), - desktopPopRootNavigator: Util.isDesktop, - ), + builder: + (_) => StackOkDialog( + title: "Failed to restore", + message: e.toString(), + desktopPopRootNavigator: Util.isDesktop, + ), ); } } finally { @@ -215,9 +209,7 @@ class _RestoreFrostMsWalletViewState if (Platform.isAndroid || Platform.isIOS) { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); + await Future.delayed(const Duration(milliseconds: 75)); } final qrResult = await BarcodeScanner.scan(); @@ -235,9 +227,7 @@ class _RestoreFrostMsWalletViewState ); if (qrResult == null) { - Logging.instance.d( - "Qr scanning cancelled", - ); + Logging.instance.d("Qr scanning cancelled"); } else { // TODO [prio=low]: Validate QR code data. configFieldController.text = qrResult; @@ -260,67 +250,64 @@ class _RestoreFrostMsWalletViewState Widget build(BuildContext context) { return ConditionalParent( condition: Util.isDesktop, - builder: (child) => DesktopScaffold( - background: Theme.of(context).extension()!.background, - appBar: const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - // TODO: [prio=high] get rid of placeholder text?? - trailing: FrostMascot( - title: 'Lorem ipsum', - body: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ', + builder: + (child) => DesktopScaffold( + background: Theme.of(context).extension()!.background, + appBar: const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + // TODO: [prio=high] get rid of placeholder text?? + trailing: FrostMascot( + title: 'Lorem ipsum', + body: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ', + ), + ), + body: SizedBox(width: 480, child: child), ), - ), - body: SizedBox( - width: 480, - child: child, - ), - ), child: ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Restore FROST multisig wallet", - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(16), - child: child, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Restore FROST multisig wallet", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), ), - ), - ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -350,51 +337,53 @@ class _RestoreFrostMsWalletViewState right: 5, ), suffixIcon: Padding( - padding: _configEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _configEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ !_configEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frConfigClearButtonKey"), - onTap: () { - configFieldController.text = ""; - - setState(() { - _configEmpty = true; - }); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Config Field.", + key: const Key("frConfigClearButtonKey"), + onTap: () { + configFieldController.text = ""; + + setState(() { + _configEmpty = true; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Config Field Input.", - key: const Key("frConfigPasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - configFieldController.text = - data.text!.trim(); - } - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - }, - child: _configEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + semanticsLabel: + "Paste Button. Pastes From Clipboard To Config Field Input.", + key: const Key("frConfigPasteButtonKey"), + onTap: () async { + final ClipboardData? data = + await Clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + configFieldController.text = + data.text!.trim(); + } + + setState(() { + _configEmpty = + configFieldController.text.isEmpty; + }); + }, + child: + _configEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_configEmpty) TextFieldIconButton( semanticsLabel: @@ -410,9 +399,7 @@ class _RestoreFrostMsWalletViewState ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -442,51 +429,53 @@ class _RestoreFrostMsWalletViewState right: 5, ), suffixIcon: Padding( - padding: _keysEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _keysEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ !_keysEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Keys Field.", - key: const Key("frMyNameClearButtonKey"), - onTap: () { - keysFieldController.text = ""; - - setState(() { - _keysEmpty = true; - }); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Keys Field.", + key: const Key("frMyNameClearButtonKey"), + onTap: () { + keysFieldController.text = ""; + + setState(() { + _keysEmpty = true; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Keys Field.", - key: const Key("frKeysPasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - keysFieldController.text = - data.text!.trim(); - } - - setState(() { - _keysEmpty = - keysFieldController.text.isEmpty; - }); - }, - child: _keysEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + semanticsLabel: + "Paste Button. Pastes From Clipboard To Keys Field.", + key: const Key("frKeysPasteButtonKey"), + onTap: () async { + final ClipboardData? data = + await Clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + keysFieldController.text = + data.text!.trim(); + } + + setState(() { + _keysEmpty = + keysFieldController.text.isEmpty; + }); + }, + child: + _keysEmpty + ? const ClipboardIcon() + : const XIcon(), + ), ], ), ), @@ -494,13 +483,9 @@ class _RestoreFrostMsWalletViewState ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (!Util.isDesktop) const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), PrimaryButton( label: "Restore", enabled: !_keysEmpty && !_configEmpty, diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index 7d93d038a..a35c4563a 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -19,7 +19,6 @@ import 'package:tuple/tuple.dart'; import '../../../app_config.dart'; import '../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/secure_store_provider.dart'; import '../../../providers/providers.dart'; import '../../../services/transaction_notification_tracker.dart'; @@ -81,11 +80,12 @@ class _NewWalletRecoveryPhraseWarningViewState if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Create Wallet Error", - message: ex?.toString() ?? "Unknown error", - maxWidth: 600, - ), + builder: + (_) => StackOkDialog( + title: "Create Wallet Error", + message: ex?.toString() ?? "Unknown error", + maxWidth: 600, + ), ); } return; @@ -95,10 +95,7 @@ class _NewWalletRecoveryPhraseWarningViewState unawaited( nav.pushNamed( NewWalletRecoveryPhraseView.routeName, - arguments: Tuple2( - result.$1, - result.$2, - ), + arguments: Tuple2(result.$1, result.$2), ), ); } @@ -107,12 +104,12 @@ class _NewWalletRecoveryPhraseWarningViewState Future<(Wallet, List)> _initNewFuture() async { try { - String? otherDataJsonString; + Map? otherDataJson; if (widget.coin is Tezos) { - otherDataJsonString = jsonEncode({ + otherDataJson = { WalletInfoKeys.tezosDerivationPath: Tezos.standardDerivationPath.value, - }); + }; // }//todo: probably not needed (broken anyways) // else if (widget.coin is Epiccash) { // final int secondsSinceEpoch = @@ -145,42 +142,32 @@ class _NewWalletRecoveryPhraseWarningViewState // }, // ); } else if (widget.coin is Firo) { - otherDataJsonString = jsonEncode( - { - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - }, - ); + otherDataJson = {WalletInfoKeys.lelantusCoinIsarRescanRequired: false}; + } + + if (ref.read(pDuress)) { + otherDataJson ??= {}; + otherDataJson[WalletInfoKeys.duressMarkedVisibleWalletKey] = true; } final info = WalletInfo.createNew( coin: widget.coin, name: widget.walletName, - otherDataJsonString: otherDataJsonString, + otherDataJsonString: jsonEncode(otherDataJson), ); var node = ref - .read( - nodeServiceChangeNotifierProvider, - ) - .getPrimaryNodeFor( - currency: coin, - ); + .read(nodeServiceChangeNotifierProvider) + .getPrimaryNodeFor(currency: coin); if (node == null) { node = coin.defaultNode; await ref - .read( - nodeServiceChangeNotifierProvider, - ) - .setPrimaryNodeFor( - coin: coin, - node: node, - ); + .read(nodeServiceChangeNotifierProvider) + .setPrimaryNodeFor(coin: coin, node: node); } - final txTracker = TransactionNotificationTracker( - walletId: info.walletId, - ); + final txTracker = TransactionNotificationTracker(walletId: info.walletId); String? mnemonicPassphrase; String? mnemonic; @@ -195,22 +182,14 @@ class _NewWalletRecoveryPhraseWarningViewState // currently a special case due to the // xmr/wow libraries handling their // own mnemonic generation - wordCount = ref.read(pNewWalletOptions)?.mnemonicWordsCount ?? + wordCount = + ref.read(pNewWalletOptions)?.mnemonicWordsCount ?? info.coin.defaultSeedPhraseLength; } else if (wordCount > 0) { - if (ref - .read( - pNewWalletOptions.state, - ) - .state != - null) { + if (ref.read(pNewWalletOptions.state).state != null) { if (coin.hasMnemonicPassphraseSupport) { - mnemonicPassphrase = ref - .read( - pNewWalletOptions.state, - ) - .state! - .mnemonicPassphrase; + mnemonicPassphrase = + ref.read(pNewWalletOptions.state).state!.mnemonicPassphrase; } else { // this may not be epiccash specific? if (coin is Epiccash) { @@ -218,39 +197,27 @@ class _NewWalletRecoveryPhraseWarningViewState } } - wordCount = ref - .read( - pNewWalletOptions.state, - ) - .state! - .mnemonicWordsCount; + wordCount = + ref.read(pNewWalletOptions.state).state!.mnemonicWordsCount; } else { mnemonicPassphrase = ""; } if (wordCount < 12 || 24 < wordCount || wordCount % 3 != 0) { - throw Exception( - "Invalid word count", - ); + throw Exception("Invalid word count"); } final strength = (wordCount ~/ 3) * 32; - mnemonic = bip39.generateMnemonic( - strength: strength, - ); + mnemonic = bip39.generateMnemonic(strength: strength); } final wallet = await Wallet.create( walletInfo: info, mainDB: ref.read(mainDBProvider), secureStorageInterface: ref.read(secureStoreProvider), - nodeService: ref.read( - nodeServiceChangeNotifierProvider, - ), - prefs: ref.read( - prefsChangeNotifierProvider, - ), + nodeService: ref.read(nodeServiceChangeNotifierProvider), + prefs: ref.read(prefsChangeNotifierProvider), mnemonicPassphrase: mnemonicPassphrase, mnemonic: mnemonic, privateKey: privateKey, @@ -263,18 +230,14 @@ class _NewWalletRecoveryPhraseWarningViewState } // set checkbox back to unchecked to annoy users to agree again :P - ref - .read( - checkBoxStateProvider.state, - ) - .state = false; + ref.read(checkBoxStateProvider.state).state = false; final fetchedMnemonic = await (wallet as MnemonicInterface).getMnemonicAsWords(); return (wallet, fetchedMnemonic); } catch (e, s) { - Logging.instance.f("$e\n$s", error: e, stackTrace: s,); + Logging.instance.f("$e\n$s", error: e, stackTrace: s); rethrow; } } @@ -297,302 +260,309 @@ class _NewWalletRecoveryPhraseWarningViewState return MasterScaffold( isDesktop: isDesktop, - appBar: isDesktop - ? const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ) - : AppBar( - leading: const AppBarBackButton(), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AppBarIconButton( - semanticsLabel: - "Question Button. Opens A Dialog For Recovery Phrase Explanation.", - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .accentColorDark, + appBar: + isDesktop + ? const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ) + : AppBar( + leading: const AppBarBackButton(), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AppBarIconButton( + semanticsLabel: + "Question Button. Opens A Dialog For Recovery Phrase Explanation.", + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + onPressed: () async { + await showDialog( + context: context, + builder: + (context) => + const RecoveryPhraseExplanationDialog(), + ); + }, ), - onPressed: () async { - await showDialog( - context: context, - builder: (context) => - const RecoveryPhraseExplanationDialog(), - ); - }, ), - ), - ], - ), + ], + ), body: SingleChildScrollView( child: ConstrainedBox( - constraints: - BoxConstraints(maxWidth: isDesktop ? 480 : double.infinity), + constraints: BoxConstraints( + maxWidth: isDesktop ? 480 : double.infinity, + ), child: IntrinsicHeight( child: Padding( padding: const EdgeInsets.all(16), child: Center( child: Column( - crossAxisAlignment: isDesktop - ? CrossAxisAlignment.center - : CrossAxisAlignment.stretch, + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.center + : CrossAxisAlignment.stretch, children: [ /*if (isDesktop) const Spacer( flex: 10, ),*/ - if (!isDesktop) - const SizedBox( - height: 4, - ), + if (!isDesktop) const SizedBox(height: 4), if (!isDesktop) Text( walletName, textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - if (!isDesktop) - const SizedBox( - height: 4, + style: STextStyles.label( + context, + ).copyWith(fontSize: 12), ), + if (!isDesktop) const SizedBox(height: 4), Text( "Recovery Phrase", textAlign: TextAlign.center, - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 32 : 16, + style: + isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), ), + SizedBox(height: isDesktop ? 32 : 16), RoundedWhiteContainer( padding: const EdgeInsets.all(32), width: isDesktop ? 480 : null, - child: isDesktop - ? Text( - "On the next screen you will see " - "$seedCount " - "words that make up your recovery phrase.\n\nPlease " - "write it down. Keep it safe and never share it with " - "anyone. Your recovery phrase is the only way you can" - " access your funds if you forget your PIN, lose your" - " phone, etc.\n\n${AppConfig.appName} does not keep nor is " - "able to restore your recover phrase. Only you have " - "access to your wallet.", - style: isDesktop - ? STextStyles.desktopTextMediumRegular( + child: + isDesktop + ? Text( + "On the next screen you will see " + "$seedCount " + "words that make up your recovery phrase.\n\nPlease " + "write it down. Keep it safe and never share it with " + "anyone. Your recovery phrase is the only way you can" + " access your funds if you forget your PIN, lose your" + " phone, etc.\n\n${AppConfig.appName} does not keep nor is " + "able to restore your recover phrase. Only you have " + "access to your wallet.", + style: + isDesktop + ? STextStyles.desktopTextMediumRegular( + context, + ) + : STextStyles.subtitle( + context, + ).copyWith(fontSize: 12), + ) + : Column( + children: [ + Text( + "Important", + style: STextStyles.desktopH3( context, - ) - : STextStyles.subtitle(context).copyWith( - fontSize: 12, - ), - ) - : Column( - children: [ - Text( - "Important", - style: - STextStyles.desktopH3(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorBlue, - ), - ), - const SizedBox( - height: 24, - ), - RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: STextStyles.desktopH3(context) - .copyWith(fontSize: 18), - children: [ - TextSpan( - text: - "On the next screen you will be given ", - style: STextStyles.desktopH3(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - fontSize: 18, - height: 1.3, - ), - ), - TextSpan( - text: "$seedCount words", - style: STextStyles.desktopH3(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorBlue, - fontSize: 18, - height: 1.3, - ), - ), - TextSpan( - text: ". They are your ", - style: STextStyles.desktopH3(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - fontSize: 18, - height: 1.3, - ), - ), - TextSpan( - text: "recovery phrase", - style: STextStyles.desktopH3(context) - .copyWith( - color: Theme.of(context) + ).copyWith( + color: + Theme.of(context) .extension()! .accentColorBlue, - fontSize: 18, - height: 1.3, - ), - ), - TextSpan( - text: ".", - style: STextStyles.desktopH3(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - fontSize: 18, - height: 1.3, - ), - ), - ], + ), ), - ), - const SizedBox( - height: 40, - ), - Column( - children: [ - Row( + const SizedBox(height: 24), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: STextStyles.desktopH3( + context, + ).copyWith(fontSize: 18), children: [ - SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - radiusMultiplier: 20, - padding: const EdgeInsets.all(9), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: SvgPicture.asset( - Assets.svg.pencil, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), + TextSpan( + text: + "On the next screen you will be given ", + style: STextStyles.desktopH3( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + fontSize: 18, + height: 1.3, ), ), - const SizedBox( - width: 20, - ), - Text( - "Write them down.", - style: - STextStyles.navBarTitle(context), + TextSpan( + text: "$seedCount words", + style: STextStyles.desktopH3( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorBlue, + fontSize: 18, + height: 1.3, + ), ), - ], - ), - const SizedBox( - height: 30, - ), - Row( - children: [ - SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - radiusMultiplier: 20, - padding: const EdgeInsets.all(8), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: SvgPicture.asset( - Assets.svg.lock, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), + TextSpan( + text: ". They are your ", + style: STextStyles.desktopH3( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + fontSize: 18, + height: 1.3, ), ), - const SizedBox( - width: 20, + TextSpan( + text: "recovery phrase", + style: STextStyles.desktopH3( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorBlue, + fontSize: 18, + height: 1.3, + ), ), - Text( - "Keep them safe.", - style: - STextStyles.navBarTitle(context), + TextSpan( + text: ".", + style: STextStyles.desktopH3( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + fontSize: 18, + height: 1.3, + ), ), ], ), - const SizedBox( - height: 30, - ), - Row( - children: [ - SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - radiusMultiplier: 20, - padding: const EdgeInsets.all(8), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: SvgPicture.asset( - Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .accentColorDark, + ), + const SizedBox(height: 40), + Column( + children: [ + Row( + children: [ + SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + radiusMultiplier: 20, + padding: const EdgeInsets.all(9), + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, + child: SvgPicture.asset( + Assets.svg.pencil, + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), ), ), - ), - const SizedBox( - width: 20, - ), - Expanded( - child: Text( - "Do not show them to anyone.", + const SizedBox(width: 20), + Text( + "Write them down.", style: STextStyles.navBarTitle( context, ), ), - ), - ], - ), - ], - ), - ], - ), + ], + ), + const SizedBox(height: 30), + Row( + children: [ + SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + radiusMultiplier: 20, + padding: const EdgeInsets.all(8), + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, + child: SvgPicture.asset( + Assets.svg.lock, + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), + ), + ), + const SizedBox(width: 20), + Text( + "Keep them safe.", + style: STextStyles.navBarTitle( + context, + ), + ), + ], + ), + const SizedBox(height: 30), + Row( + children: [ + SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + radiusMultiplier: 20, + padding: const EdgeInsets.all(8), + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, + child: SvgPicture.asset( + Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), + ), + ), + const SizedBox(width: 20), + Expanded( + child: Text( + "Do not show them to anyone.", + style: STextStyles.navBarTitle( + context, + ), + ), + ), + ], + ), + ], + ), + ], + ), ), if (!isDesktop) const Spacer(), - if (!isDesktop) - const SizedBox( - height: 16, - ), - if (isDesktop) - const SizedBox( - height: 32, - ), + if (!isDesktop) const SizedBox(height: 16), + if (isDesktop) const SizedBox(height: 32), ConstrainedBox( constraints: BoxConstraints( maxWidth: isDesktop ? 480 : 0, @@ -605,9 +575,10 @@ class _NewWalletRecoveryPhraseWarningViewState children: [ GestureDetector( onTap: () { - final value = ref - .read(checkBoxStateProvider.state) - .state; + final value = + ref + .read(checkBoxStateProvider.state) + .state; ref.read(checkBoxStateProvider.state).state = !value; }, @@ -623,11 +594,12 @@ class _NewWalletRecoveryPhraseWarningViewState child: Checkbox( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - value: ref - .watch( - checkBoxStateProvider.state, - ) - .state, + value: + ref + .watch( + checkBoxStateProvider.state, + ) + .state, onChanged: (newValue) { ref .read( @@ -637,65 +609,67 @@ class _NewWalletRecoveryPhraseWarningViewState }, ), ), - SizedBox( - width: isDesktop ? 20 : 10, - ), + SizedBox(width: isDesktop ? 20 : 10), Flexible( child: Text( "I understand that ${AppConfig.appName} 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, - ) - : STextStyles.baseXS(context) - .copyWith( - height: 1.3, - ), + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ) + : STextStyles.baseXS( + context, + ).copyWith(height: 1.3), ), ), ], ), ), ), - SizedBox( - height: isDesktop ? 32 : 16, - ), + SizedBox(height: isDesktop ? 32 : 16), ConstrainedBox( constraints: BoxConstraints( minHeight: isDesktop ? 70 : 0, ), child: TextButton( - onPressed: ref - .read(checkBoxStateProvider.state) - .state - ? _initNewWallet - : null, - style: ref - .read(checkBoxStateProvider.state) - .state - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle( - context, - ), - child: Text( - "View recovery phrase", - style: isDesktop - ? ref - .read( - checkBoxStateProvider.state, - ) - .state - ? STextStyles.desktopButtonEnabled( + onPressed: + ref + .read(checkBoxStateProvider.state) + .state + ? _initNewWallet + : null, + style: + ref + .read(checkBoxStateProvider.state) + .state + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle( context, ) - : STextStyles.desktopButtonDisabled( + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( context, - ) - : STextStyles.button(context), + ), + child: Text( + "View recovery phrase", + style: + isDesktop + ? ref + .read( + checkBoxStateProvider + .state, + ) + .state + ? STextStyles.desktopButtonEnabled( + context, + ) + : STextStyles.desktopButtonDisabled( + context, + ) + : STextStyles.button(context), ), ), ), diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart index b4b7d03e3..75bda4577 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart @@ -2,8 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:cs_monero/src/deprecated/get_height_by_date.dart' - as cs_monero_deprecated; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -13,7 +11,6 @@ import 'package:wakelock_plus/wakelock_plus.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../pages_desktop_specific/desktop_home_view.dart'; import '../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/secure_store_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; @@ -91,9 +88,7 @@ class _RestoreViewOnlyWalletViewState if (!Util.isDesktop) { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); } if (mounted) { @@ -102,9 +97,7 @@ class _RestoreViewOnlyWalletViewState useSafeArea: false, barrierDismissible: true, builder: (context) { - return ConfirmRecoveryDialog( - onConfirm: _attemptRestore, - ); + return ConfirmRecoveryDialog(onConfirm: _attemptRestore); }, ); } @@ -121,17 +114,15 @@ class _RestoreViewOnlyWalletViewState final ViewOnlyWalletType viewOnlyWalletType; if (widget.coin is Bip39HDCurrency) { if (widget.coin is Firo) { - otherDataJson.addAll( - { - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: - widget.enableLelantusScanning, - }, - ); + otherDataJson.addAll({ + WalletInfoKeys.lelantusCoinIsarRescanRequired: false, + WalletInfoKeys.enableLelantusScanning: widget.enableLelantusScanning, + }); } - viewOnlyWalletType = _addressOnly - ? ViewOnlyWalletType.addressOnly - : ViewOnlyWalletType.xPub; + viewOnlyWalletType = + _addressOnly + ? ViewOnlyWalletType.addressOnly + : ViewOnlyWalletType.xPub; } else if (widget.coin is CryptonoteCurrency) { viewOnlyWalletType = ViewOnlyWalletType.cryptonote; } else { @@ -166,10 +157,9 @@ class _RestoreViewOnlyWalletViewState onCancel: () async { isRestoring = false; - await ref.read(pWallets).deleteWallet( - info, - ref.read(secureStoreProvider), - ); + await ref + .read(pWallets) + .deleteWallet(info, ref.read(secureStoreProvider)); }, ); }, @@ -220,10 +210,9 @@ class _RestoreViewOnlyWalletViewState if (node == null) { node = widget.coin.defaultNode; - await ref.read(nodeServiceChangeNotifierProvider).setPrimaryNodeFor( - coin: widget.coin, - node: node, - ); + await ref + .read(nodeServiceChangeNotifierProvider) + .setPrimaryNodeFor(coin: widget.coin, node: node); } try { @@ -267,21 +256,25 @@ class _RestoreViewOnlyWalletViewState isar: ref.read(mainDBProvider).isar, ); + if (ref.read(pDuress)) { + await wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } + ref.read(pWallets).addWallet(wallet); if (mounted) { if (Util.isDesktop) { - Navigator.of(context).popUntil( - ModalRoute.withName( - DesktopHomeView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { unawaited( - Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, - ), + Navigator.of( + context, + ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false), ); } @@ -329,9 +322,10 @@ class _RestoreViewOnlyWalletViewState viewKeyController = TextEditingController(); if (widget.coin is Bip39HDCurrency) { - _currentDropDownValue = (widget.coin as Bip39HDCurrency) - .supportedHardenedDerivationPaths - .last; + _currentDropDownValue = + (widget.coin as Bip39HDCurrency) + .supportedHardenedDerivationPaths + .last; } } @@ -350,27 +344,28 @@ class _RestoreViewOnlyWalletViewState return MasterScaffold( isDesktop: isDesktop, - appBar: isDesktop - ? const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ) - : AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 50), - ); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, + appBar: + isDesktop + ? const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 50), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), ), - ), body: Container( color: Theme.of(context).extension()!.background, child: LayoutBuilder( @@ -386,28 +381,21 @@ class _RestoreViewOnlyWalletViewState padding: const EdgeInsets.all(16), child: Column( children: [ - if (isDesktop) - const Spacer( - flex: 10, - ), + if (isDesktop) const Spacer(flex: 10), if (!isDesktop) Text( widget.walletName, style: STextStyles.itemSubtitle(context), ), - SizedBox( - height: isDesktop ? 0 : 4, - ), + SizedBox(height: isDesktop ? 0 : 4), Text( "Enter view only details", - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), + style: + isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), ), - if (isElectrumX) - SizedBox( - height: isDesktop ? 24 : 16, - ), + if (isElectrumX) SizedBox(height: isDesktop ? 24 : 16), if (isElectrumX) SizedBox( height: isDesktop ? 56 : 48, @@ -416,12 +404,14 @@ class _RestoreViewOnlyWalletViewState key: UniqueKey(), onText: "Extended pub key", offText: "Single address", - onColor: Theme.of(context) - .extension()! - .popupBG, - offColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + onColor: + Theme.of( + context, + ).extension()!.popupBG, + offColor: + Theme.of(context) + .extension()! + .textFieldDefaultBG, isOn: _addressOnly, onValueChanged: (value) { setState(() { @@ -436,9 +426,7 @@ class _RestoreViewOnlyWalletViewState ), ), ), - SizedBox( - height: isDesktop ? 24 : 16, - ), + SizedBox(height: isDesktop ? 24 : 16), if (!isElectrumX || _addressOnly) FullTextField( key: const Key("viewOnlyAddressRestoreFieldKey"), @@ -452,16 +440,14 @@ class _RestoreViewOnlyWalletViewState }); } else { setState(() { - _enableRestoreButton = newValue.isNotEmpty && + _enableRestoreButton = + newValue.isNotEmpty && viewKeyController.text.isNotEmpty; }); } }, ), - if (!isElectrumX) - SizedBox( - height: isDesktop ? 16 : 12, - ), + if (!isElectrumX) SizedBox(height: isDesktop ? 16 : 12), if (isElectrumX && !_addressOnly) DropdownButtonHideUnderline( child: DropdownButton2( @@ -489,9 +475,10 @@ class _RestoreViewOnlyWalletViewState isExpanded: true, buttonStyleData: ButtonStyleData( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -504,9 +491,10 @@ class _RestoreViewOnlyWalletViewState Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), ), @@ -514,9 +502,10 @@ class _RestoreViewOnlyWalletViewState offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -531,9 +520,7 @@ class _RestoreViewOnlyWalletViewState ), ), if (isElectrumX && !_addressOnly) - SizedBox( - height: isDesktop ? 16 : 12, - ), + SizedBox(height: isDesktop ? 16 : 12), if (!isElectrumX || !_addressOnly) FullTextField( key: const Key("viewOnlyKeyRestoreFieldKey"), @@ -548,26 +535,22 @@ class _RestoreViewOnlyWalletViewState }); } else { setState(() { - _enableRestoreButton = value.isNotEmpty && + _enableRestoreButton = + value.isNotEmpty && addressController.text.isNotEmpty; }); } }, ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 24 : 16, - ), + SizedBox(height: isDesktop ? 24 : 16), PrimaryButton( enabled: _enableRestoreButton, onPressed: _requestRestore, width: isDesktop ? 480 : null, label: "Restore", ), - if (isDesktop) - const Spacer( - flex: 15, - ), + if (isDesktop) const Spacer(flex: 15), ], ), ), diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 59d479112..90ef055e2 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -22,13 +22,11 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; - import 'package:xelis_flutter/src/api/seed_search_engine.dart' as x_seed; import '../../../notifications/show_flush_bar.dart'; import '../../../pages_desktop_specific/desktop_home_view.dart'; import '../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/secure_store_provider.dart'; import '../../../providers/providers.dart'; import '../../../services/transaction_notification_tracker.dart'; @@ -48,8 +46,8 @@ import '../../../wallets/isar/models/wallet_info.dart'; import '../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../wallets/wallet/impl/wownero_wallet.dart'; -import '../../../wallets/wallet/intermediate/external_wallet.dart'; import '../../../wallets/wallet/impl/xelis_wallet.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; import '../../../wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; import '../../../wallets/wallet/wallet.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -158,9 +156,10 @@ class _RestoreWalletViewState extends ConsumerState { _seedWordCount = widget.seedWordsLength; isDesktop = Util.isDesktop; - textSelectionControls = Platform.isIOS - ? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste) - : CustomMaterialTextSelectionControls(onPaste: onControlsPaste); + textSelectionControls = + Platform.isIOS + ? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste) + : CustomMaterialTextSelectionControls(onPaste: onControlsPaste); scanner = widget.barcodeScanner; for (int i = 0; i < _seedWordCount; i++) { @@ -170,7 +169,9 @@ class _RestoreWalletViewState extends ConsumerState { } if (widget.coin is Xelis) { - _xelisSeedSearch = x_seed.SearchEngine.init(languageIndex: BigInt.from(0)); + _xelisSeedSearch = x_seed.SearchEngine.init( + languageIndex: BigInt.from(0), + ); } super.initState(); @@ -213,10 +214,7 @@ class _RestoreWalletViewState extends ConsumerState { OutlineInputBorder _buildOutlineInputBorder(Color color) { return OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: color, - ), + borderSide: BorderSide(width: 1, color: color), borderRadius: BorderRadius.circular(Constants.size.circularBorderRadius), ); } @@ -236,34 +234,31 @@ class _RestoreWalletViewState extends ConsumerState { // TODO: make more robust estimate of date maybe using https://explorer.epic.tech/api-index if (widget.coin is Epiccash) { - otherDataJsonString = jsonEncode( - { - WalletInfoKeys.epiccashData: jsonEncode( - ExtraEpiccashWalletInfo( - receivingIndex: 0, - changeIndex: 0, - slatesToAddresses: {}, - slatesToCommits: {}, - lastScannedBlock: height, - restoreHeight: height, - creationHeight: height, - ).toMap(), - ), - }, - ); + otherDataJsonString = jsonEncode({ + WalletInfoKeys.epiccashData: jsonEncode( + ExtraEpiccashWalletInfo( + receivingIndex: 0, + changeIndex: 0, + slatesToAddresses: {}, + slatesToCommits: {}, + lastScannedBlock: height, + restoreHeight: height, + creationHeight: height, + ).toMap(), + ), + }); } else if (widget.coin is Firo) { - otherDataJsonString = jsonEncode( - { - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: - widget.enableLelantusScanning, - }, - ); + otherDataJsonString = jsonEncode({ + WalletInfoKeys.lelantusCoinIsarRescanRequired: false, + WalletInfoKeys.enableLelantusScanning: widget.enableLelantusScanning, + }); } // TODO: do actual check to make sure it is a valid mnemonic for monero + xelis if (bip39.validateMnemonic(mnemonic) == false && - !(widget.coin is Monero || widget.coin is Wownero || widget.coin is Xelis)) { + !(widget.coin is Monero || + widget.coin is Wownero || + widget.coin is Xelis)) { unawaited( showFloatingFlushBar( type: FlushBarType.warning, @@ -297,10 +292,9 @@ class _RestoreWalletViewState extends ConsumerState { if (mounted) setState(() => _hideSeedWords = false); - await ref.read(pWallets).deleteWallet( - info, - ref.read(secureStoreProvider), - ); + await ref + .read(pWallets) + .deleteWallet(info, ref.read(secureStoreProvider)); }, ); }, @@ -314,14 +308,14 @@ class _RestoreWalletViewState extends ConsumerState { if (node == null) { node = widget.coin.defaultNode; - await ref.read(nodeServiceChangeNotifierProvider).setPrimaryNodeFor( - coin: widget.coin, - node: node, - ); + await ref + .read(nodeServiceChangeNotifierProvider) + .setPrimaryNodeFor(coin: widget.coin, node: node); } - final txTracker = - TransactionNotificationTracker(walletId: info.walletId); + final txTracker = TransactionNotificationTracker( + walletId: info.walletId, + ); try { final wallet = await Wallet.create( @@ -368,15 +362,24 @@ class _RestoreWalletViewState extends ConsumerState { isar: ref.read(mainDBProvider).isar, ); + if (ref.read(pDuress)) { + await wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } + ref.read(pWallets).addWallet(wallet); - final isCreateSpecialEthWallet = - ref.read(createSpecialEthWalletRoutingFlag); + final isCreateSpecialEthWallet = ref.read( + createSpecialEthWalletRoutingFlag, + ); if (isCreateSpecialEthWallet) { ref.read(createSpecialEthWalletRoutingFlag.notifier).state = false; - ref.read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state).state = - !ref + ref + .read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state) + .state = !ref .read( newEthWalletTriggerTempUntilHiveCompletelyDeleted.state, ) @@ -385,17 +388,13 @@ class _RestoreWalletViewState extends ConsumerState { if (mounted) { if (isDesktop) { - Navigator.of(context).popUntil( - ModalRoute.withName( - DesktopHomeView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { if (isCreateSpecialEthWallet) { Navigator.of(context).popUntil( - ModalRoute.withName( - SelectWalletForTokenView.routeName, - ), + ModalRoute.withName(SelectWalletForTokenView.routeName), ); } else { unawaited( @@ -488,57 +487,54 @@ class _RestoreWalletViewState extends ConsumerState { break; case FormInputStatus.invalid: color = Theme.of(context).extension()!.textFieldErrorBG; - prefixColor = Theme.of(context) - .extension()! - .textFieldErrorSearchIconLeft; + prefixColor = + Theme.of( + context, + ).extension()!.textFieldErrorSearchIconLeft; borderColor = Theme.of(context).extension()!.textFieldErrorBorder; suffixIcon = SvgPicture.asset( Assets.svg.alertCircle, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .textFieldErrorSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldErrorSearchIconRight, ); break; case FormInputStatus.valid: color = Theme.of(context).extension()!.textFieldSuccessBG; - prefixColor = Theme.of(context) - .extension()! - .textFieldSuccessSearchIconLeft; + prefixColor = + Theme.of( + context, + ).extension()!.textFieldSuccessSearchIconLeft; borderColor = Theme.of(context).extension()!.textFieldSuccessBorder; suffixIcon = SvgPicture.asset( Assets.svg.checkCircle, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .textFieldSuccessSearchIconRight, + color: + Theme.of( + context, + ).extension()!.textFieldSuccessSearchIconRight, ); break; } return InputDecoration( fillColor: color, filled: true, - contentPadding: const EdgeInsets.symmetric( - vertical: 12, - horizontal: 16, - ), + contentPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), prefixIcon: Align( alignment: Alignment.centerLeft, child: Padding( - padding: const EdgeInsets.only( - left: 12, - bottom: 2, - ), + padding: const EdgeInsets.only(left: 12, bottom: 2), child: Text( prefix, - style: STextStyles.fieldLabel(context).copyWith( - color: prefixColor, - fontSize: Util.isDesktop ? 16 : 14, - ), + style: STextStyles.fieldLabel( + context, + ).copyWith(color: prefixColor, fontSize: Util.isDesktop ? 16 : 14), ), ), ), @@ -633,8 +629,9 @@ class _RestoreWalletViewState extends ConsumerState { Future pasteMnemonic() async { //todo: check if print needed // debugPrint("restoreWalletPasteButton tapped"); - final ClipboardData? data = - await widget.clipboard.getData(Clipboard.kTextPlain); + final ClipboardData? data = await widget.clipboard.getData( + Clipboard.kTextPlain, + ); if (data?.text != null && data!.text!.isNotEmpty) { final content = data.text!.trim(); @@ -646,9 +643,7 @@ class _RestoreWalletViewState extends ConsumerState { Future requestRestore() async { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); if (mounted) { await showDialog( @@ -656,9 +651,7 @@ class _RestoreWalletViewState extends ConsumerState { useSafeArea: false, barrierDismissible: true, builder: (context) { - return ConfirmRecoveryDialog( - onConfirm: attemptRestore, - ); + return ConfirmRecoveryDialog(onConfirm: attemptRestore); }, ); } @@ -669,85 +662,90 @@ class _RestoreWalletViewState extends ConsumerState { final isDesktop = Util.isDesktop; return MasterScaffold( isDesktop: isDesktop, - appBar: isDesktop - ? const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ) - : AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 50), - ); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - semanticsLabel: - "View QR Code Button. Opens Camera To Scan QR Code For Restoring Wallet.", - key: const Key("restoreWalletViewQrCodeButton"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: QrCodeIcon( - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .accentColorDark, + appBar: + isDesktop + ? const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 50), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + semanticsLabel: + "View QR Code Button. Opens Camera To Scan QR Code For Restoring Wallet.", + key: const Key("restoreWalletViewQrCodeButton"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: QrCodeIcon( + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + onPressed: scanMnemonicQr, ), - onPressed: scanMnemonicQr, ), ), - ), - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard For Restoring Wallet.", - key: const Key("restoreWalletPasteButton"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: ClipboardIcon( - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .accentColorDark, + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard For Restoring Wallet.", + key: const Key("restoreWalletPasteButton"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: ClipboardIcon( + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + onPressed: pasteMnemonic, ), - onPressed: pasteMnemonic, ), ), - ), - ], - ), + ], + ), body: Container( color: Theme.of(context).extension()!.background, child: Padding( @@ -765,27 +763,23 @@ class _RestoreWalletViewState extends ConsumerState { widget.walletName, style: STextStyles.itemSubtitle(context), ), - SizedBox( - height: isDesktop ? 0 : 4, - ), + SizedBox(height: isDesktop ? 0 : 4), Text( "Recovery phrase", - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 8, + style: + isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), ), + SizedBox(height: isDesktop ? 16 : 8), Text( "Enter your $_seedWordCount-word recovery phrase.", - style: isDesktop - ? STextStyles.desktopSubtitleH2(context) - : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 16 : 10, + style: + isDesktop + ? STextStyles.desktopSubtitleH2(context) + : STextStyles.subtitle(context), ), + SizedBox(height: isDesktop ? 16 : 10), if (isDesktop) Row( mainAxisAlignment: MainAxisAlignment.center, @@ -803,19 +797,18 @@ class _RestoreWalletViewState extends ConsumerState { Assets.svg.clipboard, width: 22, height: 22, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - const SizedBox( - width: 8, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), + const SizedBox(width: 8), Text( "Paste", - style: STextStyles - .desktopButtonSmallSecondaryEnabled( - context, - ), + style: + STextStyles.desktopButtonSmallSecondaryEnabled( + context, + ), ), ], ), @@ -823,15 +816,10 @@ class _RestoreWalletViewState extends ConsumerState { ), ], ), - if (isDesktop) - const SizedBox( - height: 20, - ), + if (isDesktop) const SizedBox(height: 20), if (isDesktop) ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 1008, - ), + constraints: const BoxConstraints(maxWidth: 1008), child: Builder( builder: (BuildContext context) { const cols = 4; @@ -868,24 +856,23 @@ class _RestoreWalletViewState extends ConsumerState { ), decoration: _getInputDecorationFor( - _inputStatuses[ - i * 4 + j - 1], - "${i * 4 + j}", - ), + _inputStatuses[i * 4 + + j - + 1], + "${i * 4 + j}", + ), autovalidateMode: AutovalidateMode .onUserInteraction, - selectionControls: i * 4 + - j - - 1 == - 1 - ? textSelectionControls - : null, + selectionControls: + i * 4 + j - 1 == 1 + ? textSelectionControls + : null, // focusNode: // _focusNodes[i * 4 + j - 1], onChanged: (value) { final FormInputStatus - formInputStatus; + formInputStatus; if (value.isEmpty) { formInputStatus = @@ -917,25 +904,31 @@ class _RestoreWalletViewState extends ConsumerState { // } setState(() { _inputStatuses[i * 4 + - j - - 1] = formInputStatus; + j - + 1] = + formInputStatus; }); }, - controller: _controllers[ - i * 4 + j - 1], - style: - STextStyles.field(context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textRestore, + controller: + _controllers[i * 4 + + j - + 1], + style: STextStyles.field( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textRestore, fontSize: isDesktop ? 16 : 14, ), ), - if (_inputStatuses[ - i * 4 + j - 1] == + if (_inputStatuses[i * 4 + + j - + 1] == FormInputStatus.invalid) Align( alignment: @@ -943,23 +936,22 @@ class _RestoreWalletViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.only( - left: 12.0, - bottom: 4.0, - ), + left: 12.0, + bottom: 4.0, + ), child: Text( "Please check spelling", textAlign: TextAlign.left, - style: - STextStyles.label( + style: STextStyles.label( context, ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textError, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textError, ), ), ), @@ -974,19 +966,23 @@ class _RestoreWalletViewState extends ConsumerState { TableViewRow( spacing: 16, cells: [ - for (int i = rows * cols; - i < _seedWordCount - remainder; - i++) ...[ + for ( + int i = rows * cols; + i < _seedWordCount - remainder; + i++ + ) ...[ const TableViewCell( flex: 1, child: Column( - // ... (existing code for input field) - ), + // ... (existing code for input field) + ), ), ], - for (int i = _seedWordCount - remainder; - i < _seedWordCount; - i++) ...[ + for ( + int i = _seedWordCount - remainder; + i < _seedWordCount; + i++ + ) ...[ TableViewCell( flex: 1, child: Column( @@ -1002,18 +998,19 @@ class _RestoreWalletViewState extends ConsumerState { ), decoration: _getInputDecorationFor( - _inputStatuses[i], - "${i + 1}", - ), + _inputStatuses[i], + "${i + 1}", + ), autovalidateMode: AutovalidateMode .onUserInteraction, - selectionControls: i == 1 - ? textSelectionControls - : null, + selectionControls: + i == 1 + ? textSelectionControls + : null, onChanged: (value) { final FormInputStatus - formInputStatus; + formInputStatus; if (value.isEmpty) { formInputStatus = @@ -1037,13 +1034,15 @@ class _RestoreWalletViewState extends ConsumerState { }); }, controller: _controllers[i], - style: - STextStyles.field(context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .overlay, + style: STextStyles.field( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .overlay, fontSize: isDesktop ? 16 : 14, ), @@ -1056,23 +1055,22 @@ class _RestoreWalletViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.only( - left: 12.0, - bottom: 4.0, - ), + left: 12.0, + bottom: 4.0, + ), child: Text( "Please check spelling", textAlign: TextAlign.left, - style: - STextStyles.label( + style: STextStyles.label( context, ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textError, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textError, ), ), ), @@ -1081,9 +1079,11 @@ class _RestoreWalletViewState extends ConsumerState { ), ), ], - for (int i = 0; - i < cols - remainder; - i++) ...[ + for ( + int i = 0; + i < cols - remainder; + i++ + ) ...[ TableViewCell( flex: 1, child: Container(), @@ -1095,9 +1095,7 @@ class _RestoreWalletViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), PrimaryButton( label: "Restore wallet", width: 480, @@ -1124,8 +1122,9 @@ class _RestoreWalletViewState extends ConsumerState { Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: TextFormField( obscureText: _hideSeedWords, autocorrect: !isDesktop, @@ -1169,9 +1168,10 @@ class _RestoreWalletViewState extends ConsumerState { }, controller: _controllers[i - 1], style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textRestore, + color: + Theme.of(context) + .extension()! + .textRestore, fontSize: isDesktop ? 16 : 14, ), ), @@ -1188,11 +1188,13 @@ class _RestoreWalletViewState extends ConsumerState { child: Text( "Please check spelling", textAlign: TextAlign.left, - style: - STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .textError, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, ), ), ), @@ -1200,9 +1202,7 @@ class _RestoreWalletViewState extends ConsumerState { ], ), Padding( - padding: const EdgeInsets.only( - top: 8.0, - ), + padding: const EdgeInsets.only(top: 8.0), child: PrimaryButton( onPressed: requestRestore, label: "Restore", diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart index 04dc94d33..97c467b34 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart @@ -23,7 +23,6 @@ import '../../../models/keys/view_only_wallet_data.dart'; import '../../../notifications/show_flush_bar.dart'; import '../../../pages_desktop_specific/desktop_home_view.dart'; import '../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/secure_store_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; @@ -36,7 +35,6 @@ import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/crypto_currency/intermediate/bip39_hd_currency.dart'; import '../../../wallets/isar/models/wallet_info.dart'; -import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../wallets/wallet/impl/wownero_wallet.dart'; @@ -117,12 +115,10 @@ class _VerifyRecoveryPhraseViewState final ViewOnlyWalletType viewOnlyWalletType; if (widget.wallet is ExtendedKeysInterface) { if (widget.wallet.cryptoCurrency is Firo) { - otherDataJson.addAll( - { - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: false, - }, - ); + otherDataJson.addAll({ + WalletInfoKeys.lelantusCoinIsarRescanRequired: false, + WalletInfoKeys.enableLelantusScanning: false, + }); } viewOnlyWalletType = ViewOnlyWalletType.xPub; } else if (widget.wallet is LibMoneroWallet) { @@ -184,8 +180,9 @@ class _VerifyRecoveryPhraseViewState } else if (widget.wallet is LibMoneroWallet) { final w = widget.wallet as LibMoneroWallet; - final info = await w - .hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing(); + final info = + await w + .hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing(); final address = info.$1; final privateViewKey = info.$2; @@ -241,23 +238,27 @@ class _VerifyRecoveryPhraseViewState isar: ref.read(mainDBProvider).isar, ); + if (ref.read(pDuress)) { + await voWallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } + ref.read(pWallets).addWallet(voWallet); await voWallet.exit(); - await ref.read(pWallets).deleteWallet( - widget.wallet.info, - ref.read(secureStoreProvider), - ); + await ref + .read(pWallets) + .deleteWallet(widget.wallet.info, ref.read(secureStoreProvider)); } catch (e) { - await ref.read(pWallets).deleteWallet( - widget.wallet.info, - ref.read(secureStoreProvider), - ); - await ref.read(pWallets).deleteWallet( - voWallet.info, - ref.read(secureStoreProvider), - ); + await ref + .read(pWallets) + .deleteWallet(widget.wallet.info, ref.read(secureStoreProvider)); + await ref + .read(pWallets) + .deleteWallet(voWallet.info, ref.read(secureStoreProvider)); rethrow; } @@ -274,20 +275,27 @@ class _VerifyRecoveryPhraseViewState } } - await ref.read(pWalletInfo(widget.wallet.walletId)).setMnemonicVerified( - isar: ref.read(mainDBProvider).isar, - ); + await widget.wallet.info.setMnemonicVerified( + isar: ref.read(mainDBProvider).isar, + ); + + if (ref.read(pDuress)) { + await widget.wallet.info.updateDuressVisibilityStatus( + isDuressVisible: true, + isar: ref.read(mainDBProvider).isar, + ); + } ref.read(pWallets).addWallet(widget.wallet); - final isCreateSpecialEthWallet = - ref.read(createSpecialEthWalletRoutingFlag); + final isCreateSpecialEthWallet = ref.read( + createSpecialEthWalletRoutingFlag, + ); if (isCreateSpecialEthWallet) { ref.read(createSpecialEthWalletRoutingFlag.notifier).state = false; ref - .read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state) - .state = - !ref + .read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state) + .state = !ref .read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state) .state; } @@ -311,23 +319,22 @@ class _VerifyRecoveryPhraseViewState throw ex!; } } catch (e, s) { - Logging.instance.f("$e\n$s", error: e, stackTrace: s,); + Logging.instance.f("$e\n$s", error: e, stackTrace: s); if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: e.toString(), - desktopPopRootNavigator: Util.isDesktop, - ), + builder: + (_) => StackOkDialog( + title: e.toString(), + desktopPopRootNavigator: Util.isDesktop, + ), ); } if (mounted) { Navigator.of(context).popUntil( - ModalRoute.withName( - NewWalletRecoveryPhraseView.routeName, - ), + ModalRoute.withName(NewWalletRecoveryPhraseView.routeName), ); } return; @@ -337,17 +344,13 @@ class _VerifyRecoveryPhraseViewState if (mounted) { if (isDesktop) { if (isCreateSpecialEthWallet) { - Navigator.of(context).popUntil( - ModalRoute.withName( - SelectWalletForTokenView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(SelectWalletForTokenView.routeName)); } else { - Navigator.of(context).popUntil( - ModalRoute.withName( - DesktopHomeView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); if (_coin is Ethereum) { unawaited( Navigator.of(context).pushNamed( @@ -359,17 +362,14 @@ class _VerifyRecoveryPhraseViewState } } else { if (isCreateSpecialEthWallet) { - Navigator.of(context).popUntil( - ModalRoute.withName( - SelectWalletForTokenView.routeName, - ), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(SelectWalletForTokenView.routeName)); } else { unawaited( - Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, - ), + Navigator.of( + context, + ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false), ); if (_coin is Ethereum) { unawaited( @@ -460,10 +460,9 @@ class _VerifyRecoveryPhraseViewState } Future delete() async { - await ref.read(pWallets).deleteWallet( - widget.wallet.info, - ref.read(secureStoreProvider), - ); + await ref + .read(pWallets) + .deleteWallet(widget.wallet.info, ref.read(secureStoreProvider)); } @override @@ -476,40 +475,41 @@ class _VerifyRecoveryPhraseViewState onWillPop: onWillPop, child: MasterScaffold( isDesktop: isDesktop, - appBar: isDesktop - ? DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).popUntil( - ModalRoute.withName( - NewWalletRecoveryPhraseView.routeName, - ), - ); - }, - ), - trailing: ExitToMyStackButton( - onPressed: () async { - await delete(); - if (context.mounted) { + appBar: + isDesktop + ? DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton( + onPressed: () async { Navigator.of(context).popUntil( - ModalRoute.withName(DesktopHomeView.routeName), + ModalRoute.withName( + NewWalletRecoveryPhraseView.routeName, + ), ); - } - }, - ), - ) - : AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).popUntil( - ModalRoute.withName( - NewWalletRecoveryPhraseView.routeName, - ), - ); - }, + }, + ), + trailing: ExitToMyStackButton( + onPressed: () async { + await delete(); + if (context.mounted) { + Navigator.of(context).popUntil( + ModalRoute.withName(DesktopHomeView.routeName), + ); + } + }, + ), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).popUntil( + ModalRoute.withName( + NewWalletRecoveryPhraseView.routeName, + ), + ); + }, + ), ), - ), body: SizedBox( width: isDesktop ? 410 : null, child: Padding( @@ -518,40 +518,32 @@ class _VerifyRecoveryPhraseViewState child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (isDesktop) - const Spacer( - flex: 10, - ), - SizedBox( - height: isDesktop ? 24 : 4, - ), + if (isDesktop) const Spacer(flex: 10), + SizedBox(height: isDesktop ? 24 : 4), Text( "Verify recovery phrase", textAlign: TextAlign.center, - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - SizedBox( - height: isDesktop ? 16 : 4, + style: + isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.label(context).copyWith(fontSize: 12), ), + SizedBox(height: isDesktop ? 16 : 4), Text( isDesktop ? "Select word number" : "Tap word number ", textAlign: TextAlign.center, - style: isDesktop - ? STextStyles.desktopSubtitleH1(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 12, + style: + isDesktop + ? STextStyles.desktopSubtitleH1(context) + : STextStyles.pageTitleH1(context), ), + SizedBox(height: isDesktop ? 16 : 12), Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -564,76 +556,79 @@ class _VerifyRecoveryPhraseViewState child: Text( "${correctIndex + 1}", textAlign: TextAlign.center, - style: STextStyles.subtitle600(context).copyWith( - fontSize: 32, - letterSpacing: 0.25, - ), + style: STextStyles.subtitle600( + context, + ).copyWith(fontSize: 32, letterSpacing: 0.25), ), ), ), - if (isDesktop) - const SizedBox( - height: 40, - ), + if (isDesktop) const SizedBox(height: 40), WordTable( words: randomize(_mnemonic, correctIndex, 9).item1, isDesktop: isDesktop, ), if (!isDesktop) const Spacer(), - if (isDesktop) - const SizedBox( - height: 40, - ), + if (isDesktop) const SizedBox(height: 40), Row( children: [ Expanded( child: Consumer( builder: (_, ref, __) { - final selectedWord = ref - .watch( - verifyMnemonicSelectedWordStateProvider.state, - ) - .state; - final correctWord = ref - .watch( - verifyMnemonicCorrectWordStateProvider.state, - ) - .state; + final selectedWord = + ref + .watch( + verifyMnemonicSelectedWordStateProvider + .state, + ) + .state; + final correctWord = + ref + .watch( + verifyMnemonicCorrectWordStateProvider + .state, + ) + .state; return ConstrainedBox( constraints: BoxConstraints( minHeight: isDesktop ? 70 : 0, ), child: TextButton( - onPressed: selectedWord.isNotEmpty - ? () async { - await _continue( - correctWord == selectedWord, - ); - } - : null, - style: selectedWord.isNotEmpty - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - child: isDesktop - ? Text( - "Verify", - style: selectedWord.isNotEmpty - ? STextStyles.desktopButtonEnabled( - context, - ) - : STextStyles.desktopButtonDisabled( - context, - ), - ) - : Text( - "Continue", - style: STextStyles.button(context), - ), + onPressed: + selectedWord.isNotEmpty + ? () async { + await _continue( + correctWord == selectedWord, + ); + } + : null, + style: + selectedWord.isNotEmpty + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + child: + isDesktop + ? Text( + "Verify", + style: + selectedWord.isNotEmpty + ? STextStyles.desktopButtonEnabled( + context, + ) + : STextStyles.desktopButtonDisabled( + context, + ), + ) + : Text( + "Continue", + style: STextStyles.button(context), + ), ), ); }, @@ -641,10 +636,7 @@ class _VerifyRecoveryPhraseViewState ), ], ), - if (isDesktop) - const Spacer( - flex: 15, - ), + if (isDesktop) const Spacer(flex: 15), ], ), ), diff --git a/lib/pages/pinpad_views/create_pin_view.dart b/lib/pages/pinpad_views/create_pin_view.dart index 586e6c9fd..df1b4e557 100644 --- a/lib/pages/pinpad_views/create_pin_view.dart +++ b/lib/pages/pinpad_views/create_pin_view.dart @@ -26,6 +26,7 @@ import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_pin_put/custom_pin_put.dart'; import '../home_view/home_view.dart'; +import 'lock_screen_view.dart'; class CreatePinView extends ConsumerStatefulWidget { const CreatePinView({ @@ -55,8 +56,10 @@ class _CreatePinViewState extends ConsumerState { ); } - final PageController _pageController = - PageController(initialPage: 0, keepPage: true); + final PageController _pageController = PageController( + initialPage: 0, + keepPage: true, + ); // Attributes for Page 1 of the pageview final TextEditingController _pinPutController1 = TextEditingController(); @@ -118,27 +121,18 @@ class _CreatePinViewState extends ConsumerState { Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - "Create a PIN", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), + Text("Create a PIN", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 8), Text( "This PIN protects access to your wallet.", style: STextStyles.subtitle(context), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), CustomPinPut( fieldsCount: pinCount, eachFieldHeight: 12, eachFieldWidth: 12, - textStyle: STextStyles.label(context).copyWith( - fontSize: 1, - ), + textStyle: STextStyles.label(context).copyWith(fontSize: 1), focusNode: _pinPutFocusNode1, controller: _pinPutController1, useNativeKeyboard: false, @@ -150,9 +144,10 @@ class _CreatePinViewState extends ConsumerState { disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, - fillColor: Theme.of(context) - .extension()! - .background, + fillColor: + Theme.of( + context, + ).extension()!.background, counterText: "", ), isRandom: @@ -188,28 +183,22 @@ class _CreatePinViewState extends ConsumerState { Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - "Confirm PIN", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), + Text("Confirm PIN", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 8), Text( "This PIN protects access to your wallet.", style: STextStyles.subtitle(context), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), CustomPinPut( fieldsCount: pinCount, eachFieldHeight: 12, eachFieldWidth: 12, textStyle: STextStyles.infoSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle3, + color: + Theme.of( + context, + ).extension()!.textSubtitle3, fontSize: 1, ), focusNode: _pinPutFocusNode2, @@ -223,20 +212,23 @@ class _CreatePinViewState extends ConsumerState { disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, - fillColor: Theme.of(context) - .extension()! - .background, + fillColor: + Theme.of( + context, + ).extension()!.background, counterText: "", ), submittedFieldDecoration: _pinPutDecoration.copyWith( - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, border: Border.all( width: 1, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, ), ), selectedFieldDecoration: _pinPutDecoration, @@ -249,14 +241,15 @@ class _CreatePinViewState extends ConsumerState { if (_pinPutController1.text == _pinPutController2.text) { // ask if want to use biometrics - final bool useBiometrics = (Platform.isLinux) - ? false - : await biometrics.authenticate( - cancelButtonText: "SKIP", - localizedReason: - "You can use your fingerprint to unlock the wallet and confirm transactions.", - title: "Enable fingerprint authentication", - ); + final bool useBiometrics = + (Platform.isLinux) + ? false + : await biometrics.authenticate( + cancelButtonText: "SKIP", + localizedReason: + "You can use your fingerprint to unlock the wallet and confirm transactions.", + title: "Enable fingerprint authentication", + ); //TODO investigate why this crashes IOS, maybe ios persists securestorage even after an uninstall? // This should never fail as we are writing a new pin @@ -270,7 +263,7 @@ class _CreatePinViewState extends ConsumerState { ref.read(prefsChangeNotifierProvider).hasPin == false, ); - await _secureStore.write(key: "stack_pin", value: pin); + await _secureStore.write(key: kPinKey, value: pin); ref.read(prefsChangeNotifierProvider).useBiometrics = useBiometrics; @@ -280,11 +273,13 @@ class _CreatePinViewState extends ConsumerState { const Duration(milliseconds: 200), ); - if (mounted) { + if (context.mounted) { if (!widget.popOnSuccess) { - Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, + unawaited( + Navigator.of(context).pushNamedAndRemoveUntil( + HomeView.routeName, + (route) => false, + ), ); } else { Navigator.of(context).pop(); @@ -292,17 +287,21 @@ class _CreatePinViewState extends ConsumerState { } } else { // _onSubmitFailCount++; - _pageController.animateTo( - 0, - duration: const Duration(milliseconds: 300), - curve: Curves.linear, + unawaited( + _pageController.animateTo( + 0, + duration: const Duration(milliseconds: 300), + curve: Curves.linear, + ), ); - showFloatingFlushBar( - type: FlushBarType.warning, - message: "PIN codes do not match. Try again.", - context: context, - iconAsset: Assets.svg.alertCircle, + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "PIN codes do not match. Try again.", + context: context, + iconAsset: Assets.svg.alertCircle, + ), ); _pinPutController1.text = ''; diff --git a/lib/pages/pinpad_views/lock_screen_view.dart b/lib/pages/pinpad_views/lock_screen_view.dart index c7d6bb254..f3552cf82 100644 --- a/lib/pages/pinpad_views/lock_screen_view.dart +++ b/lib/pages/pinpad_views/lock_screen_view.dart @@ -15,11 +15,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mutex/mutex.dart'; import '../../notifications/show_flush_bar.dart'; -// import 'package:stackwallet/providers/global/has_authenticated_start_state_provider.dart'; -import '../../providers/global/node_service_provider.dart'; -import '../../providers/global/prefs_provider.dart'; import '../../providers/global/secure_store_provider.dart'; -import '../../providers/global/wallets_provider.dart'; +import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; // import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart'; import '../../utilities/assets.dart'; @@ -30,6 +27,7 @@ import '../../utilities/show_node_tor_settings_mismatch.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/wallet/intermediate/external_wallet.dart'; +import '../../wallets/wallet/wallet.dart'; import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_buttons/blue_text_button.dart'; @@ -38,6 +36,9 @@ import '../../widgets/shake/shake.dart'; import '../home_view/home_view.dart'; import '../wallet_view/wallet_view.dart'; +const kPinKey = "stack_pin"; +const kDuressPinKey = "stack_pin_duress"; + class LockscreenView extends ConsumerStatefulWidget { const LockscreenView({ super.key, @@ -82,6 +83,54 @@ class _LockscreenViewState extends ConsumerState { static const maxAttemptsBeforeThrottling = 3; Timer? _timer; + Future _loadWallets(String? loadIntoWalletId) async { + await ref + .read(pWallets) + .load( + ref.read(prefsChangeNotifierProvider), + ref.read(mainDBProvider), + ref.read(pDuress), + ); + + if (loadIntoWalletId != null) { + final Wallet wallet; + try { + wallet = ref.read(pWallets).getWallet(loadIntoWalletId); + } catch (_) { + // wallet isn't marked as duress, continue without loading into it + return true; + } + + final canContinue = + mounted && + await checkShowNodeTorSettingsMismatch( + context: context, + currency: wallet.cryptoCurrency, + prefs: ref.read(prefsChangeNotifierProvider), + nodeService: ref.read(nodeServiceChangeNotifierProvider), + allowCancel: false, + rootNavigator: Util.isDesktop, + ); + + if (!canContinue) { + return false; + } + + final Future loadFuture; + if (wallet is ExternalWallet) { + loadFuture = wallet.init().then( + (value) async => await (wallet as ExternalWallet).open(), + ); + } else { + loadFuture = wallet.init(); + } + + await loadFuture; + } + + return true; + } + Future _onUnlock() async { final now = DateTime.now().toUtc(); ref.read(prefsChangeNotifierProvider).lastUnlocked = @@ -97,41 +146,23 @@ class _LockscreenViewState extends ConsumerState { if (widget.popOnSuccess) { Navigator.of(context).pop(widget.routeOnSuccessArguments); } else { - final loadIntoWallet = widget.routeOnSuccess == HomeView.routeName && + final loadIntoWallet = + widget.routeOnSuccess == HomeView.routeName && widget.routeOnSuccessArguments is String; - if (loadIntoWallet) { - final walletId = widget.routeOnSuccessArguments as String; - - final wallet = ref.read(pWallets).getWallet(walletId); - - final canContinue = await checkShowNodeTorSettingsMismatch( + if (widget.isInitialAppLogin) { + final loadSuccess = await showLoading( + whileFuture: _loadWallets( + loadIntoWallet ? widget.routeOnSuccessArguments as String : null, + ), + opaqueBG: true, context: context, - currency: wallet.cryptoCurrency, - prefs: ref.read(prefsChangeNotifierProvider), - nodeService: ref.read(nodeServiceChangeNotifierProvider), - allowCancel: false, - rootNavigator: Util.isDesktop, + message: "Loading wallets...", ); - if (!canContinue) { + if (loadSuccess == null || loadSuccess == false) { return; } - - final Future loadFuture; - if (wallet is ExternalWallet) { - loadFuture = - wallet.init().then((value) async => await (wallet).open()); - } else { - loadFuture = wallet.init(); - } - - await showLoading( - opaqueBG: true, - whileFuture: loadFuture, - context: context, - message: "Loading ${wallet.info.coin.prettyName} wallet...", - ); } if (mounted) { @@ -146,10 +177,9 @@ class _LockscreenViewState extends ConsumerState { final walletId = widget.routeOnSuccessArguments as String; unawaited( - Navigator.of(context).pushNamed( - WalletView.routeName, - arguments: walletId, - ), + Navigator.of( + context, + ).pushNamed(WalletView.routeName, arguments: walletId), ); } } @@ -169,11 +199,27 @@ class _LockscreenViewState extends ConsumerState { final cancelButtonText = widget.biometricsCancelButtonString; if (useBiometrics) { - if (await biometrics.authenticate( - title: title, - localizedReason: localizedReason, - cancelButtonText: cancelButtonText, - )) { + final bool canTryUnlock; + if (widget.isInitialAppLogin) { + final hasDuressPin = + (await _secureStore.read(key: kDuressPinKey)) != null; + + ref.read(pDuress.notifier).state = hasDuressPin; + canTryUnlock = true; + } else { + if (ref.read(pDuress)) { + canTryUnlock = ref.read(prefsChangeNotifierProvider).biometricsDuress; + } else { + canTryUnlock = true; + } + } + + if (canTryUnlock && + (await biometrics.authenticate( + title: title, + localizedReason: localizedReason, + cancelButtonText: cancelButtonText, + ))) { // check if initial log in // if (widget.routeOnSuccess == "/mainview") { // await logIn(await walletsService.networkName, currentWalletName, @@ -239,6 +285,29 @@ class _LockscreenViewState extends ConsumerState { final _pinTextController = TextEditingController(); + Future _checkCanUnlock(String pin) async { + final bool canUnlock; + if (widget.isInitialAppLogin) { + final storedPin = await _secureStore.read(key: kPinKey); + final duressPin = await _secureStore.read(key: kDuressPinKey); + if (pin == storedPin || pin == duressPin) { + ref.read(pDuress.notifier).state = pin == duressPin; + canUnlock = true; + } else { + canUnlock = false; + } + } else { + if (ref.read(pDuress)) { + final duressPin = await _secureStore.read(key: kDuressPinKey); + canUnlock = pin == duressPin; + } else { + final storedPin = await _secureStore.read(key: kPinKey); + canUnlock = pin == storedPin; + } + } + return canUnlock; + } + final Mutex _autoPinCheckLock = Mutex(); void _onPinChangedAutologinCheck() async { if (mounted) { @@ -247,11 +316,8 @@ class _LockscreenViewState extends ConsumerState { try { if (_autoPin && _pinTextController.text.length >= 4) { - final storedPin = await _secureStore.read(key: 'stack_pin'); - if (_pinTextController.text == storedPin) { - await Future.delayed( - const Duration(milliseconds: 200), - ); + if (await _checkCanUnlock(_pinTextController.text)) { + await Future.delayed(const Duration(milliseconds: 200)); unawaited(_onUnlock()); } } @@ -319,21 +385,15 @@ class _LockscreenViewState extends ConsumerState { ), ); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); _pinTextController.text = ''; return; } - final storedPin = await _secureStore.read(key: 'stack_pin'); - - if (storedPin == pin) { - await Future.delayed( - const Duration(milliseconds: 200), - ); + if (await _checkCanUnlock(pin)) { + await Future.delayed(const Duration(milliseconds: 200)); unawaited(_onUnlock()); } else { unawaited(_shakeController.shake()); @@ -348,136 +408,128 @@ class _LockscreenViewState extends ConsumerState { ); } - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); _pinTextController.text = ''; } } Widget get _body => Background( - child: SafeArea( - child: Scaffold( - extendBodyBehindAppBar: true, - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: widget.showBackButton + child: SafeArea( + child: Scaffold( + extendBodyBehindAppBar: true, + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: + widget.showBackButton ? AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 70), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ) + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 70), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ) : Container(), - actions: [ - // check prefs and hide if user has biometrics toggle off? - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only( - right: 16.0, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - if (ref - .read(prefsChangeNotifierProvider) - .useBiometrics == - true) - CustomTextButton( - text: "Use biometrics", - onTap: () async { - await _checkUseBiometrics(); - }, - ), - ], - ), - ), - ], - ), - ], - ), - body: Column( + actions: [ + // check prefs and hide if user has biometrics toggle off? + Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Shake( - animationDuration: const Duration(milliseconds: 700), - animationRange: 12, - controller: _shakeController, - child: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - "Enter PIN", - style: STextStyles.pageTitleH1(context), - ), - ), - const SizedBox( - height: 52, - ), - CustomPinPut( - fieldsCount: pinCount, - eachFieldHeight: 12, - eachFieldWidth: 12, - textStyle: STextStyles.label(context).copyWith( - fontSize: 1, - ), - focusNode: _pinFocusNode, - controller: _pinTextController, - useNativeKeyboard: false, - obscureText: "", - inputDecoration: InputDecoration( - border: InputBorder.none, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - disabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - focusedErrorBorder: InputBorder.none, - fillColor: Theme.of(context) - .extension()! - .background, - counterText: "", - ), - submittedFieldDecoration: _pinPutDecoration, - isRandom: ref - .read(prefsChangeNotifierProvider) - .randomizePIN, - onSubmit: (pin) { - if (!_autoPinCheckLock.isLocked) { - _onSubmitPin(pin); - } + Padding( + padding: const EdgeInsets.only(right: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (ref.read(prefsChangeNotifierProvider).useBiometrics == + true) + CustomTextButton( + text: "Use biometrics", + onTap: () async { + await _checkUseBiometrics(); }, ), - ], - ), + ], ), ), ], ), - ), + ], ), - ); + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Shake( + animationDuration: const Duration(milliseconds: 700), + animationRange: 12, + controller: _shakeController, + child: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + "Enter PIN", + style: STextStyles.pageTitleH1(context), + ), + ), + const SizedBox(height: 52), + CustomPinPut( + fieldsCount: pinCount, + eachFieldHeight: 12, + eachFieldWidth: 12, + textStyle: STextStyles.label( + context, + ).copyWith(fontSize: 1), + focusNode: _pinFocusNode, + controller: _pinTextController, + useNativeKeyboard: false, + obscureText: "", + inputDecoration: InputDecoration( + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + disabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + focusedErrorBorder: InputBorder.none, + fillColor: + Theme.of( + context, + ).extension()!.background, + counterText: "", + ), + submittedFieldDecoration: _pinPutDecoration, + isRandom: + ref.read(prefsChangeNotifierProvider).randomizePIN, + onSubmit: (pin) { + if (!_autoPinCheckLock.isLocked) { + _onSubmitPin(pin); + } + }, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); @override Widget build(BuildContext context) { return widget.showBackButton ? _body : WillPopScope( - onWillPop: () async { - return widget.showBackButton; - }, - child: _body, - ); + onWillPop: () async { + return widget.showBackButton; + }, + child: _body, + ); } } diff --git a/lib/pages/pinpad_views/pinpad_dialog.dart b/lib/pages/pinpad_views/pinpad_dialog.dart index 68dbc144c..f962632d0 100644 --- a/lib/pages/pinpad_views/pinpad_dialog.dart +++ b/lib/pages/pinpad_views/pinpad_dialog.dart @@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mutex/mutex.dart'; import '../../notifications/show_flush_bar.dart'; +import '../../providers/global/duress_provider.dart'; import '../../providers/global/prefs_provider.dart'; import '../../providers/global/secure_store_provider.dart'; import '../../themes/stack_colors.dart'; @@ -15,6 +16,7 @@ import '../../utilities/text_styles.dart'; import '../../widgets/custom_pin_put/custom_pin_put.dart'; import '../../widgets/shake/shake.dart'; import '../../widgets/stack_dialog.dart'; +import 'lock_screen_view.dart'; class PinpadDialog extends ConsumerStatefulWidget { const PinpadDialog({ @@ -74,11 +76,14 @@ class _PinpadDialogState extends ConsumerState { try { if (_autoPin && _pinTextController.text.length >= 4) { - final storedPin = await _secureStore.read(key: 'stack_pin'); + final String? storedPin; + if (ref.read(pDuress)) { + storedPin = await _secureStore.read(key: kDuressPinKey); + } else { + storedPin = await _secureStore.read(key: kPinKey); + } if (_pinTextController.text == storedPin) { - await Future.delayed( - const Duration(milliseconds: 200), - ); + await Future.delayed(const Duration(milliseconds: 200)); unawaited(_onUnlock()); } } @@ -181,22 +186,23 @@ class _PinpadDialogState extends ConsumerState { ), ); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); _pinTextController.text = ''; return; } - final storedPin = await _secureStore.read(key: 'stack_pin'); + final String? storedPin; + if (ref.read(pDuress)) { + storedPin = await _secureStore.read(key: kDuressPinKey); + } else { + storedPin = await _secureStore.read(key: kPinKey); + } if (mounted) { if (storedPin == pin) { - await Future.delayed( - const Duration(milliseconds: 200), - ); + await Future.delayed(const Duration(milliseconds: 200)); unawaited(_onUnlock()); } else { unawaited(_shakeController.shake()); @@ -209,9 +215,7 @@ class _PinpadDialogState extends ConsumerState { ), ); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); _pinTextController.text = ''; } @@ -262,16 +266,12 @@ class _PinpadDialogState extends ConsumerState { style: STextStyles.pageTitleH1(context), ), ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), CustomPinPut( fieldsCount: pinCount, eachFieldHeight: 12, eachFieldWidth: 12, - textStyle: STextStyles.label(context).copyWith( - fontSize: 1, - ), + textStyle: STextStyles.label(context).copyWith(fontSize: 1), focusNode: _pinFocusNode, controller: _pinTextController, useNativeKeyboard: false, @@ -296,9 +296,7 @@ class _PinpadDialogState extends ConsumerState { } }, ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart b/lib/pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart index 57fa710ad..0afaecb7c 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart @@ -8,12 +8,14 @@ * */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../../notifications/show_flush_bar.dart'; -import '../../../../../providers/global/prefs_provider.dart'; import '../../../../../providers/global/secure_store_provider.dart'; +import '../../../../../providers/providers.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../utilities/assets.dart'; import '../../../../../utilities/flutter_secure_storage_interface.dart'; @@ -21,12 +23,11 @@ import '../../../../../utilities/text_styles.dart'; import '../../../../../widgets/background.dart'; import '../../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../../widgets/custom_pin_put/custom_pin_put.dart'; +import '../../../../pinpad_views/lock_screen_view.dart'; import '../security_view.dart'; class ChangePinView extends ConsumerStatefulWidget { - const ChangePinView({ - super.key, - }); + const ChangePinView({super.key}); static const String routeName = "/changePin"; @@ -46,8 +47,10 @@ class _ChangePinViewState extends ConsumerState { ); } - final PageController _pageController = - PageController(initialPage: 0, keepPage: true); + final PageController _pageController = PageController( + initialPage: 0, + keepPage: true, + ); // Attributes for Page 1 of the page view final TextEditingController _pinPutController1 = TextEditingController(); @@ -110,16 +113,12 @@ class _ChangePinViewState extends ConsumerState { style: STextStyles.pageTitleH1(context), ), ), - const SizedBox( - height: 52, - ), + const SizedBox(height: 52), CustomPinPut( fieldsCount: pinCount, eachFieldHeight: 12, eachFieldWidth: 12, - textStyle: STextStyles.label(context).copyWith( - fontSize: 1, - ), + textStyle: STextStyles.label(context).copyWith(fontSize: 1), focusNode: _pinPutFocusNode1, controller: _pinPutController1, useNativeKeyboard: false, @@ -131,9 +130,10 @@ class _ChangePinViewState extends ConsumerState { disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, - fillColor: Theme.of(context) - .extension()! - .background, + fillColor: + Theme.of( + context, + ).extension()!.background, counterText: "", ), isRandom: @@ -161,7 +161,6 @@ class _ChangePinViewState extends ConsumerState { ), // page 2 - Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -171,17 +170,16 @@ class _ChangePinViewState extends ConsumerState { style: STextStyles.pageTitleH1(context), ), ), - const SizedBox( - height: 52, - ), + const SizedBox(height: 52), CustomPinPut( fieldsCount: pinCount, eachFieldHeight: 12, eachFieldWidth: 12, textStyle: STextStyles.infoSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle3, + color: + Theme.of( + context, + ).extension()!.textSubtitle3, fontSize: 1, ), focusNode: _pinPutFocusNode2, @@ -195,9 +193,10 @@ class _ChangePinViewState extends ConsumerState { disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, - fillColor: Theme.of(context) - .extension()! - .background, + fillColor: + Theme.of( + context, + ).extension()!.background, counterText: "", ), isRandom: @@ -207,40 +206,58 @@ class _ChangePinViewState extends ConsumerState { followingFieldDecoration: _pinPutDecoration, onSubmit: (String pin) async { if (_pinPutController1.text == _pinPutController2.text) { - // This should never fail as we are overwriting the existing pin - assert( - (await _secureStore.read(key: "stack_pin")) != null, - ); - await _secureStore.write(key: "stack_pin", value: pin); + final isDuress = ref.read(pDuress); - showFloatingFlushBar( - type: FlushBarType.success, - message: "New PIN is set up", - context: context, - iconAsset: Assets.svg.check, - ); + if (isDuress) { + await _secureStore.write( + key: kDuressPinKey, + value: pin, + ); + } else { + // This should never fail as we are overwriting the existing pin + assert( + (await _secureStore.read(key: kPinKey)) != null, + ); + await _secureStore.write(key: kPinKey, value: pin); + } - await Future.delayed( - const Duration(milliseconds: 1200), - ); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: + "New${isDuress ? " duress" : ""} PIN is set up", + context: context, + iconAsset: Assets.svg.check, + ), + ); - if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(SecurityView.routeName), + await Future.delayed( + const Duration(milliseconds: 1200), ); + + if (context.mounted) { + Navigator.of(context).popUntil( + ModalRoute.withName(SecurityView.routeName), + ); + } } } else { - _pageController.animateTo( - 0, - duration: const Duration(milliseconds: 300), - curve: Curves.linear, + unawaited( + _pageController.animateTo( + 0, + duration: const Duration(milliseconds: 300), + curve: Curves.linear, + ), ); - showFloatingFlushBar( - type: FlushBarType.warning, - message: "PIN codes do not match. Try again.", - context: context, - iconAsset: Assets.svg.alertCircle, + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "PIN codes do not match. Try again.", + context: context, + iconAsset: Assets.svg.alertCircle, + ), ); _pinPutController1.text = ''; diff --git a/lib/pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart b/lib/pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart new file mode 100644 index 000000000..7db6dbd42 --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart @@ -0,0 +1,257 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../../notifications/show_flush_bar.dart'; +import '../../../../../providers/global/prefs_provider.dart'; +import '../../../../../providers/global/secure_store_provider.dart'; +import '../../../../../themes/stack_colors.dart'; +import '../../../../../utilities/assets.dart'; +import '../../../../../utilities/flutter_secure_storage_interface.dart'; +import '../../../../../utilities/text_styles.dart'; +import '../../../../../widgets/background.dart'; +import '../../../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../../../widgets/custom_pin_put/custom_pin_put.dart'; +import '../../../pinpad_views/lock_screen_view.dart'; +import 'security_view.dart'; + +class CreateDuressPinView extends ConsumerStatefulWidget { + const CreateDuressPinView({super.key}); + + static const String routeName = "/createDuressPinView"; + + @override + ConsumerState createState() => + _CreateDuressPinViewState(); +} + +class _CreateDuressPinViewState extends ConsumerState { + BoxDecoration get _pinPutDecoration { + return BoxDecoration( + color: Theme.of(context).extension()!.infoItemIcons, + border: Border.all( + width: 1, + color: Theme.of(context).extension()!.infoItemIcons, + ), + borderRadius: BorderRadius.circular(6), + ); + } + + final PageController _pageController = PageController( + initialPage: 0, + keepPage: true, + ); + + // Attributes for Page 1 of the page view + final TextEditingController _pinPutController1 = TextEditingController(); + final FocusNode _pinPutFocusNode1 = FocusNode(); + + // Attributes for Page 2 of the page view + final TextEditingController _pinPutController2 = TextEditingController(); + final FocusNode _pinPutFocusNode2 = FocusNode(); + + late final SecureStorageInterface _secureStore; + + int pinCount = 1; + + @override + void initState() { + super.initState(); + _secureStore = ref.read(secureStoreProvider); + } + + @override + void dispose() { + _pageController.dispose(); + _pinPutController1.dispose(); + _pinPutController2.dispose(); + _pinPutFocusNode1.dispose(); + _pinPutFocusNode2.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Background( + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 70)); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + body: SafeArea( + child: PageView( + controller: _pageController, + physics: const NeverScrollableScrollPhysics(), + children: [ + // page 1 + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + "Create duress PIN", + style: STextStyles.pageTitleH1(context), + ), + ), + const SizedBox(height: 52), + CustomPinPut( + fieldsCount: pinCount, + eachFieldHeight: 12, + eachFieldWidth: 12, + textStyle: STextStyles.label(context).copyWith(fontSize: 1), + focusNode: _pinPutFocusNode1, + controller: _pinPutController1, + useNativeKeyboard: false, + obscureText: "", + inputDecoration: InputDecoration( + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + disabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + focusedErrorBorder: InputBorder.none, + fillColor: + Theme.of( + context, + ).extension()!.background, + counterText: "", + ), + isRandom: + ref.read(prefsChangeNotifierProvider).randomizePIN, + submittedFieldDecoration: _pinPutDecoration, + selectedFieldDecoration: _pinPutDecoration, + followingFieldDecoration: _pinPutDecoration, + onSubmit: (String pin) { + if (pin.length < 4) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "PIN not long enough!", + iconAsset: Assets.svg.alertCircle, + context: context, + ); + } else { + _pageController.nextPage( + duration: const Duration(milliseconds: 300), + curve: Curves.linear, + ); + } + }, + ), + ], + ), + + // page 2 + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + "Confirm duress PIN", + style: STextStyles.pageTitleH1(context), + ), + ), + const SizedBox(height: 52), + CustomPinPut( + fieldsCount: pinCount, + eachFieldHeight: 12, + eachFieldWidth: 12, + textStyle: STextStyles.infoSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle3, + fontSize: 1, + ), + focusNode: _pinPutFocusNode2, + controller: _pinPutController2, + useNativeKeyboard: false, + obscureText: "", + inputDecoration: InputDecoration( + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + disabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + focusedErrorBorder: InputBorder.none, + fillColor: + Theme.of( + context, + ).extension()!.background, + counterText: "", + ), + isRandom: + ref.read(prefsChangeNotifierProvider).randomizePIN, + submittedFieldDecoration: _pinPutDecoration, + selectedFieldDecoration: _pinPutDecoration, + followingFieldDecoration: _pinPutDecoration, + onSubmit: (String pin) async { + if (_pinPutController1.text == _pinPutController2.text) { + await _secureStore.write( + key: kDuressPinKey, + value: pin, + ); + ref.read(prefsChangeNotifierProvider).hasDuressPin = + true; + + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Duress PIN is set up", + context: context, + iconAsset: Assets.svg.check, + ), + ); + } + + await Future.delayed( + const Duration(milliseconds: 1200), + ); + + if (context.mounted) { + Navigator.of(context).popUntil( + ModalRoute.withName(SecurityView.routeName), + ); + } + } else { + unawaited( + _pageController.animateTo( + 0, + duration: const Duration(milliseconds: 300), + curve: Curves.linear, + ), + ); + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "PIN codes do not match. Try again.", + context: context, + iconAsset: Assets.svg.alertCircle, + ), + ); + + _pinPutController1.text = ''; + _pinPutController2.text = ''; + } + }, + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart index e80374320..7ccfd2650 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart @@ -11,25 +11,192 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../../providers/global/duress_provider.dart'; import '../../../../providers/global/prefs_provider.dart'; +import '../../../../providers/global/secure_store_provider.dart'; import '../../../../route_generator.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; +import '../../../../utilities/logger.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; +import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/rounded_white_container.dart'; +import '../../../../widgets/stack_dialog.dart'; import '../../../pinpad_views/lock_screen_view.dart'; import 'change_pin_view/change_pin_view.dart'; +import 'create_duress_pin_view.dart'; -class SecurityView extends StatelessWidget { - const SecurityView({ - super.key, - }); +class SecurityView extends ConsumerStatefulWidget { + const SecurityView({super.key}); static const String routeName = "/security"; + @override + ConsumerState createState() => _SecurityViewState(); +} + +class _SecurityViewState extends ConsumerState { + bool _lock = false; + + Future _duressToggled(bool newValue) async { + if (_lock) return; + try { + _lock = true; + + if (newValue) { + await _createDuressPin(); + } else { + await _deleteDuressPin(); + } + } finally { + _lock = false; + } + } + + Future _createDuressPin() async { + final result = await showDialog( + context: context, + builder: + (context) => StackDialogBase( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Enable duress PIN", + style: STextStyles.pageTitleH2(context), + ), + const SizedBox(height: 8), + Row( + children: [ + Flexible( + child: Text( + "When unlocking the app with a duress PIN, only wallets" + " marked as visible in duress mode will be loaded and" + " shown. Be aware that providing a duress PIN instead" + " of your real PIN to law enforcement, border agents," + " or other authorities may be considered deception and" + " could carry legal consequences depending on your" + " jurisdiction. Use with care and according to your" + " threat model.", + style: STextStyles.smallMed14(context), + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + onPressed: () => Navigator.of(context).pop(false), + ), + ), + const SizedBox(width: 8), + Expanded( + child: PrimaryButton( + label: "Ok", + onPressed: () => Navigator.of(context).pop(true), + ), + ), + ], + ), + ], + ), + ), + ); + + if (result == true && mounted) { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: CreateDuressPinView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: "Authenticate to create duress PIN", + biometricsAuthenticationTitle: "Create duress PIN", + ), + settings: const RouteSettings(name: "/createDuressPinLockscreen"), + ), + ); + } + } + + Future _deleteDuressPin() async { + await showDialog( + context: context, + builder: + (context) => StackDialogBase( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Disable duress PIN", + style: STextStyles.pageTitleH2(context), + ), + const SizedBox(height: 8), + Row( + children: [ + Flexible( + child: Text( + "Your duress pin will be deleted. " + "You will be asked to create a PIN when you enable this again. " + "Are you sure you want to continue?", + + style: STextStyles.smallMed14(context), + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + onPressed: Navigator.of(context).pop, + ), + ), + const SizedBox(width: 8), + Expanded( + child: PrimaryButton( + label: "Ok", + onPressed: () async { + try { + await ref + .read(secureStoreProvider) + .delete(key: kDuressPinKey); + } catch (e, s) { + Logging.instance.f( + "dpin delete failed!!", + error: e, + stackTrace: s, + ); + } + + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + ], + ), + ], + ), + ), + ); + + ref.read(prefsChangeNotifierProvider).hasDuressPin = false; + } + @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); @@ -43,10 +210,7 @@ class SecurityView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Security", - style: STextStyles.navBarTitle(context), - ), + title: Text("Security", style: STextStyles.navBarTitle(context)), ), body: Padding( padding: const EdgeInsets.all(16), @@ -69,16 +233,18 @@ class SecurityView extends StatelessWidget { RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - routeOnSuccess: ChangePinView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to change PIN", - biometricsAuthenticationTitle: "Change PIN", + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: ChangePinView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to change PIN", + biometricsAuthenticationTitle: "Change PIN", + ), + settings: const RouteSettings( + name: "/changepinlockscreen", ), - settings: - const RouteSettings(name: "/changepinlockscreen"), ), ); }, @@ -99,9 +265,7 @@ class SecurityView extends StatelessWidget { ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -140,8 +304,9 @@ class SecurityView extends StatelessWidget { width: 40, child: DraggableSwitchButton( isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.useBiometrics), + prefsChangeNotifierProvider.select( + (value) => value.useBiometrics, + ), ), onValueChanged: (newValue) { ref @@ -157,9 +322,7 @@ class SecurityView extends StatelessWidget { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -187,8 +350,9 @@ class SecurityView extends StatelessWidget { width: 40, child: DraggableSwitchButton( isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.randomizePIN), + prefsChangeNotifierProvider.select( + (value) => value.randomizePIN, + ), ), onValueChanged: (newValue) { ref @@ -205,9 +369,7 @@ class SecurityView extends StatelessWidget { ), ), // The "autoPin" preference (whether to automatically accept a correct PIN). - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -235,8 +397,9 @@ class SecurityView extends StatelessWidget { width: 40, child: DraggableSwitchButton( isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.autoPin), + prefsChangeNotifierProvider.select( + (value) => value.autoPin, + ), ), onValueChanged: (newValue) { ref @@ -252,6 +415,107 @@ class SecurityView extends StatelessWidget { }, ), ), + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Duress PIN", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + ), + onChanged: _duressToggled, + ), + ), + ], + ), + ), + ); + }, + ), + ), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + const SizedBox(height: 8), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Duress uses biometrics", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.biometricsDuress, + ), + ), + onChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .biometricsDuress = newValue; + }, + ), + ), + ], + ), + ), + ); + }, + ), + ), ], ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index 18b18d9e1..68436c634 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -115,27 +115,26 @@ class _WalletSettingsViewState extends ConsumerState { eventBus = widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; - _syncStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == walletId) { - switch (event.newStatus) { - case WalletSyncStatus.unableToSync: - // TODO: Handle this case. - break; - case WalletSyncStatus.synced: - // TODO: Handle this case. - break; - case WalletSyncStatus.syncing: - // TODO: Handle this case. - break; + _syncStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == walletId) { + switch (event.newStatus) { + case WalletSyncStatus.unableToSync: + // TODO: Handle this case. + break; + case WalletSyncStatus.synced: + // TODO: Handle this case. + break; + case WalletSyncStatus.syncing: + // TODO: Handle this case. + break; + } + setState(() { + _currentSyncStatus = event.newStatus; + }); } - setState(() { - _currentSyncStatus = event.newStatus; - }); - } - }, - ); + }); // _nodeStatusSubscription = // eventBus.on().listen( @@ -189,19 +188,12 @@ class _WalletSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("Settings", style: STextStyles.navBarTitle(context)), ), body: LayoutBuilder( builder: (builderContext, constraints) { return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( @@ -229,9 +221,7 @@ class _WalletSettingsViewState extends ConsumerState { }, ), if (coin is FrostCurrency) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is FrostCurrency) SettingsListButton( iconAssetName: Assets.svg.addressBook2, @@ -244,9 +234,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SettingsListButton( iconAssetName: Assets.svg.node, iconSize: 16, @@ -262,10 +250,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - if (canBackup) - const SizedBox( - height: 8, - ), + if (canBackup) const SizedBox(height: 8), if (canBackup) Consumer( builder: (_, ref, __) { @@ -281,11 +266,10 @@ class _WalletSettingsViewState extends ConsumerState { String myName, String config, String keys, - ({ - String config, - String keys - })? prevGen, - })? frostWalletData; + ({String config, String keys})? + prevGen, + })? + frostWalletData; if (wallet is BitcoinFrostWallet) { final futures = [ wallet.getSerializedKeys(), @@ -294,21 +278,23 @@ class _WalletSettingsViewState extends ConsumerState { wallet.getMultisigConfigPrevGen(), ]; - final results = - await Future.wait(futures); + final results = await Future.wait( + futures, + ); if (results.length == 4) { frostWalletData = ( myName: wallet.frostInfo.myName, config: results[1]!, keys: results[0]!, - prevGen: results[2] == null || - results[3] == null - ? null - : ( - config: results[3]!, - keys: results[2]!, - ), + prevGen: + results[2] == null || + results[3] == null + ? null + : ( + config: results[3]!, + keys: results[2]!, + ), ); } } else { @@ -319,8 +305,9 @@ class _WalletSettingsViewState extends ConsumerState { .isViewOnly) { // TODO: is something needed here? } else { - mnemonic = await wallet - .getMnemonicAsWords(); + mnemonic = + await wallet + .getMnemonicAsWords(); } } } @@ -329,8 +316,9 @@ class _WalletSettingsViewState extends ConsumerState { if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { - keyData = await wallet - .getViewOnlyWalletData(); + keyData = + await wallet + .getViewOnlyWalletData(); } else if (wallet is ExtendedKeysInterface) { keyData = await wallet.getXPrivs(); @@ -350,23 +338,25 @@ class _WalletSettingsViewState extends ConsumerState { shouldUseMaterialRoute: RouteGenerator .useMaterialPageRoute, - builder: (_) => - LockscreenView( - routeOnSuccessArguments: ( - walletId: walletId, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: - MobileKeyDataView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery data", - biometricsAuthenticationTitle: - "View recovery data", - ), + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + ( + walletId: + walletId, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + MobileKeyDataView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery data", + biometricsAuthenticationTitle: + "View recovery data", + ), settings: const RouteSettings( name: "/viewRecoveryDataLockscreen", @@ -380,26 +370,27 @@ class _WalletSettingsViewState extends ConsumerState { shouldUseMaterialRoute: RouteGenerator .useMaterialPageRoute, - builder: (_) => - LockscreenView( - routeOnSuccessArguments: ( - walletId: walletId, - mnemonic: mnemonic ?? [], - frostWalletData: - frostWalletData, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: - WalletBackupView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: - "View recovery phrase", - ), + builder: + (_) => LockscreenView( + routeOnSuccessArguments: ( + walletId: walletId, + mnemonic: + mnemonic ?? [], + frostWalletData: + frostWalletData, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + WalletBackupView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", + ), settings: const RouteSettings( name: "/viewRecoverPhraseLockscreen", @@ -412,9 +403,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SettingsListButton( iconAssetName: Assets.svg.downloadFolder, title: "Wallet settings", @@ -427,9 +416,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), SettingsListButton( iconAssetName: Assets.svg.arrowRotate, title: "Syncing preferences", @@ -439,10 +426,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - if (xPubEnabled) - const SizedBox( - height: 8, - ), + if (xPubEnabled) const SizedBox(height: 8), if (xPubEnabled) Consumer( builder: (_, ref, __) { @@ -454,22 +438,24 @@ class _WalletSettingsViewState extends ConsumerState { delay: const Duration( milliseconds: 800, ), - whileFuture: (ref - .read(pWallets) - .getWallet(walletId) - as ExtendedKeysInterface) - .getXPubs(), + whileFuture: + (ref + .read(pWallets) + .getWallet(walletId) + as ExtendedKeysInterface) + .getXPubs(), context: context, message: "Loading xpubs", rootNavigator: Util.isDesktop, ); if (context.mounted) { - await Navigator.of(context) - .pushNamed( + await Navigator.of( + context, + ).pushNamed( XPubView.routeName, arguments: ( widget.walletId, - xpubData + xpubData, ), ); } @@ -477,10 +463,7 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - if (coin is Firo) - const SizedBox( - height: 8, - ), + if (coin is Firo) const SizedBox(height: 8), if (coin is Firo) Consumer( builder: (_, ref, __) { @@ -493,43 +476,43 @@ class _WalletSettingsViewState extends ConsumerState { useSafeArea: false, barrierDismissible: true, context: context, - builder: (_) => StackOkDialog( - title: - "Are you sure you want to clear " - "${coin.prettyName} electrumx cache?", - onOkPressed: (value) { - result = value; - }, - leftButton: SecondaryButton( - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), + builder: + (_) => StackOkDialog( + title: + "Are you sure you want to clear " + "${coin.prettyName} electrumx cache?", + onOkPressed: (value) { + result = value; + }, + leftButton: SecondaryButton( + label: "Cancel", + onPressed: () { + Navigator.of( + context, + ).pop(); + }, + ), + ), ); if (result == "OK" && context.mounted) { await showLoading( - whileFuture: Future.wait( - [ - Future.delayed( - const Duration( - milliseconds: 1500, - ), + whileFuture: Future.wait([ + Future.delayed( + const Duration( + milliseconds: 1500, ), - DB.instance - .clearSharedTransactionCache( - currency: coin, - ), - if (coin is Firo) - FiroCacheCoordinator - .clearSharedCache( - coin.network, + ), + DB.instance + .clearSharedTransactionCache( + currency: coin, ), - ], - ), + if (coin is Firo) + FiroCacheCoordinator.clearSharedCache( + coin.network, + ), + ]), context: context, message: "Clearing cache...", ); @@ -539,9 +522,7 @@ class _WalletSettingsViewState extends ConsumerState { }, ), if (coin is NanoCurrency) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (coin is NanoCurrency) Consumer( builder: (_, ref, __) { @@ -571,9 +552,7 @@ class _WalletSettingsViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), const Spacer(), Consumer( builder: (_, ref, __) { @@ -598,9 +577,10 @@ class _WalletSettingsViewState extends ConsumerState { child: Text( "Log out", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ); @@ -621,10 +601,7 @@ class _WalletSettingsViewState extends ConsumerState { } class EpicBoxInfoForm extends ConsumerStatefulWidget { - const EpicBoxInfoForm({ - super.key, - required this.walletId, - }); + const EpicBoxInfoForm({super.key, required this.walletId}); final String walletId; @@ -668,9 +645,7 @@ class _EpiBoxInfoFormState extends ConsumerState { controller: hostController, decoration: const InputDecoration(hintText: "Host"), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -679,9 +654,7 @@ class _EpiBoxInfoFormState extends ConsumerState { keyboardType: Util.isDesktop ? null : const TextInputType.numberWithOptions(), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), TextButton( onPressed: () async { try { diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index c689baf30..3917f743e 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -12,11 +12,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../models/keys/view_only_wallet_data.dart'; -import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../route_generator.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; +import '../../../../utilities/logger.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/isar/models/wallet_info.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; @@ -40,10 +40,7 @@ import 'rename_wallet_view.dart'; import 'spark_info.dart'; class WalletSettingsWalletSettingsView extends ConsumerStatefulWidget { - const WalletSettingsWalletSettingsView({ - super.key, - required this.walletId, - }); + const WalletSettingsWalletSettingsView({super.key, required this.walletId}); static const String routeName = "/walletSettingsWalletSettings"; @@ -58,6 +55,34 @@ class _WalletSettingsWalletSettingsViewState extends ConsumerState { late final DSBController _switchController; + bool _switchDuressToggleLock = false; // Mutex. + Future _switchDuressToggled() async { + if (_switchDuressToggleLock) { + return; + } + _switchDuressToggleLock = true; // Lock mutex. + + try { + final visibility = ref.read(pWalletInfo(widget.walletId)).isDuressVisible; + + await ref + .read(pWalletInfo(widget.walletId)) + .updateDuressVisibilityStatus( + isDuressVisible: !visibility, + isar: ref.read(mainDBProvider).isar, + ); + } catch (e, s) { + Logging.instance.f( + "Failed to update duress visibility for wallet", + error: e, + stackTrace: s, + ); + } finally { + // ensure _switchDuressToggleLock is set to false no matter what. + _switchDuressToggleLock = false; + } + } + bool _switchReuseAddressToggledLock = false; // Mutex. Future _switchReuseAddressToggled() async { if (_switchReuseAddressToggledLock) { @@ -90,10 +115,7 @@ class _WalletSettingsWalletSettingsViewState style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Continue", - style: STextStyles.button(context), - ), + child: Text("Continue", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -115,12 +137,12 @@ class _WalletSettingsWalletSettingsViewState } Future _updateAddressReuse(bool shouldReuse) async { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: shouldReuse, - }, - isar: ref.read(mainDBProvider).isar, - ); + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.reuseAddress: shouldReuse}, + isar: ref.read(mainDBProvider).isar, + ); if (_switchController.isOn != null) { if (_switchController.isOn!.call() != shouldReuse) { @@ -139,7 +161,8 @@ class _WalletSettingsWalletSettingsViewState Widget build(BuildContext context) { final wallet = ref.watch(pWallets).getWallet(widget.walletId); - final isViewOnlyNoAddressGen = wallet is ViewOnlyOptionInterface && + final isViewOnlyNoAddressGen = + wallet is ViewOnlyOptionInterface && wallet.isViewOnly && wallet.viewOnlyType == ViewOnlyWalletType.addressOnly; @@ -158,11 +181,7 @@ class _WalletSettingsWalletSettingsViewState ), ), body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -199,10 +218,7 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is RbfInterface) - const SizedBox( - height: 8, - ), + if (wallet is RbfInterface) const SizedBox(height: 8), if (wallet is RbfInterface) RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -236,9 +252,7 @@ class _WalletSettingsWalletSettingsViewState ), ), if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -269,11 +283,13 @@ class _WalletSettingsWalletSettingsViewState width: 40, child: IgnorePointer( child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData, - ), - )[WalletInfoKeys.reuseAddress] as bool? ?? + isOn: + ref.watch( + pWalletInfo(widget.walletId).select( + (value) => value.otherData, + ), + )[WalletInfoKeys.reuseAddress] + as bool? ?? false, controller: _switchController, ), @@ -284,10 +300,56 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is LelantusInterface && !wallet.isViewOnly) - const SizedBox( - height: 8, + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: _switchDuressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Show in duress", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitch( + value: + ref.watch( + pWalletInfo(widget.walletId).select( + (value) => value.otherData, + ), + )[WalletInfoKeys + .duressMarkedVisibleWalletKey] + as bool? ?? + false, + onChanged: (_) => (), + ), + ), + ), + ], + ), + ), + ), ), + if (wallet is LelantusInterface && !wallet.isViewOnly) + const SizedBox(height: 8), if (wallet is LelantusInterface && !wallet.isViewOnly) RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -321,9 +383,7 @@ class _WalletSettingsWalletSettingsViewState ), ), if (wallet is SparkInterface && !wallet.isViewOnly) - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), if (wallet is SparkInterface && !wallet.isViewOnly) RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -356,10 +416,7 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is LibMoneroWallet) - const SizedBox( - height: 8, - ), + if (wallet is LibMoneroWallet) const SizedBox(height: 8), if (wallet is LibMoneroWallet) RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -392,9 +449,7 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( @@ -410,59 +465,65 @@ class _WalletSettingsWalletSettingsViewState showDialog( barrierDismissible: true, context: context, - builder: (_) => StackDialog( - title: - "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) + builder: + (_) => StackDialog( + title: + "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", + leftButton: TextButton( + style: Theme.of(context) .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: widget.walletId, - showBackButton: true, - routeOnSuccess: - DeleteWalletWarningView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: - "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen", + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen", + ), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), ), - ), - ), ); }, child: Padding( diff --git a/lib/providers/global/duress_provider.dart b/lib/providers/global/duress_provider.dart new file mode 100644 index 000000000..f6e84011c --- /dev/null +++ b/lib/providers/global/duress_provider.dart @@ -0,0 +1,4 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final pDuress = StateProvider((ref) => true); + diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart index 0f2f12343..90e0ced3a 100644 --- a/lib/providers/providers.dart +++ b/lib/providers/providers.dart @@ -19,6 +19,7 @@ export './exchange/exchange_form_state_provider.dart'; export './exchange/exchange_send_from_wallet_id_provider.dart'; export './exchange/trade_note_service_provider.dart'; export './exchange/trade_sent_from_stack_lookup_provider.dart'; +export './global/duress_provider.dart'; export './global/locale_provider.dart'; export './global/node_service_provider.dart'; export './global/notifications_provider.dart'; diff --git a/lib/route_generator.dart b/lib/route_generator.dart index fb0e79c86..65f2df473 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -114,6 +114,7 @@ import 'pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_ import 'pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart'; import 'pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart'; import 'pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart'; +import 'pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart'; import 'pages/settings_views/global_settings_view/security_views/security_view.dart'; import 'pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart'; import 'pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart'; @@ -975,6 +976,13 @@ class RouteGenerator { settings: RouteSettings(name: settings.name), ); + case CreateDuressPinView.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const CreateDuressPinView(), + settings: RouteSettings(name: settings.name), + ); + case BaseCurrencySettingsView.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, diff --git a/lib/services/wallets.dart b/lib/services/wallets.dart index 07856e6ee..d47c7b66b 100644 --- a/lib/services/wallets.dart +++ b/lib/services/wallets.dart @@ -152,10 +152,10 @@ class Wallets { } } - Future load(Prefs prefs, MainDB mainDB) async { + Future load(Prefs prefs, MainDB mainDB, bool isDuress) async { // return await _loadV1(prefs, mainDB); // return await _loadV2(prefs, mainDB); - return await _loadV3(prefs, mainDB); + return await _loadV3(prefs, mainDB, isDuress); } Future _loadV1(Prefs prefs, MainDB mainDB) async { @@ -165,18 +165,21 @@ class Wallets { hasLoaded = true; // clear out any wallet hive boxes where the wallet was deleted in previous app run - for (final walletId in DB.instance - .values(boxName: DB.boxNameWalletsToDeleteOnStart)) { + for (final walletId in DB.instance.values( + boxName: DB.boxNameWalletsToDeleteOnStart, + )) { await mainDB.isar.writeTxn( - () async => await mainDB.isar.walletInfo - .where() - .walletIdEqualTo(walletId) - .deleteAll(), + () async => + await mainDB.isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .deleteAll(), ); } // clear list - await DB.instance - .deleteAll(boxName: DB.boxNameWalletsToDeleteOnStart); + await DB.instance.deleteAll( + boxName: DB.boxNameWalletsToDeleteOnStart, + ); final walletInfoList = await mainDB.isar.walletInfo.where().findAll(); if (walletInfoList.isEmpty) { @@ -204,9 +207,10 @@ class Wallets { for (final walletInfo in walletInfoList) { try { final isVerified = await walletInfo.isMnemonicVerified(mainDB.isar); - Logging.instance - .d("LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " - "IS VERIFIED: $isVerified"); + Logging.instance.d( + "LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " + "IS VERIFIED: $isVerified", + ); if (isVerified) { // TODO: integrate this into the new wallets somehow? @@ -222,7 +226,8 @@ class Wallets { prefs: prefs, ); - final shouldSetAutoSync = shouldAutoSyncAll || + final shouldSetAutoSync = + shouldAutoSyncAll || walletIdsToEnableAutoSync.contains(walletInfo.walletId); if (wallet is LibMoneroWallet) { @@ -269,18 +274,21 @@ class Wallets { hasLoaded = true; // clear out any wallet hive boxes where the wallet was deleted in previous app run - for (final walletId in DB.instance - .values(boxName: DB.boxNameWalletsToDeleteOnStart)) { + for (final walletId in DB.instance.values( + boxName: DB.boxNameWalletsToDeleteOnStart, + )) { await mainDB.isar.writeTxn( - () async => await mainDB.isar.walletInfo - .where() - .walletIdEqualTo(walletId) - .deleteAll(), + () async => + await mainDB.isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .deleteAll(), ); } // clear list - await DB.instance - .deleteAll(boxName: DB.boxNameWalletsToDeleteOnStart); + await DB.instance.deleteAll( + boxName: DB.boxNameWalletsToDeleteOnStart, + ); final walletInfoList = await mainDB.isar.walletInfo.where().findAll(); if (walletInfoList.isEmpty) { @@ -309,9 +317,10 @@ class Wallets { for (final walletInfo in walletInfoList) { try { final isVerified = await walletInfo.isMnemonicVerified(mainDB.isar); - Logging.instance - .d("LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " - "IS VERIFIED: $isVerified"); + Logging.instance.d( + "LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " + "IS VERIFIED: $isVerified", + ); if (isVerified) { // TODO: integrate this into the new wallets somehow? @@ -345,11 +354,7 @@ class Wallets { deleteFutures.add(_deleteWallet(walletInfo.walletId)); } } catch (e, s) { - Logging.instance.w( - "$e $s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e $s", error: e, stackTrace: s); continue; } } @@ -357,17 +362,17 @@ class Wallets { final asyncWalletIds = await Future.wait(walletIDInitFutures); asyncWalletIds.removeWhere((e) => e == "dummy_ignore"); - final List> walletInitFutures = asyncWalletIds - .map( - (id) => _wallets[id]!.init().then( - (_) { - if (shouldAutoSyncAll || walletIdsToEnableAutoSync.contains(id)) { - _wallets[id]!.shouldAutoSync = true; - } - }, - ), - ) - .toList(); + final List> walletInitFutures = + asyncWalletIds + .map( + (id) => _wallets[id]!.init().then((_) { + if (shouldAutoSyncAll || + walletIdsToEnableAutoSync.contains(id)) { + _wallets[id]!.shouldAutoSync = true; + } + }), + ) + .toList(); if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) { unawaited( @@ -387,34 +392,43 @@ class Wallets { } /// should be best performance - Future _loadV3(Prefs prefs, MainDB mainDB) async { + Future _loadV3(Prefs prefs, MainDB mainDB, bool isDuress) async { if (hasLoaded) { return; } hasLoaded = true; // clear out any wallet hive boxes where the wallet was deleted in previous app run - for (final walletId in DB.instance - .values(boxName: DB.boxNameWalletsToDeleteOnStart)) { + for (final walletId in DB.instance.values( + boxName: DB.boxNameWalletsToDeleteOnStart, + )) { await mainDB.isar.writeTxn( - () async => await mainDB.isar.walletInfo - .where() - .walletIdEqualTo(walletId) - .deleteAll(), + () async => + await mainDB.isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .deleteAll(), ); } // clear list - await DB.instance - .deleteAll(boxName: DB.boxNameWalletsToDeleteOnStart); - - final walletInfoList = await mainDB.isar.walletInfo - .where() - .filter() - .anyOf( - AppConfig.coins.map((e) => e.identifier), - (q, element) => q.coinNameMatches(element), - ) - .findAll(); + await DB.instance.deleteAll( + boxName: DB.boxNameWalletsToDeleteOnStart, + ); + + final walletInfoList = + await mainDB.isar.walletInfo + .where() + .filter() + .anyOf( + AppConfig.coins.map((e) => e.identifier), + (q, element) => q.coinNameMatches(element), + ) + .findAll(); + + if (isDuress) { + walletInfoList.retainWhere((e) => e.isDuressVisible); + } + if (walletInfoList.isEmpty) { return; } @@ -441,9 +455,10 @@ class Wallets { for (final walletInfo in walletInfoList) { try { final isVerified = await walletInfo.isMnemonicVerified(mainDB.isar); - Logging.instance - .d("LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " - "IS VERIFIED: $isVerified"); + Logging.instance.d( + "LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} " + "IS VERIFIED: $isVerified", + ); if (isVerified) { // TODO: integrate this into the new wallets somehow? @@ -477,11 +492,7 @@ class Wallets { deleteFutures.add(_deleteWallet(walletInfo.walletId)); } } catch (e, s) { - Logging.instance.w( - "$e $s", - error: e, - stackTrace: s, - ); + Logging.instance.w("$e $s", error: e, stackTrace: s); continue; } } @@ -490,24 +501,21 @@ class Wallets { asyncWalletIds.removeWhere((e) => e == "dummy_ignore"); final List idsToRefresh = []; - final List> walletInitFutures = asyncWalletIds - .map( - (id) => _wallets[id]!.init().then( - (_) { - if (shouldSyncAllOnceOnStartup || - walletIdsToSyncOnceOnStartup.contains(id)) { - idsToRefresh.add(id); - } - }, - ), - ) - .toList(); + final List> walletInitFutures = + asyncWalletIds + .map( + (id) => _wallets[id]!.init().then((_) { + if (shouldSyncAllOnceOnStartup || + walletIdsToSyncOnceOnStartup.contains(id)) { + idsToRefresh.add(id); + } + }), + ) + .toList(); Future _refreshFutures(List idsToRefresh) async { final start = DateTime.now(); - Logging.instance.d( - "Initial refresh start: ${start.toUtc()}", - ); + Logging.instance.d("Initial refresh start: ${start.toUtc()}"); const groupCount = 3; for (int i = 0; i < idsToRefresh.length; i += groupCount) { final List> futures = []; @@ -515,14 +523,13 @@ class Wallets { if (i + j >= idsToRefresh.length) { break; } - futures.add( - _wallets[idsToRefresh[i + j]]!.refresh(), - ); + futures.add(_wallets[idsToRefresh[i + j]]!.refresh()); } await Future.wait(futures); } - Logging.instance - .d("Initial refresh duration: ${DateTime.now().difference(start)}"); + Logging.instance.d( + "Initial refresh duration: ${DateTime.now().difference(start)}", + ); } if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) { @@ -530,15 +537,13 @@ class Wallets { Future.wait([ _initLinearly(walletsToInitLinearly), ...walletInitFutures, - ]).then( - (value) => _refreshFutures(idsToRefresh), - ), + ]).then((value) => _refreshFutures(idsToRefresh)), ); } else if (walletInitFutures.isNotEmpty) { unawaited( - Future.wait(walletInitFutures).then( - (value) => _refreshFutures(idsToRefresh), - ), + Future.wait( + walletInitFutures, + ).then((value) => _refreshFutures(idsToRefresh)), ); } else if (walletsToInitLinearly.isNotEmpty) { unawaited(_initLinearly(walletsToInitLinearly)); @@ -578,7 +583,8 @@ class Wallets { ); if (isVerified) { - final shouldSetAutoSync = shouldAutoSyncAll || + final shouldSetAutoSync = + shouldAutoSyncAll || walletIdsToEnableAutoSync.contains(wallet.walletId); if (isDesktop) { diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 395e5ecd6..a436c8483 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -41,6 +41,8 @@ class Prefs extends ChangeNotifier { _randomizePIN = await _getRandomizePIN(); _useBiometrics = await _getUseBiometrics(); _hasPin = await _getHasPin(); + _hasDuressPin = await _getHasDuressPin(); + _biometricsDuress = await _getBiometricsDuress(); _language = await _getPreferredLanguage(); _showFavoriteWallets = await _getShowFavoriteWallets(); _wifiOnly = await _getUseWifiOnly(); @@ -101,9 +103,10 @@ class Prefs extends ChangeNotifier { Future _getLastUnlockedTimeout() async { return (DB.instance.get( - boxName: DB.boxNamePrefs, - key: "lastUnlockedTimeout", - )) as int? ?? + boxName: DB.boxNamePrefs, + key: "lastUnlockedTimeout", + )) + as int? ?? 60; } @@ -127,9 +130,10 @@ class Prefs extends ChangeNotifier { Future _getLastUnlocked() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "lastUnlocked", - ) as int? ?? + boxName: DB.boxNamePrefs, + key: "lastUnlocked", + ) + as int? ?? 0; } @@ -155,9 +159,10 @@ class Prefs extends ChangeNotifier { Future _getCurrentNotificationIndex() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "currentNotificationId", - ) as int? ?? + boxName: DB.boxNamePrefs, + key: "currentNotificationId", + ) + as int? ?? 0; } @@ -180,10 +185,12 @@ class Prefs extends ChangeNotifier { } Future> _getWalletIdsSyncOnStartup() async { - final list = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "walletIdsSyncOnStartup", - ) as List? ?? + final list = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "walletIdsSyncOnStartup", + ) + as List? ?? []; return List.from(list); } @@ -207,10 +214,12 @@ class Prefs extends ChangeNotifier { } Future _getSyncType() async { - final int index = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "syncTypeIndex", - ) as int? ?? + final int index = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "syncTypeIndex", + ) + as int? ?? SyncingType.allWalletsOnStartup.index; return SyncingType.values[index]; } @@ -234,8 +243,11 @@ class Prefs extends ChangeNotifier { } Future _getUseWifiOnly() async { - return await DB.instance - .get(boxName: DB.boxNamePrefs, key: "wifiOnly") as bool? ?? + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "wifiOnly", + ) + as bool? ?? false; } @@ -259,9 +271,10 @@ class Prefs extends ChangeNotifier { Future _getShowFavoriteWallets() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "showFavoriteWallets", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "showFavoriteWallets", + ) + as bool? ?? true; } @@ -285,9 +298,10 @@ class Prefs extends ChangeNotifier { Future _getPreferredLanguage() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "language", - ) as String? ?? + boxName: DB.boxNamePrefs, + key: "language", + ) + as String? ?? Language.englishUS.description; } @@ -311,9 +325,10 @@ class Prefs extends ChangeNotifier { Future _getPreferredCurrency() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "currency", - ) as String? ?? + boxName: DB.boxNamePrefs, + key: "currency", + ) + as String? ?? "USD"; } @@ -378,9 +393,10 @@ class Prefs extends ChangeNotifier { Future _getRandomizePIN() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "randomizePIN", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "randomizePIN", + ) + as bool? ?? false; } @@ -404,9 +420,10 @@ class Prefs extends ChangeNotifier { Future _getUseBiometrics() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "useBiometrics", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "useBiometrics", + ) + as bool? ?? false; } @@ -418,16 +435,76 @@ class Prefs extends ChangeNotifier { set hasPin(bool hasPin) { if (_hasPin != hasPin) { - DB.instance - .put(boxName: DB.boxNamePrefs, key: "hasPin", value: hasPin); + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "hasPin", + value: hasPin, + ); _hasPin = hasPin; notifyListeners(); } } Future _getHasPin() async { - return await DB.instance - .get(boxName: DB.boxNamePrefs, key: "hasPin") as bool? ?? + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "hasPin", + ) + as bool? ?? + false; + } + + // has set up pin + + bool _hasDuressPin = false; + + bool get hasDuressPin => _hasDuressPin; + + set hasDuressPin(bool hasDuressPin) { + if (_hasDuressPin != hasDuressPin) { + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "hasDuressPin", + value: hasDuressPin, + ); + _hasDuressPin = hasDuressPin; + notifyListeners(); + } + } + + Future _getHasDuressPin() async { + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "hasDuressPin", + ) + as bool? ?? + false; + } + + // has toggled biometrics to act for duress instead of normal auth + + bool _biometricsDuress = false; + + bool get biometricsDuress => _biometricsDuress; + + set biometricsDuress(bool biometricsDuress) { + if (_biometricsDuress != biometricsDuress) { + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "biometricsDuress", + value: biometricsDuress, + ); + _biometricsDuress = biometricsDuress; + notifyListeners(); + } + } + + Future _getBiometricsDuress() async { + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "biometricsDuress", + ) + as bool? ?? false; } @@ -451,9 +528,10 @@ class Prefs extends ChangeNotifier { Future _getHasFamiliarity() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "familiarity", - ) as int? ?? + boxName: DB.boxNamePrefs, + key: "familiarity", + ) + as int? ?? 0; } @@ -477,9 +555,10 @@ class Prefs extends ChangeNotifier { Future _getTorKillswitch() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "torKillswitch", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "torKillswitch", + ) + as bool? ?? true; } @@ -503,9 +582,10 @@ class Prefs extends ChangeNotifier { Future _getShowTestNetCoins() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "showTestNetCoins", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "showTestNetCoins", + ) + as bool? ?? false; } @@ -519,22 +599,23 @@ class Prefs extends ChangeNotifier { if (_isAutoBackupEnabled != isAutoBackupEnabled) { DB.instance .put( - boxName: DB.boxNamePrefs, - key: "isAutoBackupEnabled", - value: isAutoBackupEnabled, - ) + boxName: DB.boxNamePrefs, + key: "isAutoBackupEnabled", + value: isAutoBackupEnabled, + ) .then((_) { - _isAutoBackupEnabled = isAutoBackupEnabled; - notifyListeners(); - }); + _isAutoBackupEnabled = isAutoBackupEnabled; + notifyListeners(); + }); } } Future _getIsAutoBackupEnabled() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "isAutoBackupEnabled", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "isAutoBackupEnabled", + ) + as bool? ?? false; } @@ -558,9 +639,10 @@ class Prefs extends ChangeNotifier { Future _getAutoBackupLocation() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "autoBackupLocation", - ) as String?; + boxName: DB.boxNamePrefs, + key: "autoBackupLocation", + ) + as String?; } // auto backup frequency type @@ -601,10 +683,12 @@ class Prefs extends ChangeNotifier { } Future _getBackupFrequencyType() async { - String? rate = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "backupFrequencyType", - ) as String?; + String? rate = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "backupFrequencyType", + ) + as String?; rate ??= "10Min"; switch (rate) { case "10Min": @@ -638,9 +722,10 @@ class Prefs extends ChangeNotifier { Future _getLastAutoBackup() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "autoBackupFileUri", - ) as DateTime?; + boxName: DB.boxNamePrefs, + key: "autoBackupFileUri", + ) + as DateTime?; } // auto backup @@ -653,22 +738,23 @@ class Prefs extends ChangeNotifier { if (_hideBlockExplorerWarning != hideBlockExplorerWarning) { DB.instance .put( - boxName: DB.boxNamePrefs, - key: "hideBlockExplorerWarning", - value: hideBlockExplorerWarning, - ) + boxName: DB.boxNamePrefs, + key: "hideBlockExplorerWarning", + value: hideBlockExplorerWarning, + ) .then((_) { - _hideBlockExplorerWarning = hideBlockExplorerWarning; - notifyListeners(); - }); + _hideBlockExplorerWarning = hideBlockExplorerWarning; + notifyListeners(); + }); } } Future _getHideBlockExplorerWarning() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "hideBlockExplorerWarning", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "hideBlockExplorerWarning", + ) + as bool? ?? false; } @@ -682,22 +768,23 @@ class Prefs extends ChangeNotifier { if (_gotoWalletOnStartup != gotoWalletOnStartup) { DB.instance .put( - boxName: DB.boxNamePrefs, - key: "gotoWalletOnStartup", - value: gotoWalletOnStartup, - ) + boxName: DB.boxNamePrefs, + key: "gotoWalletOnStartup", + value: gotoWalletOnStartup, + ) .then((_) { - _gotoWalletOnStartup = gotoWalletOnStartup; - notifyListeners(); - }); + _gotoWalletOnStartup = gotoWalletOnStartup; + notifyListeners(); + }); } } Future _getGotoWalletOnStartup() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "gotoWalletOnStartup", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "gotoWalletOnStartup", + ) + as bool? ?? false; } @@ -721,9 +808,10 @@ class Prefs extends ChangeNotifier { Future _getStartupWalletId() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "startupWalletId", - ) as String?; + boxName: DB.boxNamePrefs, + key: "startupWalletId", + ) + as String?; } // incognito mode off by default @@ -736,28 +824,31 @@ class Prefs extends ChangeNotifier { if (_externalCalls != externalCalls) { DB.instance .put( - boxName: DB.boxNamePrefs, - key: "externalCalls", - value: externalCalls, - ) + boxName: DB.boxNamePrefs, + key: "externalCalls", + value: externalCalls, + ) .then((_) { - _externalCalls = externalCalls; - notifyListeners(); - }); + _externalCalls = externalCalls; + notifyListeners(); + }); } } Future _getHasExternalCalls() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "externalCalls", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "externalCalls", + ) + as bool? ?? true; } Future isExternalCallsSet() async { - if (await DB.instance - .get(boxName: DB.boxNamePrefs, key: "externalCalls") == + if (await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "externalCalls", + ) == null) { return false; } @@ -768,8 +859,9 @@ class Prefs extends ChangeNotifier { String? get userID => _userId; Future _getUserId() async { - String? userID = await DB.instance - .get(boxName: DB.boxNamePrefs, key: "userID") as String?; + String? userID = + await DB.instance.get(boxName: DB.boxNamePrefs, key: "userID") + as String?; if (userID == null) { userID = const Uuid().v4(); await saveUserID(userID); @@ -779,8 +871,11 @@ class Prefs extends ChangeNotifier { Future saveUserID(String userId) async { _userId = userId; - await DB.instance - .put(boxName: DB.boxNamePrefs, key: "userID", value: _userId); + await DB.instance.put( + boxName: DB.boxNamePrefs, + key: "userID", + value: _userId, + ); // notifyListeners(); } @@ -788,10 +883,15 @@ class Prefs extends ChangeNotifier { int? get signupEpoch => _signupEpoch; Future _getSignupEpoch() async { - int? signupEpoch = await DB.instance - .get(boxName: DB.boxNamePrefs, key: "signupEpoch") as int?; + int? signupEpoch = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "signupEpoch", + ) + as int?; if (signupEpoch == null) { - signupEpoch = DateTime.now().millisecondsSinceEpoch ~/ + signupEpoch = + DateTime.now().millisecondsSinceEpoch ~/ Duration.millisecondsPerSecond; await saveSignupEpoch(signupEpoch); } @@ -828,9 +928,10 @@ class Prefs extends ChangeNotifier { Future _getEnableCoinControl() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "enableCoinControl", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "enableCoinControl", + ) + as bool? ?? false; } @@ -854,9 +955,10 @@ class Prefs extends ChangeNotifier { Future _getEnableSystemBrightness() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "enableSystemBrightness", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "enableSystemBrightness", + ) + as bool? ?? false; } @@ -880,9 +982,10 @@ class Prefs extends ChangeNotifier { Future _getThemeId() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "themeId", - ) as String? ?? + boxName: DB.boxNamePrefs, + key: "themeId", + ) + as String? ?? "light"; } @@ -906,9 +1009,10 @@ class Prefs extends ChangeNotifier { Future _getSystemBrightnessLightThemeId() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "systemBrightnessLightThemeId", - ) as String? ?? + boxName: DB.boxNamePrefs, + key: "systemBrightnessLightThemeId", + ) + as String? ?? "light"; } @@ -932,9 +1036,10 @@ class Prefs extends ChangeNotifier { Future _getSystemBrightnessDarkTheme() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "systemBrightnessDarkThemeId", - ) as String? ?? + boxName: DB.boxNamePrefs, + key: "systemBrightnessDarkThemeId", + ) + as String? ?? "dark"; } @@ -962,10 +1067,12 @@ class Prefs extends ChangeNotifier { Future _setAmountUnits() async { for (final coin in AppConfig.coins) { - final unitIndex = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "amountUnitFor${coin.identifier}", - ) as int? ?? + final unitIndex = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "amountUnitFor${coin.identifier}", + ) + as int? ?? 0; // 0 is "normal" _amountUnits[coin] = AmountUnit.values[unitIndex]; } @@ -995,10 +1102,12 @@ class Prefs extends ChangeNotifier { Future _setMaxDecimals() async { for (final coin in AppConfig.coins) { - final decimals = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "maxDecimalsFor${coin.identifier}", - ) as int? ?? + final decimals = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "maxDecimalsFor${coin.identifier}", + ) + as int? ?? (coin.fractionDigits > 18 ? 18 : coin.fractionDigits); // use some sane max rather than up to 30 that nano uses _amountDecimals[coin.identifier] = decimals; @@ -1031,9 +1140,10 @@ class Prefs extends ChangeNotifier { Future _getUseTor() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "useTor", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "useTor", + ) + as bool? ?? false; } @@ -1054,10 +1164,7 @@ class Prefs extends ChangeNotifier { boxName: DB.boxNamePrefs, key: "fusionServerInfoMap", value: _fusionServerInfo.map( - (key, value) => MapEntry( - key, - value.toJsonString(), - ), + (key, value) => MapEntry(key, value.toJsonString()), ), ); notifyListeners(); @@ -1065,29 +1172,30 @@ class Prefs extends ChangeNotifier { } Future> _getFusionServerInfo() async { - final map = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "fusionServerInfoMap", - ) as Map?; + final map = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "fusionServerInfoMap", + ) + as Map?; if (map == null) { return _fusionServerInfo; } - final actualMap = Map.from(map).map( - (key, value) => MapEntry( - key, - FusionInfo.fromJsonString(value), - ), - ); + final actualMap = Map.from( + map, + ).map((key, value) => MapEntry(key, FusionInfo.fromJsonString(value))); // legacy bch check if (actualMap["bitcoincash"] == null || actualMap["bitcoincashTestnet"] == null) { - final saved = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "fusionServerInfo", - ) as String?; + final saved = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "fusionServerInfo", + ) + as String?; if (saved != null) { final bchInfo = FusionInfo.fromJsonString(saved); @@ -1098,10 +1206,7 @@ class Prefs extends ChangeNotifier { boxName: DB.boxNamePrefs, key: "fusionServerInfoMap", value: actualMap.map( - (key, value) => MapEntry( - key, - value.toJsonString(), - ), + (key, value) => MapEntry(key, value.toJsonString()), ), ), ); @@ -1131,9 +1236,10 @@ class Prefs extends ChangeNotifier { Future _getAutoPin() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "autoPin", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "autoPin", + ) + as bool? ?? false; } @@ -1157,9 +1263,10 @@ class Prefs extends ChangeNotifier { Future _getEnableExchange() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "showExchange", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "showExchange", + ) + as bool? ?? true; } @@ -1180,9 +1287,10 @@ class Prefs extends ChangeNotifier { Future _getAdvancedFiroFeatures() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "advancedFiroFeatures", - ) as bool? ?? + boxName: DB.boxNamePrefs, + key: "advancedFiroFeatures", + ) + as bool? ?? false; } @@ -1203,9 +1311,10 @@ class Prefs extends ChangeNotifier { Future _getLogsPath() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "logsPath", - ) as String?; + boxName: DB.boxNamePrefs, + key: "logsPath", + ) + as String?; } // log level pref @@ -1224,10 +1333,12 @@ class Prefs extends ChangeNotifier { } Future _getLogLevel() async { - final value = await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "logLevel", - ) as int?; + final value = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "logLevel", + ) + as int?; try { return Level.values.firstWhere((e) => e.value == value); diff --git a/lib/wallets/isar/models/wallet_info.dart b/lib/wallets/isar/models/wallet_info.dart index 779f1dd78..f943ea5aa 100644 --- a/lib/wallets/isar/models/wallet_info.dart +++ b/lib/wallets/isar/models/wallet_info.dart @@ -114,9 +114,10 @@ class WalletInfo implements IsarId { } @ignore - Map get otherData => otherDataJsonString == null - ? {} - : Map.from(jsonDecode(otherDataJsonString!) as Map); + Map get otherData => + otherDataJsonString == null + ? {} + : Map.from(jsonDecode(otherDataJsonString!) as Map); @ignore bool get isViewOnly => @@ -134,9 +135,25 @@ class WalletInfo implements IsarId { ?.isMnemonicVerified == true; + @ignore + bool get isDuressVisible => + otherData[WalletInfoKeys.duressMarkedVisibleWalletKey] as bool? ?? false; + //============================================================================ //============= Updaters ================================================ + Future updateDuressVisibilityStatus({ + required bool isDuressVisible, + required Isar isar, + }) async { + await updateOtherData( + newEntries: { + WalletInfoKeys.duressMarkedVisibleWalletKey: isDuressVisible, + }, + isar: isar, + ); + } + Future updateBalance({ required Balance newBalance, required Isar isar, @@ -151,9 +168,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - cachedBalanceString: newEncoded, - ), + thisInfo.copyWith(cachedBalanceString: newEncoded), ); }); } @@ -173,9 +188,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - cachedBalanceSecondaryString: newEncoded, - ), + thisInfo.copyWith(cachedBalanceSecondaryString: newEncoded), ); }); } @@ -195,9 +208,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - cachedBalanceTertiaryString: newEncoded, - ), + thisInfo.copyWith(cachedBalanceTertiaryString: newEncoded), ); }); } @@ -215,9 +226,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - cachedChainHeight: newHeight, - ), + thisInfo.copyWith(cachedChainHeight: newHeight), ); }); } @@ -235,11 +244,12 @@ class WalletInfo implements IsarId { if (customIndexOverride != null) { index = customIndexOverride; } else if (flag) { - final highest = await isar.walletInfo - .where() - .sortByFavouriteOrderIndexDesc() - .favouriteOrderIndexProperty() - .findFirst(); + final highest = + await isar.walletInfo + .where() + .sortByFavouriteOrderIndexDesc() + .favouriteOrderIndexProperty() + .findFirst(); index = (highest ?? 0) + 1; } else { index = -1; @@ -253,19 +263,14 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - favouriteOrderIndex: index, - ), + thisInfo.copyWith(favouriteOrderIndex: index), ); }); } } /// copies this with a new name and updates the db - Future updateName({ - required String newName, - required Isar isar, - }) async { + Future updateName({required String newName, required Isar isar}) async { // don't allow empty names if (newName.isEmpty) { throw Exception("Empty wallet name not allowed!"); @@ -278,11 +283,7 @@ class WalletInfo implements IsarId { if (thisInfo.name != newName) { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); - await isar.walletInfo.put( - thisInfo.copyWith( - name: newName, - ), - ); + await isar.walletInfo.put(thisInfo.copyWith(name: newName)); }); } } @@ -299,9 +300,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - cachedReceivingAddress: newAddress, - ), + thisInfo.copyWith(cachedReceivingAddress: newAddress), ); }); } @@ -325,37 +324,27 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - otherDataJsonString: encodedNew, - ), + thisInfo.copyWith(otherDataJsonString: encodedNew), ); }); } } /// Can be dangerous. Don't use unless you know the consequences - Future setMnemonicVerified({ - required Isar isar, - }) async { + Future setMnemonicVerified({required Isar isar}) async { final meta = await isar.walletInfoMeta.where().walletIdEqualTo(walletId).findFirst(); if (meta == null) { await isar.writeTxn(() async { await isar.walletInfoMeta.put( - WalletInfoMeta( - walletId: walletId, - isMnemonicVerified: true, - ), + WalletInfoMeta(walletId: walletId, isMnemonicVerified: true), ); }); } else if (meta.isMnemonicVerified == false) { await isar.writeTxn(() async { await isar.walletInfoMeta.deleteByWalletId(walletId); await isar.walletInfoMeta.put( - WalletInfoMeta( - walletId: walletId, - isMnemonicVerified: true, - ), + WalletInfoMeta(walletId: walletId, isMnemonicVerified: true), ); }); } else { @@ -384,9 +373,7 @@ class WalletInfo implements IsarId { await isar.writeTxn(() async { await isar.walletInfo.delete(thisInfo.id); await isar.walletInfo.put( - thisInfo.copyWith( - restoreHeight: newRestoreHeight, - ), + thisInfo.copyWith(restoreHeight: newRestoreHeight), ); }); } @@ -423,9 +410,7 @@ class WalletInfo implements IsarId { this.cachedBalanceSecondaryString, this.cachedBalanceTertiaryString, this.otherDataJsonString, - }) : assert( - AppConfig.coins.map((e) => e.identifier).contains(coinName), - ); + }) : assert(AppConfig.coins.map((e) => e.identifier).contains(coinName)); WalletInfo copyWith({ String? name, @@ -481,9 +466,7 @@ class WalletInfo implements IsarId { Map jsonObject, AddressType mainAddressType, ) { - final coin = AppConfig.getCryptoCurrencyFor( - jsonObject["coin"] as String, - )!; + final coin = AppConfig.getCryptoCurrencyFor(jsonObject["coin"] as String)!; return WalletInfo( coinName: coin.identifier, walletId: jsonObject["id"] as String, @@ -494,11 +477,7 @@ class WalletInfo implements IsarId { @Deprecated("Legacy support") Map toMap() { - return { - "name": name, - "id": walletId, - "coin": coin.identifier, - }; + return {"name": name, "id": walletId, "coin": coin.identifier}; } @Deprecated("Legacy support") @@ -527,4 +506,6 @@ abstract class WalletInfoKeys { static const String reuseAddress = "reuseAddressKey"; static const String isViewOnlyKey = "isViewOnlyKey"; static const String viewOnlyTypeIndexKey = "viewOnlyTypeIndexKey"; + static const String duressMarkedVisibleWalletKey = + "duressMarkedVisibleWalletKey"; } diff --git a/lib/wallets/isar/providers/all_wallets_info_provider.dart b/lib/wallets/isar/providers/all_wallets_info_provider.dart index 0acbae46c..2bdb932ca 100644 --- a/lib/wallets/isar/providers/all_wallets_info_provider.dart +++ b/lib/wallets/isar/providers/all_wallets_info_provider.dart @@ -3,20 +3,30 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; -import '../../../providers/db/main_db_provider.dart'; + import '../../../app_config.dart'; +import '../../../providers/db/main_db_provider.dart'; +import '../../../providers/global/duress_provider.dart'; import '../../crypto_currency/crypto_currency.dart'; import '../models/wallet_info.dart'; final pAllWalletsInfo = Provider((ref) { - return ref.watch(_pAllWalletsInfo.select((value) => value.value)); + final duress = ref.watch(pDuress); + + final results = ref.watch(_pAllWalletsInfo.select((value) => value.value)); + + if (duress) { + results.retainWhere((e) => e.isDuressVisible); + } + + return results; }); final pAllWalletsInfoByCoin = Provider((ref) { final infos = ref.watch(pAllWalletsInfo); final Map wallets})> - map = {}; + map = {}; for (final info in infos) { if (map[info.coin] == null) { @@ -41,6 +51,7 @@ _WalletInfoWatcher? _globalInstance; final _pAllWalletsInfo = ChangeNotifierProvider((ref) { if (_globalInstance == null) { final isar = ref.watch(mainDBProvider).isar; + _globalInstance = _WalletInfoWatcher( isar.walletInfo .where() @@ -65,21 +76,22 @@ class _WalletInfoWatcher extends ChangeNotifier { List get value => _value; _WalletInfoWatcher(this._value, Isar isar) { - _streamSubscription = - isar.walletInfo.watchLazy(fireImmediately: true).listen((event) { - isar.walletInfo - .where() - .filter() - .anyOf( - AppConfig.coins.map((e) => e.identifier), - (q, element) => q.coinNameMatches(element), - ) - .findAll() - .then((value) { - _value = value; - notifyListeners(); - }); - }); + _streamSubscription = isar.walletInfo + .watchLazy(fireImmediately: true) + .listen((event) { + isar.walletInfo + .where() + .filter() + .anyOf( + AppConfig.coins.map((e) => e.identifier), + (q, element) => q.coinNameMatches(element), + ) + .findAll() + .then((value) { + _value = value; + notifyListeners(); + }); + }); } @override diff --git a/lib/widgets/custom_buttons/draggable_switch_button.dart b/lib/widgets/custom_buttons/draggable_switch_button.dart index 064746c6f..e0ea21ebf 100644 --- a/lib/widgets/custom_buttons/draggable_switch_button.dart +++ b/lib/widgets/custom_buttons/draggable_switch_button.dart @@ -48,10 +48,9 @@ class DraggableSwitchButtonState extends State { Color _colorBG(bool isOn, bool enabled, double alpha) { if (enabled) { return Color.alphaBlend( - Theme.of(context) - .extension()! - .switchBGOn - .withOpacity(alpha), + Theme.of( + context, + ).extension()!.switchBGOn.withOpacity(alpha), Theme.of(context).extension()!.switchBGOff, ); } @@ -61,10 +60,9 @@ class DraggableSwitchButtonState extends State { Color _colorFG(bool isOn, bool enabled, double alpha) { if (enabled) { return Color.alphaBlend( - Theme.of(context) - .extension()! - .switchCircleOn - .withOpacity(alpha), + Theme.of( + context, + ).extension()!.switchCircleOn.withOpacity(alpha), Theme.of(context).extension()!.switchCircleOff, ); } @@ -190,15 +188,11 @@ class DraggableSwitchButtonState extends State { children: [ SizedBox( width: constraint.maxWidth / 2, - child: Center( - child: widget.onItem, - ), + child: Center(child: widget.onItem), ), SizedBox( width: constraint.maxWidth / 2, - child: Center( - child: widget.offItem, - ), + child: Center(child: widget.offItem), ), ], ), @@ -215,3 +209,85 @@ class DSBController { VoidCallback? activate; bool Function()? isOn; } + +// new and improved(ish) version +class DraggableSwitch extends StatefulWidget { + final bool value; + final ValueChanged onChanged; + + const DraggableSwitch({ + super.key, + required this.value, + required this.onChanged, + }); + + @override + State createState() => _DraggableSwitchState(); +} + +class _DraggableSwitchState extends State { + final _duration = const Duration(milliseconds: 150); + + double _dragOffset = 0.0; + + void _handleDragEnd(DragEndDetails details) { + if (_dragOffset.abs() > 10) { + final shouldTurnOn = _dragOffset > 0; + if (widget.value != shouldTurnOn) { + widget.onChanged(shouldTurnOn); + } + } + _dragOffset = 0.0; + } + + void _toggle() { + widget.onChanged(!widget.value); + } + + @override + Widget build(BuildContext context) { + final isOn = widget.value; + + final colors = Theme.of(context).extension()!; + + final colorBG = isOn ? colors.switchBGOn : colors.switchBGOff; + final colorFG = isOn ? colors.switchCircleOn : colors.switchCircleOff; + + return GestureDetector( + onTap: _toggle, + onHorizontalDragUpdate: (details) { + _dragOffset += details.primaryDelta!; + }, + onHorizontalDragEnd: _handleDragEnd, + child: LayoutBuilder( + builder: (context, constraints) { + return AnimatedContainer( + duration: _duration, + curve: Curves.easeInOut, + width: constraints.maxWidth, + height: constraints.maxHeight, + padding: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: colorBG, + borderRadius: BorderRadius.circular(constraints.maxHeight / 2), + ), + child: AnimatedAlign( + duration: _duration, + curve: Curves.easeInOut, + alignment: isOn ? Alignment.centerRight : Alignment.centerLeft, + child: AnimatedContainer( + duration: _duration, + height: constraints.maxHeight - 4, + width: constraints.maxWidth / 2 - 4, + decoration: BoxDecoration( + color: colorFG, + shape: BoxShape.circle, + ), + ), + ), + ); + }, + ), + ); + } +} From 6e086611a947c8a5796cbce5452eea6de26dbd15 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 16 May 2025 15:51:57 -0600 Subject: [PATCH 061/206] update mocks --- test/cached_electrumx_test.mocks.dart | 30 +++++++++++++++++ .../pages/send_view/send_view_test.mocks.dart | 32 +++++++++++++++++++ .../exchange/exchange_view_test.mocks.dart | 30 +++++++++++++++++ .../managed_favorite_test.mocks.dart | 32 +++++++++++++++++++ .../node_options_sheet_test.mocks.dart | 32 +++++++++++++++++++ .../table_view/table_view_row_test.mocks.dart | 2 ++ .../transaction_card_test.mocks.dart | 32 +++++++++++++++++++ test/widget_tests/wallet_card_test.mocks.dart | 2 ++ ...et_info_row_balance_future_test.mocks.dart | 2 ++ .../wallet_info_row_test.mocks.dart | 2 ++ 10 files changed, 196 insertions(+) diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index 11c558f20..22ab2a712 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -911,6 +911,36 @@ class MockPrefs extends _i1.Mock implements _i10.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index 476ab3883..c4398cf4d 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -202,6 +202,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { _i10.Future load( _i12.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -209,6 +210,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i10.Future.value(), @@ -848,6 +850,36 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 1271b96b0..643d6cc6b 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -272,6 +272,36 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index 218b9c0c5..6eb09a26e 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -202,6 +202,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { _i10.Future load( _i12.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -209,6 +210,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i10.Future.value(), @@ -553,6 +555,36 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index cf7098de6..172abecf2 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -203,6 +203,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { _i10.Future load( _i12.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -210,6 +211,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i10.Future.value(), @@ -428,6 +430,36 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/widget_tests/table_view/table_view_row_test.mocks.dart b/test/widget_tests/table_view/table_view_row_test.mocks.dart index 9393a5730..4d7adcad3 100644 --- a/test/widget_tests/table_view/table_view_row_test.mocks.dart +++ b/test/widget_tests/table_view/table_view_row_test.mocks.dart @@ -171,6 +171,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { _i8.Future load( _i11.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -178,6 +179,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i8.Future.value(), diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index ac6790693..a090e757e 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -230,6 +230,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { _i10.Future load( _i13.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -237,6 +238,7 @@ class MockWallets extends _i1.Mock implements _i9.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i10.Future.value(), @@ -526,6 +528,36 @@ class MockPrefs extends _i1.Mock implements _i13.Prefs { returnValueForMissingStub: null, ); + @override + bool get hasDuressPin => (super.noSuchMethod( + Invocation.getter(#hasDuressPin), + returnValue: false, + ) as bool); + + @override + set hasDuressPin(bool? hasDuressPin) => super.noSuchMethod( + Invocation.setter( + #hasDuressPin, + hasDuressPin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get biometricsDuress => (super.noSuchMethod( + Invocation.getter(#biometricsDuress), + returnValue: false, + ) as bool); + + @override + set biometricsDuress(bool? biometricsDuress) => super.noSuchMethod( + Invocation.setter( + #biometricsDuress, + biometricsDuress, + ), + returnValueForMissingStub: null, + ); + @override int get familiarity => (super.noSuchMethod( Invocation.getter(#familiarity), diff --git a/test/widget_tests/wallet_card_test.mocks.dart b/test/widget_tests/wallet_card_test.mocks.dart index 80c03af35..1ba8ca158 100644 --- a/test/widget_tests/wallet_card_test.mocks.dart +++ b/test/widget_tests/wallet_card_test.mocks.dart @@ -174,6 +174,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { _i8.Future load( _i11.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -181,6 +182,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i8.Future.value(), diff --git a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart index d7fea45d4..7ded2cf87 100644 --- a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart @@ -170,6 +170,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { _i8.Future load( _i10.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -177,6 +178,7 @@ class MockWallets extends _i1.Mock implements _i7.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i8.Future.value(), diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart index 88f854589..3f2a24ac7 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart @@ -184,6 +184,7 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { _i9.Future load( _i11.Prefs? prefs, _i3.MainDB? mainDB, + bool? isDuress, ) => (super.noSuchMethod( Invocation.method( @@ -191,6 +192,7 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { [ prefs, mainDB, + isDuress, ], ), returnValue: _i9.Future.value(), From d23f50bfc5cd0e1aaf233ea437928746e91251a9 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 16 May 2025 15:56:51 -0600 Subject: [PATCH 062/206] refactor to descriptive function name --- lib/pages/send_view/send_view.dart | 8 ++++---- .../wallet_view/sub_widgets/desktop_send.dart | 4 ++-- lib/utilities/address_utils.dart | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 3c907605e..4047a2064 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -231,7 +231,7 @@ class _SendViewState extends ConsumerState { _applyUri(paymentData); } else { if (coin is Epiccash) { - content = AddressUtils().formatAddress(content); + content = AddressUtils().formatEpicCashAddress(content); } sendToController.text = content; @@ -245,7 +245,7 @@ class _SendViewState extends ConsumerState { } catch (e) { if (coin is Epiccash) { // strip http:// and https:// if content contains @ - content = AddressUtils().formatAddress(content); + content = AddressUtils().formatEpicCashAddress(content); } await _checkSparkNameAndOrSetAddress(content); @@ -977,7 +977,7 @@ class _SendViewState extends ConsumerState { if (coin is Epiccash) { // strip http:// and https:// if content contains @ - content = AddressUtils().formatAddress(content); + content = AddressUtils().formatEpicCashAddress(content); } final trimmed = content.trim(); @@ -1223,7 +1223,7 @@ class _SendViewState extends ConsumerState { _address = _address!.substring(0, _address!.indexOf("\n")); } - sendToController.text = AddressUtils().formatAddress(_address!); + sendToController.text = AddressUtils().formatEpicCashAddress(_address!); } }); } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 300bc4d99..7dd007a2e 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -737,7 +737,7 @@ class _DesktopSendState extends ConsumerState { _applyUri(paymentData); } else { if (coin is Epiccash) { - content = AddressUtils().formatAddress(content); + content = AddressUtils().formatEpicCashAddress(content); } sendToController.text = content; @@ -752,7 +752,7 @@ class _DesktopSendState extends ConsumerState { // If parsing fails, treat it as a plain address. if (coin is Epiccash) { // strip http:// and https:// if content contains @ - content = AddressUtils().formatAddress(content); + content = AddressUtils().formatEpicCashAddress(content); } await _checkSparkNameAndOrSetAddress(content); diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index d14e4e809..9b2f03758 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -229,7 +229,7 @@ class AddressUtils { } /// Formats an address string to remove any unnecessary prefixes or suffixes. - String formatAddress(String epicAddress) { + String formatEpicCashAddress(String epicAddress) { // strip http:// or https:// prefixes if the address contains an @ symbol (and is thus an epicbox address) if ((epicAddress.startsWith("http://") || epicAddress.startsWith("https://")) && From 7d28ed89342cc7b969e0408c94506f812c38ec02 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 16 May 2025 16:40:39 -0600 Subject: [PATCH 063/206] fix: empty other data error --- .../new_wallet_recovery_phrase_warning_view.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index a35c4563a..2ad110fbd 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -150,10 +150,15 @@ class _NewWalletRecoveryPhraseWarningViewState otherDataJson[WalletInfoKeys.duressMarkedVisibleWalletKey] = true; } + String? otherDataJsonString; + if (otherDataJson != null && otherDataJson.isNotEmpty) { + otherDataJsonString = jsonEncode(otherDataJson); + } + final info = WalletInfo.createNew( coin: widget.coin, name: widget.walletName, - otherDataJsonString: jsonEncode(otherDataJson), + otherDataJsonString: otherDataJsonString, ); var node = ref From d6bc8befa796c2e951dc7c3357a8cdf34fca796a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 16 May 2025 16:42:29 -0600 Subject: [PATCH 064/206] hack in check for addresses that can contain colon in the uri parsing logic --- lib/utilities/address_utils.dart | 14 ++++++++++++++ test/address_utils_test.dart | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index 9b2f03758..9e63370e1 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -134,6 +134,20 @@ class AddressUtils { /// /// Returns null on failure to parse static PaymentUriData? parsePaymentUri(String uri, {Logging? logging}) { + // hacky check its not just a bcash, ecash, or xel address + final parts = uri.split(":"); + if (parts.length == 2) { + if ([ + "xel", + "bitcoincash", + "bchtest", + "ecash", + "ectest", + ].contains(parts.first.toLowerCase())) { + return null; + } + } + try { final Map parsedData = _parseUri(uri); diff --git a/test/address_utils_test.dart b/test/address_utils_test.dart index 599380c31..c3ce3cbad 100644 --- a/test/address_utils_test.dart +++ b/test/address_utils_test.dart @@ -57,6 +57,17 @@ void main() { expect(AddressUtils.parsePaymentUri(uri), isNull); }); + test("parse double prefix type address", () { + const uri = + "bitcoin:xel:$firoAddress?amount=50.1&message=eggs%20are%20good%21"; + final result = AddressUtils.parsePaymentUri(uri); + expect(result, isNotNull); + expect(result!.scheme, "bitcoin"); + expect(result.address, "xel:$firoAddress"); + expect(result.amount, "50.1"); + expect(result.message, "eggs are good!"); + }); + test("encode a list of (mnemonic) words/strings as a json object", () { final List list = [ "hello", @@ -92,7 +103,10 @@ void main() { test("build a uri string with empty params", () { expect( AddressUtils.buildUriString( - Firo(CryptoCurrencyNetwork.main).uriScheme, firoAddress, {}), + Firo(CryptoCurrencyNetwork.main).uriScheme, + firoAddress, + {}, + ), "firo:$firoAddress", ); }); From 2bbe82d4006520f8ce3ed6a0cb5bb8c443598ef6 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 19 May 2025 09:47:52 -0600 Subject: [PATCH 065/206] Fix hardcoded android logs dir. Might fix https://github.com/cypherstack/stack_wallet/issues/1134 ? --- lib/utilities/stack_file_system.dart | 37 ++++++++++++------- pubspec.lock | 8 ++-- scripts/app_config/templates/pubspec.template | 2 +- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index 14cb0fae0..4f9bff090 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -10,6 +10,7 @@ import 'dart:io'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -40,14 +41,17 @@ abstract class StackFileSystem { if (Util.isArmLinux) { appDirectory = await getApplicationDocumentsDirectory(); appDirectory = Directory( - "${appDirectory.path}/.${AppConfig.appDefaultDataDirName}", + path.join(appDirectory.path, ".${AppConfig.appDefaultDataDirName}"), ); } else if (Platform.isLinux) { if (_overrideDesktopDirPath != null) { appDirectory = Directory(_overrideDesktopDirPath!); } else { appDirectory = Directory( - "${Platform.environment['HOME']}/.${AppConfig.appDefaultDataDirName}", + path.join( + Platform.environment['HOME']!, + ".${AppConfig.appDefaultDataDirName}", + ), ); } } else if (Platform.isWindows) { @@ -62,7 +66,7 @@ abstract class StackFileSystem { } else { appDirectory = await getLibraryDirectory(); appDirectory = Directory( - "${appDirectory.path}/${AppConfig.appDefaultDataDirName}", + path.join(appDirectory.path, AppConfig.appDefaultDataDirName), ); } } else if (Platform.isIOS) { @@ -86,7 +90,7 @@ abstract class StackFileSystem { static Future applicationIsarDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { - final dir = Directory("${root.path}/isar"); + final dir = Directory(path.join(root.path, "isar")); if (!dir.existsSync()) { await dir.create(); } @@ -99,7 +103,7 @@ abstract class StackFileSystem { static Future applicationDriftDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { - final dir = Directory("${root.path}/drift"); + final dir = Directory(path.join(root.path, "drift")); if (!dir.existsSync()) { await dir.create(); } @@ -126,7 +130,7 @@ abstract class StackFileSystem { static Future applicationTorDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { - final dir = Directory("${root.path}/tor"); + final dir = Directory(path.join(root.path, "tor")); if (!dir.existsSync()) { await dir.create(); } @@ -139,7 +143,7 @@ abstract class StackFileSystem { static Future applicationFiroCacheSQLiteDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { - final dir = Directory("${root.path}/sqlite/firo_cache"); + final dir = Directory(path.join(root.path, "sqlite", "firo_cache")); if (!dir.existsSync()) { await dir.create(recursive: true); } @@ -152,7 +156,7 @@ abstract class StackFileSystem { static Future applicationHiveDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { - final dir = Directory("${root.path}/hive"); + final dir = Directory(path.join(root.path, "hive")); if (!dir.existsSync()) { await dir.create(); } @@ -164,7 +168,7 @@ abstract class StackFileSystem { static Future applicationXelisDirectory() async { final root = await applicationRootDirectory(); - final dir = Directory("${root.path}${Platform.pathSeparator}xelis"); + final dir = Directory(path.join(root.path, "xelis")); if (!dir.existsSync()) { await dir.create(); } @@ -173,7 +177,7 @@ abstract class StackFileSystem { static Future applicationXelisTableDirectory() async { final xelis = await applicationXelisDirectory(); - final dir = Directory("${xelis.path}${Platform.pathSeparator}table"); + final dir = Directory(path.join(xelis.path, "table")); if (!dir.existsSync()) { await dir.create(); } @@ -183,7 +187,7 @@ abstract class StackFileSystem { static Future initThemesDir() async { final root = await applicationRootDirectory(); - final dir = Directory("${root.path}/themes"); + final dir = Directory(path.join(root.path, "themes")); if (!dir.existsSync()) { await dir.create(); } @@ -206,13 +210,18 @@ abstract class StackFileSystem { final Directory logsDir; if (Platform.isIOS) { - logsDir = Directory("${appDocsDir.path}/logs"); + logsDir = Directory(path.join(appDocsDir.path, "logs")); } else if (Platform.isMacOS || Platform.isLinux || Platform.isWindows) { // TODO check this is correct for macos - logsDir = Directory("${appDocsDir.path}/$logsDirName"); + logsDir = Directory(path.join(appDocsDir.path, logsDirName)); } else if (Platform.isAndroid) { await Permission.storage.request(); - logsDir = Directory("/storage/emulated/0/Documents/$logsDirName"); + final ext = await getExternalStorageDirectory(); + final rootPath = path.dirname( + path.dirname(path.dirname(path.dirname(ext!.path))), + ); + final logsDirPath = path.join(rootPath, "Documents", logsDirName); + logsDir = Directory(logsDirPath); } else { throw Exception("Unsupported Platform"); } diff --git a/pubspec.lock b/pubspec.lock index 16e439300..c5baa5ce0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1574,18 +1574,18 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" + sha256: "2d070d8684b68efb580a5997eb62f675e8a885ef0be6e754fb9ef489c177470f" url: "https://pub.dev" source: hosted - version: "11.4.0" + version: "12.0.0+1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" url: "https://pub.dev" source: hosted - version: "12.1.0" + version: "13.0.1" permission_handler_apple: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index d086b0f94..f4959f93d 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -78,7 +78,7 @@ dependencies: # Utility plugins http: ^0.13.0 local_auth: ^2.3.0 - permission_handler: ^11.0.0 + permission_handler: ^12.0.0+1 flutter_local_notifications: ^17.2.2 rxdart: ^0.27.3 zxcvbn: ^1.0.0 From 9b8239bdba5fc6f374d07dfe8e57a49d24524739 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 20 May 2025 12:44:21 -0600 Subject: [PATCH 066/206] fix: duress biometrics --- lib/pages/pinpad_views/lock_screen_view.dart | 5 ++++- .../global_settings_view/security_views/security_view.dart | 2 +- lib/providers/global/duress_provider.dart | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pages/pinpad_views/lock_screen_view.dart b/lib/pages/pinpad_views/lock_screen_view.dart index f3552cf82..7a21a99c3 100644 --- a/lib/pages/pinpad_views/lock_screen_view.dart +++ b/lib/pages/pinpad_views/lock_screen_view.dart @@ -204,7 +204,10 @@ class _LockscreenViewState extends ConsumerState { final hasDuressPin = (await _secureStore.read(key: kDuressPinKey)) != null; - ref.read(pDuress.notifier).state = hasDuressPin; + ref.read(pDuress.notifier).state = + hasDuressPin && + ref.read(prefsChangeNotifierProvider).biometricsDuress; + canTryUnlock = true; } else { if (ref.read(pDuress)) { diff --git a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart index 7ccfd2650..b5aac24a9 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart @@ -489,7 +489,7 @@ class _SecurityViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Duress uses biometrics", + "Biometrics opens duress", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), diff --git a/lib/providers/global/duress_provider.dart b/lib/providers/global/duress_provider.dart index f6e84011c..22ef4072d 100644 --- a/lib/providers/global/duress_provider.dart +++ b/lib/providers/global/duress_provider.dart @@ -1,4 +1,4 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -final pDuress = StateProvider((ref) => true); +final pDuress = StateProvider((ref) => false); From b51e6a807b16085e039cb30aee310a59f4ea28bf Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 20 May 2025 19:41:29 -0600 Subject: [PATCH 067/206] WIP: just android things... --- lib/pages/monkey/monkey_view.dart | 611 +++++++++--------- lib/pages/ordinals/ordinal_details_view.dart | 116 ++-- .../advanced_views/logging_settings_view.dart | 160 +++-- .../helpers/swb_file_system.dart | 33 +- .../desktop_ordinal_details_view.dart | 147 ++--- lib/utilities/stack_file_system.dart | 27 +- .../android/app/src/main/AndroidManifest.xml | 6 - scripts/app_config/templates/pubspec.template | 2 +- 8 files changed, 544 insertions(+), 558 deletions(-) diff --git a/lib/pages/monkey/monkey_view.dart b/lib/pages/monkey/monkey_view.dart index f8f9d3f4d..ab39021cb 100644 --- a/lib/pages/monkey/monkey_view.dart +++ b/lib/pages/monkey/monkey_view.dart @@ -4,8 +4,8 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import '../../notifications/show_flush_bar.dart'; import '../../providers/global/wallets_provider.dart'; @@ -14,6 +14,7 @@ import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; import '../../utilities/show_loading.dart'; +import '../../utilities/stack_file_system.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; @@ -30,10 +31,7 @@ import '../../widgets/desktop/secondary_button.dart'; import '../../widgets/stack_dialog.dart'; class MonkeyView extends ConsumerStatefulWidget { - const MonkeyView({ - super.key, - required this.walletId, - }); + const MonkeyView({super.key, required this.walletId}); static const String routeName = "/monkey"; static const double navBarHeight = 65.0; @@ -56,7 +54,7 @@ class _MonkeyViewState extends ConsumerState { Future _getDocsDir() async { try { if (Platform.isAndroid) { - return Directory("/storage/emulated/0/Documents"); + return await StackFileSystem.wtfAndroidDocumentsPath(); } return await getApplicationDocumentsDirectory(); @@ -72,21 +70,17 @@ class _MonkeyViewState extends ConsumerState { bool isPNG = false, bool overwrite = false, }) async { - if (Platform.isAndroid) { - await Permission.storage.request(); - } - final dir = await _getDocsDir(); if (dir == null) { throw Exception("Failed to get documents directory to save monKey image"); } - final address = await ref - .read(pWallets) - .getWallet(walletId) - .getCurrentReceivingAddress(); - final docPath = dir.path; - String filePath = "$docPath/monkey_$address"; + final address = + await ref + .read(pWallets) + .getWallet(walletId) + .getCurrentReceivingAddress(); + String filePath = path.join(dir.path, "monkey_$address"); filePath += isPNG ? ".png" : ".svg"; @@ -119,273 +113,261 @@ class _MonkeyViewState extends ConsumerState { return Background( child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopScaffold( - appBar: DesktopAppBar( - background: Theme.of(context).extension()!.popupBG, - leading: Expanded( - child: Row( - children: [ - const SizedBox( - width: 32, - ), - AppBarIconButton( - size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.arrowLeft, - width: 18, - height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: Navigator.of(context).pop, - ), - const SizedBox( - width: 15, - ), - SvgPicture.asset( - Assets.svg.monkey, - width: 32, - height: 32, - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - const SizedBox( - width: 12, + builder: + (child) => DesktopScaffold( + appBar: DesktopAppBar( + background: Theme.of(context).extension()!.popupBG, + leading: Expanded( + child: Row( + children: [ + const SizedBox(width: 32), + AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + const SizedBox(width: 15), + SvgPicture.asset( + Assets.svg.monkey, + width: 32, + height: 32, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + const SizedBox(width: 12), + Text("MonKey", style: STextStyles.desktopH3(context)), + ], ), - Text( - "MonKey", - style: STextStyles.desktopH3(context), + ), + trailing: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(1000), ), - ], - ), - ), - trailing: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(1000), - ), - onPressed: () { - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + onPressed: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxHeight: double.infinity, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "About MonKeys", - style: STextStyles.desktopH3(context), - ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "About MonKeys", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - const DesktopDialogCloseButton(), - ], - ), - Text( - "A MonKey is a visual representation of your Banano address.", - style: - STextStyles.desktopTextMedium(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.all( - 32, - ), - child: PrimaryButton( - width: 272.5, - label: "OK", - onPressed: () { - Navigator.of(context).pop(); - }, + Text( + "A MonKey is a visual representation of your Banano address.", + style: STextStyles.desktopTextMedium( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, ), ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: PrimaryButton( + width: 272.5, + label: "OK", + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ], + ), ], ), - ], - ), + ); + }, ); }, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 19, - horizontal: 32, - ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .customTextButtonEnabledText, - ), - const SizedBox( - width: 8, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 19, + horizontal: 32, ), - Text( - "What is MonKey?", - style: - STextStyles.desktopMenuItemSelected(context).copyWith( - color: Theme.of(context) - .extension()! - .customTextButtonEnabledText, - ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + color: + Theme.of(context) + .extension()! + .customTextButtonEnabledText, + ), + const SizedBox(width: 8), + Text( + "What is MonKey?", + style: STextStyles.desktopMenuItemSelected( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .customTextButtonEnabledText, + ), + ), + ], ), - ], + ), ), + useSpacers: false, + isCompactHeight: true, ), + body: child, ), - useSpacers: false, - isCompactHeight: true, - ), - body: child, - ), child: ConditionalParent( condition: !isDesktop, - builder: (child) => Scaffold( - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "MonKey", - style: STextStyles.navBarTitle(context), - ), - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - ), + builder: + (child) => Scaffold( + appBar: AppBar( + leading: AppBarBackButton( onPressed: () { - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return const StackOkDialog( - title: "About MonKeys", - message: - "A MonKey is a visual representation of your Banano address.", - ); - }, - ); + Navigator.of(context).pop(); }, ), + title: Text( + "MonKey", + style: STextStyles.navBarTitle(context), + ), + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + icon: SvgPicture.asset(Assets.svg.circleQuestion), + onPressed: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const StackOkDialog( + title: "About MonKeys", + message: + "A MonKey is a visual representation of your Banano address.", + ); + }, + ); + }, + ), + ), + ], ), - ], - ), - body: child, - ), + body: child, + ), child: ConditionalParent( condition: isDesktop, - builder: (child) => SizedBox( - width: 318, - child: child, - ), + builder: (child) => SizedBox(width: 318, child: child), child: ConditionalParent( condition: imageBytes != null, - builder: (_) => Column( - children: [ - isDesktop - ? const SizedBox( - height: 50, - ) - : const Spacer( - flex: 1, - ), - if (imageBytes != null) - SizedBox( - width: 300, - height: 300, - child: SvgPicture.memory(Uint8List.fromList(imageBytes!)), - ), - isDesktop - ? const SizedBox( - height: 50, - ) - : const Spacer( - flex: 1, + builder: + (_) => Column( + children: [ + isDesktop + ? const SizedBox(height: 50) + : const Spacer(flex: 1), + if (imageBytes != null) + SizedBox( + width: 300, + height: 300, + child: SvgPicture.memory( + Uint8List.fromList(imageBytes!), + ), ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - SecondaryButton( - label: "Save as SVG", - onPressed: () async { - bool didError = false; - await showLoading( - whileFuture: Future.wait([ - _saveMonKeyToFile( - bytes: Uint8List.fromList( - (wallet as BananoWallet) - .getMonkeyImageBytes()!, - ), - ), - Future.delayed( - const Duration(seconds: 2), - ), - ]), - context: context, - rootNavigator: Util.isDesktop, - message: "Saving MonKey svg", - onException: (e) { - didError = true; - String msg = e.toString(); - while (msg.isNotEmpty && - msg.startsWith("Exception:")) { - msg = msg.substring(10).trim(); - } - showFloatingFlushBar( - type: FlushBarType.warning, - message: msg, + isDesktop + ? const SizedBox(height: 50) + : const Spacer(flex: 1), + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + SecondaryButton( + label: "Save as SVG", + onPressed: () async { + bool didError = false; + await showLoading( + whileFuture: Future.wait([ + _saveMonKeyToFile( + bytes: Uint8List.fromList( + (wallet as BananoWallet) + .getMonkeyImageBytes()!, + ), + ), + Future.delayed( + const Duration(seconds: 2), + ), + ]), context: context, + rootNavigator: Util.isDesktop, + message: "Saving MonKey svg", + onException: (e) { + didError = true; + String msg = e.toString(); + while (msg.isNotEmpty && + msg.startsWith("Exception:")) { + msg = msg.substring(10).trim(); + } + showFloatingFlushBar( + type: FlushBarType.warning, + message: msg, + context: context, + ); + }, ); - }, - ); - if (!didError && mounted) { - await showFloatingFlushBar( - type: FlushBarType.success, - message: - "SVG MonKey image saved to $_monkeyPath", - context: context, - ); - } - }, - ), - const SizedBox(height: 12), - SecondaryButton( - label: "Download as PNG", - onPressed: () async { - bool didError = false; - await showLoading( - whileFuture: Future.wait([ - wallet.getCurrentReceivingAddress().then( + if (!didError && mounted) { + await showFloatingFlushBar( + type: FlushBarType.success, + message: + "SVG MonKey image saved to $_monkeyPath", + context: context, + ); + } + }, + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Download as PNG", + onPressed: () async { + bool didError = false; + await showLoading( + whileFuture: Future.wait([ + wallet.getCurrentReceivingAddress().then( (address) async => await ref .read(pMonKeyService) .fetchMonKey( @@ -395,80 +377,73 @@ class _MonkeyViewState extends ConsumerState { .then( (monKeyBytes) async => await _saveMonKeyToFile( - bytes: monKeyBytes, - isPNG: true, - ), + bytes: monKeyBytes, + isPNG: true, + ), ), ), - Future.delayed( - const Duration(seconds: 2), - ), - ]), - context: context, - rootNavigator: Util.isDesktop, - message: "Downloading MonKey png", - onException: (e) { - didError = true; - String msg = e.toString(); - while (msg.isNotEmpty && - msg.startsWith("Exception:")) { - msg = msg.substring(10).trim(); - } - showFloatingFlushBar( - type: FlushBarType.warning, - message: msg, + Future.delayed( + const Duration(seconds: 2), + ), + ]), context: context, + rootNavigator: Util.isDesktop, + message: "Downloading MonKey png", + onException: (e) { + didError = true; + String msg = e.toString(); + while (msg.isNotEmpty && + msg.startsWith("Exception:")) { + msg = msg.substring(10).trim(); + } + showFloatingFlushBar( + type: FlushBarType.warning, + message: msg, + context: context, + ); + }, ); - }, - ); - if (!didError && mounted) { - await showFloatingFlushBar( - type: FlushBarType.success, - message: - "PNG MonKey image saved to $_monkeyPath", - context: context, - ); - } - }, + if (!didError && mounted) { + await showFloatingFlushBar( + type: FlushBarType.success, + message: + "PNG MonKey image saved to $_monkeyPath", + context: context, + ); + } + }, + ), + ], ), - ], - ), + ), + // child, + ], ), - // child, - ], - ), child: Column( children: [ isDesktop - ? const SizedBox( - height: 100, - ) - : const Spacer( - flex: 4, - ), + ? const SizedBox(height: 100) + : const Spacer(flex: 4), Center( child: Column( children: [ Opacity( opacity: 0.2, child: SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: 200, height: 200, ), ), - const SizedBox( - height: 70, - ), + const SizedBox(height: 70), Text( "You do not have a MonKey yet. \nFetch yours now!", style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, ), textAlign: TextAlign.center, ), @@ -476,12 +451,8 @@ class _MonkeyViewState extends ConsumerState { ), ), isDesktop - ? const SizedBox( - height: 50, - ) - : const Spacer( - flex: 6, - ), + ? const SizedBox(height: 50) + : const Spacer(flex: 6), Padding( padding: const EdgeInsets.all(16.0), child: PrimaryButton( @@ -490,16 +461,14 @@ class _MonkeyViewState extends ConsumerState { await showLoading( whileFuture: Future.wait([ wallet.getCurrentReceivingAddress().then( - (address) async => await ref - .read(pMonKeyService) - .fetchMonKey(address: address!.value) - .then( - (monKeyBytes) async => - await _updateWalletMonKey( - monKeyBytes, - ), - ), - ), + (address) async => await ref + .read(pMonKeyService) + .fetchMonKey(address: address!.value) + .then( + (monKeyBytes) async => + await _updateWalletMonKey(monKeyBytes), + ), + ), Future.delayed(const Duration(seconds: 2)), ]), context: context, diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart index 02e0ee074..40ba0333e 100644 --- a/lib/pages/ordinals/ordinal_details_view.dart +++ b/lib/pages/ordinals/ordinal_details_view.dart @@ -5,8 +5,8 @@ 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:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import '../../models/isar/models/blockchain_data/utxo.dart'; import '../../models/isar/ordinal.dart'; @@ -21,6 +21,7 @@ import '../../utilities/amount/amount_formatter.dart'; import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/show_loading.dart'; +import '../../utilities/stack_file_system.dart'; import '../../utilities/text_styles.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../widgets/background.dart'; @@ -92,9 +93,7 @@ class _OrdinalDetailsViewState extends ConsumerState { title: "Inscription number", data: widget.ordinal.inscriptionNumber.toString(), ), - const SizedBox( - height: _spacing, - ), + const SizedBox(height: _spacing), _DetailsItemWCopy( title: "Inscription ID", data: widget.ordinal.inscriptionId, @@ -103,37 +102,32 @@ class _OrdinalDetailsViewState extends ConsumerState { // height: _spacing, // ), // // todo: add utxo status - const SizedBox( - height: _spacing, - ), + const SizedBox(height: _spacing), _DetailsItemWCopy( title: "Amount", - data: utxo == null - ? "ERROR" - : ref.watch(pAmountFormatter(coin)).format( - Amount( - rawValue: BigInt.from(utxo!.value), - fractionDigits: coin.fractionDigits, - ), - ), - ), - const SizedBox( - height: _spacing, + data: + utxo == null + ? "ERROR" + : ref + .watch(pAmountFormatter(coin)) + .format( + Amount( + rawValue: BigInt.from(utxo!.value), + fractionDigits: coin.fractionDigits, + ), + ), ), + const SizedBox(height: _spacing), _DetailsItemWCopy( title: "Owner address", data: utxo?.address ?? "ERROR", ), - const SizedBox( - height: _spacing, - ), + const SizedBox(height: _spacing), _DetailsItemWCopy( title: "Transaction ID", data: widget.ordinal.utxoTXID, ), - const SizedBox( - height: _spacing, - ), + const SizedBox(height: _spacing), ], ), ), @@ -145,11 +139,7 @@ class _OrdinalDetailsViewState extends ConsumerState { } class _DetailsItemWCopy extends StatelessWidget { - const _DetailsItemWCopy({ - super.key, - required this.title, - required this.data, - }); + const _DetailsItemWCopy({super.key, required this.title, required this.data}); final String title; final String data; @@ -163,10 +153,7 @@ class _DetailsItemWCopy extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - title, - style: STextStyles.itemSubtitle(context), - ), + Text(title, style: STextStyles.itemSubtitle(context)), GestureDetector( onTap: () async { await Clipboard.setData(ClipboardData(text: data)); @@ -184,20 +171,20 @@ class _DetailsItemWCopy extends StatelessWidget { children: [ SvgPicture.asset( Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, width: 12, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Text( "Copy", style: STextStyles.infoSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemIcons, + color: + Theme.of( + context, + ).extension()!.infoItemIcons, ), ), ], @@ -205,13 +192,8 @@ class _DetailsItemWCopy extends StatelessWidget { ), ], ), - const SizedBox( - height: 4, - ), - SelectableText( - data, - style: STextStyles.itemSubtitle12(context), - ), + const SizedBox(height: 4), + SelectableText(data, style: STextStyles.itemSubtitle12(context)), ], ), ); @@ -235,9 +217,10 @@ class _OrdinalImageGroup extends ConsumerWidget { final response = await client.get( url: Uri.parse(ordinal.content), - proxyInfo: ref.read(prefsChangeNotifierProvider).useTor - ? ref.read(pTorService).getProxyInfo() - : null, + proxyInfo: + ref.read(prefsChangeNotifierProvider).useTor + ? ref.read(pTorService).getProxyInfo() + : null, ); if (response.code != 200) { @@ -248,16 +231,14 @@ class _OrdinalImageGroup extends ConsumerWidget { final bytes = response.bodyBytes; - if (Platform.isAndroid) { - await Permission.storage.request(); - } - - final dir = Platform.isAndroid - ? Directory("/storage/emulated/0/Documents") - : await getApplicationDocumentsDirectory(); - - final docPath = dir.path; - final filePath = "$docPath/ordinal_${ordinal.inscriptionNumber}.png"; + final dir = + Platform.isAndroid + ? await StackFileSystem.wtfAndroidDocumentsPath() + : await getApplicationDocumentsDirectory(); + final filePath = path.join( + dir.path, + "ordinal_${ordinal.inscriptionNumber}.png", + ); final File imgFile = File(filePath); @@ -299,9 +280,7 @@ class _OrdinalImageGroup extends ConsumerWidget { ), ), ), - const SizedBox( - height: _spacing, - ), + const SizedBox(height: _spacing), Row( children: [ Expanded( @@ -311,9 +290,10 @@ class _OrdinalImageGroup extends ConsumerWidget { Assets.svg.arrowDown, width: 10, height: 12, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), buttonHeight: ButtonHeight.l, iconSpacing: 4, diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/logging_settings_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/logging_settings_view.dart index dc6c24013..eb4eb5536 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/logging_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/logging_settings_view.dart @@ -11,21 +11,28 @@ import 'dart:async'; import 'dart:io'; +import 'package:archive/archive_io.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; // import 'package:flutter_libmonero/git_versions.dart' as MONERO_VERSIONS; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; import '../../../../app_config.dart'; import '../../../../providers/global/prefs_provider.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; import '../../../../utilities/logger.dart'; +import '../../../../utilities/show_loading.dart'; +import '../../../../utilities/stack_file_system.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/log_level_preference_widget.dart'; import '../../../../widgets/rounded_white_container.dart'; import '../../../../widgets/stack_dialog.dart'; @@ -45,15 +52,14 @@ class _LoggingSettingsViewState extends ConsumerState { bool _lock = false; Future _edit() async { - final currentPath = ref.read(prefsChangeNotifierProvider).logsPath ?? + final currentPath = + ref.read(prefsChangeNotifierProvider).logsPath ?? Logging.instance.logsDirPath; final newPath = await _pickDir(context, currentPath); // test if has permission to write if (newPath != null) { - final file = File( - "$newPath${Platform.pathSeparator}._test", - ); + final file = File("$newPath${Platform.pathSeparator}._test"); if (!file.existsSync()) { file.createSync(); file.deleteSync(); @@ -67,7 +73,7 @@ class _LoggingSettingsViewState extends ConsumerState { setState(() { fileLocationController.text = ref.read(prefsChangeNotifierProvider).logsPath ?? - Logging.instance.logsDirPath; + Logging.instance.logsDirPath; }); } } @@ -88,13 +94,82 @@ class _LoggingSettingsViewState extends ConsumerState { return chosenPath; } + Future _exportHelper() async { + final logsDir = await StackFileSystem.applicationLogsDirectory( + ref.read(prefsChangeNotifierProvider), + ); + + final files = logsDir + .listSync(recursive: false) + .whereType() + .where((f) => f.path.endsWith('.txt')); + + if (files.isEmpty) { + throw Exception("No logs found in ${logsDir.path}"); + } + + final archive = Archive(); + + for (final file in files) { + final bytes = await file.readAsBytes(); + final fileName = path.basename(file.path); + archive.addFile(ArchiveFile(fileName, bytes.length, bytes)); + } + + if (archive.isEmpty) { + throw Exception("Failed to add log files to archive"); + } + + // Write zip to a temp location + final tempDir = await getTemporaryDirectory(); + final zipPath = path.join(tempDir.path, 'logs.zip'); + final zipFile = File(zipPath); + await zipFile.writeAsBytes(ZipEncoder().encode(archive)!); + + await Share.shareXFiles([ + XFile(zipFile.path), + ], text: "${AppConfig.appName} logs"); + } + + bool _exportLock = false; + Future _androidExportLogs() async { + if (_exportLock) { + return; + } + _exportLock = true; + try { + await showLoading( + whileFuture: _exportHelper(), + context: context, + message: "Exporting logs...", + onException: (e) => throw e, + ); + } catch (e, s) { + Logging.instance.e("Failed to export logs", error: e, stackTrace: s); + if (mounted) { + unawaited( + showDialog( + context: context, + builder: + (context) => StackOkDialog( + title: "Failed to export logs", + message: e.toString(), + ), + ), + ); + } + } finally { + _exportLock = false; + } + } + @override void initState() { super.initState(); fileLocationController = TextEditingController(); fileLocationController.text = ref.read(prefsChangeNotifierProvider).logsPath ?? - Logging.instance.logsDirPath; + Logging.instance.logsDirPath; } @override @@ -114,18 +189,11 @@ class _LoggingSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Logging", - style: STextStyles.navBarTitle(context), - ), + title: Text("Logging", style: STextStyles.navBarTitle(context)), ), body: SafeArea( child: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), child: Column( children: [ Row( @@ -137,9 +205,7 @@ class _LoggingSettingsViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), TextField( autocorrect: false, enableSuggestions: false, @@ -151,27 +217,22 @@ class _LoggingSettingsViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), ), - key: const Key( - "logsDirPathLocationControllerKey", - ), + key: const Key("logsDirPathLocationControllerKey"), readOnly: true, toolbarOptions: const ToolbarOptions( copy: true, @@ -181,13 +242,9 @@ class _LoggingSettingsViewState extends ConsumerState { ), onChanged: (newValue) {}, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const LogLevelPreferenceWidget(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -201,10 +258,16 @@ class _LoggingSettingsViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), + + if (Platform.isAndroid) + SecondaryButton( + label: "Export logs", + onPressed: _androidExportLogs, + ), + if (Platform.isAndroid) const SizedBox(height: 16), + PrimaryButton( label: "Select log save location", onPressed: () async { @@ -222,9 +285,9 @@ class _LoggingSettingsViewState extends ConsumerState { ); if (context.mounted) { final String err; - if (e - .toString() - .contains("OS Error: Operation not permitted")) { + if (e.toString().contains( + "OS Error: Operation not permitted", + )) { err = "Cannot use chosen location"; } else { err = e.toString(); @@ -233,10 +296,11 @@ class _LoggingSettingsViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => StackOkDialog( - title: "Failed to change logs path", - message: err, - ), + builder: + (context) => StackOkDialog( + title: "Failed to change logs path", + message: err, + ), ), ); } @@ -245,9 +309,7 @@ class _LoggingSettingsViewState extends ConsumerState { } }, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/swb_file_system.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/swb_file_system.dart index 001279117..9954cb0b7 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/swb_file_system.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/swb_file_system.dart @@ -12,10 +12,11 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import '../../../../../app_config.dart'; +import '../../../../../utilities/stack_file_system.dart'; import '../../../../../utilities/util.dart'; class SWBFileSystem { @@ -29,13 +30,9 @@ class SWBFileSystem { Future prepareStorage() async { if (Platform.isAndroid) { - await Permission.storage.request(); - } - rootPath = (await getApplicationDocumentsDirectory()); - //todo: check if print needed - // debugPrint(rootPath!.absolute.toString()); - if (Platform.isAndroid) { - rootPath = Directory("/storage/emulated/0/"); + rootPath = await StackFileSystem.wtfAndroidDocumentsPath(); + } else { + rootPath = await getApplicationDocumentsDirectory(); } //todo: check if print needed // debugPrint(rootPath!.absolute.toString()); @@ -45,14 +42,11 @@ class SWBFileSystem { if (Platform.isIOS) { sampleFolder = Directory(rootPath!.path); - } else if (Platform.isAndroid) { - sampleFolder = Directory('${rootPath!.path}Documents/$dirName'); - } else if (Platform.isLinux) { - sampleFolder = Directory('${rootPath!.path}/$dirName'); - } else if (Platform.isWindows) { - sampleFolder = Directory('${rootPath!.path}/$dirName'); - } else if (Platform.isMacOS) { - sampleFolder = Directory('${rootPath!.path}/$dirName'); + } else if (Platform.isAndroid || + Platform.isLinux || + Platform.isWindows || + Platform.isMacOS) { + sampleFolder = Directory(path.join(rootPath!.path, dirName)); } try { @@ -86,9 +80,10 @@ class SWBFileSystem { if (Platform.isIOS) { chosenPath = startPath?.path; } else { - final String path = Platform.isWindows - ? startPath!.path.replaceAll("/", "\\") - : startPath!.path; + final String path = + Platform.isWindows + ? startPath!.path.replaceAll("/", "\\") + : startPath!.path; chosenPath = await FilePicker.platform.getDirectoryPath( dialogTitle: "Choose Backup location", initialDirectory: path, diff --git a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart index 4aff4afb0..aea4a8f02 100644 --- a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart +++ b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart @@ -3,8 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import '../../models/isar/models/blockchain_data/utxo.dart'; import '../../models/isar/ordinal.dart'; @@ -21,6 +21,7 @@ import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/prefs.dart'; import '../../utilities/show_loading.dart'; +import '../../utilities/stack_file_system.dart'; import '../../utilities/text_styles.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/desktop/desktop_app_bar.dart'; @@ -56,9 +57,10 @@ class _DesktopOrdinalDetailsViewState final response = await client.get( url: Uri.parse(widget.ordinal.content), - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); if (response.code != 200) { @@ -69,16 +71,15 @@ class _DesktopOrdinalDetailsViewState final bytes = response.bodyBytes; - if (Platform.isAndroid) { - await Permission.storage.request(); - } - - final dir = Platform.isAndroid - ? Directory("/storage/emulated/0/Documents") - : await getApplicationDocumentsDirectory(); + final dir = + Platform.isAndroid + ? await StackFileSystem.wtfAndroidDocumentsPath() + : await getApplicationDocumentsDirectory(); - final docPath = dir.path; - final filePath = "$docPath/ordinal_${widget.ordinal.inscriptionNumber}.png"; + final filePath = path.join( + dir.path, + "ordinal_${widget.ordinal.inscriptionNumber}.png", + ); final File imgFile = File(filePath); @@ -105,32 +106,27 @@ class _DesktopOrdinalDetailsViewState child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), AppBarIconButton( size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: Navigator.of(context).pop, ), - const SizedBox( - width: 18, - ), - Text( - "Ordinal details", - style: STextStyles.desktopH3(context), - ), + const SizedBox(width: 18), + Text("Ordinal details", style: STextStyles.desktopH3(context)), ], ), ), @@ -138,11 +134,7 @@ class _DesktopOrdinalDetailsViewState isCompactHeight: true, ), body: Padding( - padding: const EdgeInsets.only( - left: 24, - top: 24, - right: 24, - ), + padding: const EdgeInsets.only(left: 24, top: 24, right: 24), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -154,7 +146,8 @@ class _DesktopOrdinalDetailsViewState Constants.size.circularBorderRadius, ), child: Image.network( - widget.ordinal + widget + .ordinal .content, // Use the preview URL as the image source fit: BoxFit.cover, filterQuality: @@ -162,9 +155,7 @@ class _DesktopOrdinalDetailsViewState ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: SingleChildScrollView( child: Padding( @@ -187,9 +178,7 @@ class _DesktopOrdinalDetailsViewState ], ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), // PrimaryButton( // width: 150, // label: "Send", @@ -224,9 +213,10 @@ class _DesktopOrdinalDetailsViewState Assets.svg.arrowDown, width: 13, height: 18, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), buttonHeight: ButtonHeight.l, iconSpacing: 8, @@ -264,9 +254,7 @@ class _DesktopOrdinalDetailsViewState ], ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), RoundedWhiteContainer( padding: const EdgeInsets.all(16), child: Column( @@ -288,25 +276,28 @@ class _DesktopOrdinalDetailsViewState const _Divider(), Consumer( builder: (context, ref, _) { - final coin = ref - .watch(pWallets) - .getWallet(widget.walletId) - .info - .coin; + final coin = + ref + .watch(pWallets) + .getWallet(widget.walletId) + .info + .coin; return _DetailsItemWCopy( title: "Amount", - data: utxo == null - ? "ERROR" - : ref - .watch(pAmountFormatter(coin)) - .format( - Amount( - rawValue: - BigInt.from(utxo!.value), - fractionDigits: - coin.fractionDigits, - ), - ), + data: + utxo == null + ? "ERROR" + : ref + .watch(pAmountFormatter(coin)) + .format( + Amount( + rawValue: BigInt.from( + utxo!.value, + ), + fractionDigits: + coin.fractionDigits, + ), + ), ); }, ), @@ -341,9 +332,7 @@ class _Divider extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, - ), + padding: const EdgeInsets.symmetric(vertical: 16), child: Container( height: 1, color: Theme.of(context).extension()!.backgroundAppBar, @@ -353,11 +342,7 @@ class _Divider extends StatelessWidget { } class _DetailsItemWCopy extends StatelessWidget { - const _DetailsItemWCopy({ - super.key, - required this.title, - required this.data, - }); + const _DetailsItemWCopy({super.key, required this.title, required this.data}); final String title; final String data; @@ -370,22 +355,12 @@ class _DetailsItemWCopy extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - title, - style: STextStyles.itemSubtitle(context), - ), - IconCopyButton( - data: data, - ), + Text(title, style: STextStyles.itemSubtitle(context)), + IconCopyButton(data: data), ], ), - const SizedBox( - height: 4, - ), - SelectableText( - data, - style: STextStyles.itemSubtitle12(context), - ), + const SizedBox(height: 4), + SelectableText(data, style: STextStyles.itemSubtitle12(context)), ], ); } diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index 4f9bff090..7a254dffe 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -12,7 +12,6 @@ import 'dart:io'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; import '../app_config.dart'; import 'prefs.dart'; @@ -215,13 +214,11 @@ abstract class StackFileSystem { // TODO check this is correct for macos logsDir = Directory(path.join(appDocsDir.path, logsDirName)); } else if (Platform.isAndroid) { - await Permission.storage.request(); - final ext = await getExternalStorageDirectory(); - final rootPath = path.dirname( - path.dirname(path.dirname(path.dirname(ext!.path))), - ); - final logsDirPath = path.join(rootPath, "Documents", logsDirName); - logsDir = Directory(logsDirPath); + // final dir = await wtfAndroidDocumentsPath(); + // final logsDirPath = path.join(dir.path, logsDirName); + // logsDir = Directory(logsDirPath); + + logsDir = Directory(path.join(appDocsDir.path, "logs")); } else { throw Exception("Unsupported Platform"); } @@ -232,4 +229,18 @@ abstract class StackFileSystem { return logsDir; } + + static Future wtfAndroidDocumentsPath() async { + const base = "/storage/emulated/"; + final rootDir = await applicationRootDirectory(); + final parts = rootDir.path.replaceFirst("/data/user/", "").split("/"); + if (parts.isNotEmpty) { + final id = int.tryParse(parts.first); + + if (id != null) { + return Directory(path.join(base, id.toString(), "Documents")); + } + } + throw Exception("Unsupported Android flavor"); + } } diff --git a/scripts/app_config/templates/android/app/src/main/AndroidManifest.xml b/scripts/app_config/templates/android/app/src/main/AndroidManifest.xml index 07f7a3ef0..d10488cc9 100644 --- a/scripts/app_config/templates/android/app/src/main/AndroidManifest.xml +++ b/scripts/app_config/templates/android/app/src/main/AndroidManifest.xml @@ -5,12 +5,6 @@ android:name="android.permission.INTERNET"/> - - - Date: Thu, 22 May 2025 15:30:23 -0500 Subject: [PATCH 068/206] chore: add cs_salvium to pubspec and autogenerated plugin registrants etc --- linux/flutter/generated_plugin_registrant.cc | 4 ++++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 ++ scripts/app_config/templates/pubspec.template | 5 +++++ windows/flutter/generated_plugin_registrant.cc | 3 +++ windows/flutter/generated_plugins.cmake | 1 + 6 files changed, 16 insertions(+) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 88c196c5e..02b019f4d 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -21,6 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) cs_monero_flutter_libs_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "CsMoneroFlutterLibsLinuxPlugin"); cs_monero_flutter_libs_linux_plugin_register_with_registrar(cs_monero_flutter_libs_linux_registrar); + g_autoptr(FlPluginRegistrar) cs_salvium_flutter_libs_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "CsSalviumFlutterLibsLinuxPlugin"); + cs_salvium_flutter_libs_linux_plugin_register_with_registrar(cs_salvium_flutter_libs_linux_registrar); g_autoptr(FlPluginRegistrar) desktop_drop_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index aa67f97ac..8bca8e723 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST cs_monero_flutter_libs_linux + cs_salvium_flutter_libs_linux desktop_drop devicelocale flutter_libepiccash diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 245400e1a..8b28c002f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import camera_macos import connectivity_plus import cs_monero_flutter_libs_macos +import cs_salvium_flutter_libs_macos import desktop_drop import device_info_plus import devicelocale @@ -31,6 +32,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { CameraMacosPlugin.register(with: registry.registrar(forPlugin: "CameraMacosPlugin")) ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) CsMoneroFlutterLibsMacosPlugin.register(with: registry.registrar(forPlugin: "CsMoneroFlutterLibsMacosPlugin")) + CsSalviumFlutterLibsMacosPlugin.register(with: registry.registrar(forPlugin: "CsSalviumFlutterLibsMacosPlugin")) DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index b8d87d85a..2171e8cda 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -221,6 +221,11 @@ dependencies: drift: ^2.22.1 drift_flutter: ^0.2.3 path: ^1.9.1 +# cs_salvium: 1.0.0-pre.1 + cs_salvium: + path: ../cs_salvium/packages/cs_salvium + cs_salvium_flutter_libs: + path: ../cs_salvium/packages/cs_salvium_flutter_libs dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 74ef33c4e..63c954ce1 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); CsMoneroFlutterLibsWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("CsMoneroFlutterLibsWindowsPluginCApi")); + CsSalviumFlutterLibsWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("CsSalviumFlutterLibsWindowsPluginCApi")); DesktopDropPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopDropPlugin")); FlutterLibepiccashPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 55c2cc622..b7bea9e3f 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST camera_windows connectivity_plus cs_monero_flutter_libs_windows + cs_salvium_flutter_libs_windows desktop_drop flutter_libepiccash flutter_secure_storage_windows From 1369d8ffcac60f942bedf8b7b924b07e1d267188 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 22 May 2025 16:57:04 -0500 Subject: [PATCH 069/206] feat: add wip salvium wallet files --- .../crypto_currency/coins/salvium.dart | 124 ++++++++++++++++ .../crypto_currency/crypto_currency.dart | 1 + lib/wallets/wallet/impl/salvium_wallet.dart | 134 ++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 lib/wallets/crypto_currency/coins/salvium.dart create mode 100644 lib/wallets/wallet/impl/salvium_wallet.dart diff --git a/lib/wallets/crypto_currency/coins/salvium.dart b/lib/wallets/crypto_currency/coins/salvium.dart new file mode 100644 index 000000000..fe4d8f64d --- /dev/null +++ b/lib/wallets/crypto_currency/coins/salvium.dart @@ -0,0 +1,124 @@ +import 'package:cs_salvium/src/ffi_bindings/salvium_wallet_bindings.dart' + as sal_wallet_ffi; + +import '../../../models/node_model.dart'; +import '../../../utilities/default_nodes.dart'; +import '../../../utilities/enums/derive_path_type_enum.dart'; +import '../crypto_currency.dart'; +import '../intermediate/cryptonote_currency.dart'; + +class Salvium extends CryptonoteCurrency { + Salvium(super.network) { + _idMain = "salvium"; + _uriScheme = "salvium"; + switch (network) { + case CryptoCurrencyNetwork.main: + _id = _idMain; + _name = "Salvium"; + _ticker = "SAL"; + default: + throw Exception("Unsupported network: $network"); + } + } + + late final String _id; + @override + String get identifier => _id; + + late final String _idMain; + @override + String get mainNetId => _idMain; + + late final String _name; + @override + String get prettyName => _name; + + late final String _uriScheme; + @override + String get uriScheme => _uriScheme; + + late final String _ticker; + @override + String get ticker => _ticker; + + @override + int get minConfirms => 10; + + @override + bool get torSupport => true; + + @override + bool validateAddress(String address) { + if (address.contains("111")) { + return false; + } + switch (network) { + case CryptoCurrencyNetwork.main: + return sal_wallet_ffi.validateAddress(address, 0); + default: + throw Exception("Unsupported network: $network"); + } + } + + @override + NodeModel get defaultNode { + switch (network) { + case CryptoCurrencyNetwork.main: + return NodeModel( + host: "https://salvium.stackwallet.com", + port: 19081, + name: DefaultNodes.defaultName, + id: DefaultNodes.buildId(this), + useSSL: true, + enabled: true, + coinName: identifier, + isFailover: true, + isDown: false, + trusted: true, + torEnabled: true, + clearnetEnabled: true, + ); + + default: + throw UnimplementedError(); + } + } + + @override + int get defaultSeedPhraseLength => 25; + + @override + int get fractionDigits => 12; + + @override + bool get hasBuySupport => false; + + @override + bool get hasMnemonicPassphraseSupport => false; + + @override + List get possibleMnemonicLengths => [defaultSeedPhraseLength]; + + @override + BigInt get satsPerCoin => BigInt.from(1000000000000); + + @override + int get targetBlockTimeSeconds => 120; + + @override + DerivePathType get defaultDerivePathType => throw UnsupportedError( + "$runtimeType does not use bitcoin style derivation paths", + ); + + @override + Uri defaultBlockExplorer(String txid) { + switch (network) { + case CryptoCurrencyNetwork.main: + return Uri.parse("https://explorer.salvium.io//tx/$txid"); + default: + throw Exception( + "Unsupported network for defaultBlockExplorer(): $network", + ); + } + } +} diff --git a/lib/wallets/crypto_currency/crypto_currency.dart b/lib/wallets/crypto_currency/crypto_currency.dart index d5553ceca..773128bbb 100644 --- a/lib/wallets/crypto_currency/crypto_currency.dart +++ b/lib/wallets/crypto_currency/crypto_currency.dart @@ -19,6 +19,7 @@ export 'coins/namecoin.dart'; export 'coins/nano.dart'; export 'coins/particl.dart'; export 'coins/peercoin.dart'; +export 'coins/salvium.dart'; export 'coins/solana.dart'; export 'coins/stellar.dart'; export 'coins/tezos.dart'; diff --git a/lib/wallets/wallet/impl/salvium_wallet.dart b/lib/wallets/wallet/impl/salvium_wallet.dart new file mode 100644 index 000000000..c04baed27 --- /dev/null +++ b/lib/wallets/wallet/impl/salvium_wallet.dart @@ -0,0 +1,134 @@ +import 'dart:async'; + +import 'package:compat/compat.dart' as lib_salvium_compat; +import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; + +import '../../../utilities/amount/amount.dart'; +import '../../crypto_currency/crypto_currency.dart'; +import '../intermediate/lib_monero_wallet.dart'; + +class SalviumWallet extends LibMoneroWallet { + SalviumWallet(CryptoCurrencyNetwork network) + : super(Salvium(network), lib_salvium_compat.WalletType.salvium); + + @override + Future estimateFeeFor(Amount amount, BigInt feeRate) async { + if (libMoneroWallet == null || + syncStatus is! lib_salvium_compat.SyncedSyncStatus) { + return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); + } + + lib_salvium.TransactionPriority priority; + switch (feeRate.toInt()) { + case 1: + priority = lib_salvium.TransactionPriority.low; + break; + case 2: + priority = lib_salvium.TransactionPriority.medium; + break; + case 3: + priority = lib_salvium.TransactionPriority.high; + break; + case 4: + priority = lib_salvium.TransactionPriority.last; + break; + case 0: + default: + priority = lib_salvium.TransactionPriority.normal; + break; + } + + int approximateFee = 0; + await estimateFeeMutex.protect(() async { + approximateFee = await libMoneroWallet!.estimateFee( + priority, + amount.raw.toInt(), + ); + }); + + return Amount( + rawValue: BigInt.from(approximateFee), + fractionDigits: cryptoCurrency.fractionDigits, + ); + } + + @override + bool walletExists(String path) => lib_salvium.SalviumWallet.isWalletExist(path); + + @override + Future loadWallet({ + required String path, + required String password, + }) async { + libMoneroWallet = await lib_salvium.SalviumWallet.loadWallet( + path: path, + password: password, + ); + } + + @override + Future getCreatedWallet({ + required String path, + required String password, + required int wordCount, + required String seedOffset, + }) async { + final lib_salvium.SalviumSeedType type; + switch (wordCount) { + case 16: + type = lib_salvium.SalviumSeedType.sixteen; + break; + + case 25: + type = lib_salvium.SalviumSeedType.twentyFive; + break; + + default: + throw Exception("Invalid mnemonic word count: $wordCount"); + } + + return await lib_salvium.SalviumWallet.create( + path: path, + password: password, + seedType: type, + seedOffset: seedOffset, + ); + } + + @override + Future getRestoredWallet({ + required String path, + required String password, + required String mnemonic, + required String seedOffset, + int height = 0, + }) async => await lib_salvium.SalviumWallet.restoreWalletFromSeed( + path: path, + password: password, + seed: mnemonic, + restoreHeight: height, + seedOffset: seedOffset, + ); + + @override + Future getRestoredFromViewKeyWallet({ + required String path, + required String password, + required String address, + required String privateViewKey, + int height = 0, + }) async => lib_salvium.SalviumWallet.createViewOnlyWallet( + path: path, + password: password, + address: address, + viewKey: privateViewKey, + restoreHeight: height, + ); + + @override + void invalidSeedLengthCheck(int length) { + if (length != 25 && length != 16) { + throw Exception("Invalid salvium mnemonic length found: $length"); + } + } +} From b8cbffdb7f00514c2b92be5d462bdff0822dbce9 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 22 May 2025 16:57:20 -0500 Subject: [PATCH 070/206] chore: ignore working theme dir(s) --- asset_sources/default_themes/stack_wallet/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 asset_sources/default_themes/stack_wallet/.gitignore diff --git a/asset_sources/default_themes/stack_wallet/.gitignore b/asset_sources/default_themes/stack_wallet/.gitignore new file mode 100644 index 000000000..49f4a6294 --- /dev/null +++ b/asset_sources/default_themes/stack_wallet/.gitignore @@ -0,0 +1,2 @@ +light/ +dark/ From d2a566e971d50606114bc3580f262f6f18d31a66 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 23 May 2025 10:15:49 -0600 Subject: [PATCH 071/206] fix mobile nav issue --- lib/pages/spark_names/buy_spark_name_view.dart | 2 +- lib/route_generator.dart | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart index 94c868e9d..01f69fcaf 100644 --- a/lib/pages/spark_names/buy_spark_name_view.dart +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -142,7 +142,7 @@ class _BuySparkNameViewState extends ConsumerState { } else { await Navigator.of(context).pushNamed( ConfirmSparkNameTransactionView.routeName, - arguments: (txData, widget.walletId), + arguments: (walletId: widget.walletId, txData: txData), ); } } diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 65f2df473..629a3a1a7 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -150,6 +150,7 @@ import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_setting import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart'; import 'pages/spark_names/buy_spark_name_view.dart'; +import 'pages/spark_names/confirm_spark_name_transaction_view.dart'; import 'pages/spark_names/spark_names_home_view.dart'; import 'pages/spark_names/sub_widgets/spark_name_details.dart'; import 'pages/special/firo_rescan_recovery_error_dialog.dart'; @@ -842,6 +843,20 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case ConfirmSparkNameTransactionView.routeName: + if (args is ({String walletId, TxData txData})) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => ConfirmSparkNameTransactionView( + walletId: args.walletId, + txData: args.txData, + ), + settings: RouteSettings(name: settings.name), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case SparkNameDetailsView.routeName: if (args is ({String walletId, SparkName name})) { return getRoute( From b570d6ed1686814f7ba22b7308e02d402c86a28b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 13:37:01 -0500 Subject: [PATCH 072/206] feat: add libSalviumWallet workaround --- lib/wallets/wallet/impl/salvium_wallet.dart | 20 +- .../intermediate/lib_salvium_wallet.dart | 1507 +++++++++++++++++ 2 files changed, 1515 insertions(+), 12 deletions(-) create mode 100644 lib/wallets/wallet/intermediate/lib_salvium_wallet.dart diff --git a/lib/wallets/wallet/impl/salvium_wallet.dart b/lib/wallets/wallet/impl/salvium_wallet.dart index c04baed27..29555ef62 100644 --- a/lib/wallets/wallet/impl/salvium_wallet.dart +++ b/lib/wallets/wallet/impl/salvium_wallet.dart @@ -1,20 +1,20 @@ import 'dart:async'; -import 'package:compat/compat.dart' as lib_salvium_compat; +import 'package:compat/compat.dart' as lib_monero_compat; import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; import '../../../utilities/amount/amount.dart'; import '../../crypto_currency/crypto_currency.dart'; -import '../intermediate/lib_monero_wallet.dart'; +import '../intermediate/lib_salvium_wallet.dart'; -class SalviumWallet extends LibMoneroWallet { +class SalviumWallet extends LibSalviumWallet { SalviumWallet(CryptoCurrencyNetwork network) - : super(Salvium(network), lib_salvium_compat.WalletType.salvium); + : super(Salvium(network), lib_monero_compat.WalletType.salvium); @override Future estimateFeeFor(Amount amount, BigInt feeRate) async { - if (libMoneroWallet == null || - syncStatus is! lib_salvium_compat.SyncedSyncStatus) { + if (libSalviumWallet == null || + syncStatus is! lib_monero_compat.SyncedSyncStatus) { return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } @@ -40,7 +40,7 @@ class SalviumWallet extends LibMoneroWallet { int approximateFee = 0; await estimateFeeMutex.protect(() async { - approximateFee = await libMoneroWallet!.estimateFee( + approximateFee = await libSalviumWallet!.estimateFee( priority, amount.raw.toInt(), ); @@ -60,7 +60,7 @@ class SalviumWallet extends LibMoneroWallet { required String path, required String password, }) async { - libMoneroWallet = await lib_salvium.SalviumWallet.loadWallet( + libSalviumWallet = await lib_salvium.SalviumWallet.loadWallet( path: path, password: password, ); @@ -75,10 +75,6 @@ class SalviumWallet extends LibMoneroWallet { }) async { final lib_salvium.SalviumSeedType type; switch (wordCount) { - case 16: - type = lib_salvium.SalviumSeedType.sixteen; - break; - case 25: type = lib_salvium.SalviumSeedType.twentyFive; break; diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart new file mode 100644 index 000000000..be26f5b22 --- /dev/null +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -0,0 +1,1507 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:compat/compat.dart' as lib_monero_compat; +import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; +import 'package:isar/isar.dart'; +import 'package:mutex/mutex.dart'; +import 'package:stack_wallet_backup/generate_password.dart'; + +import '../../../db/hive/db.dart'; +import '../../../models/balance.dart'; +import '../../../models/isar/models/blockchain_data/address.dart'; +import '../../../models/isar/models/blockchain_data/transaction.dart'; +import '../../../models/isar/models/blockchain_data/utxo.dart'; +import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; +import '../../../models/keys/cw_key_data.dart'; +import '../../../models/keys/view_only_wallet_data.dart'; +import '../../../models/paymint/fee_object_model.dart'; +import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; +import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; +import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import '../../../services/event_bus/events/global/tor_status_changed_event.dart'; +import '../../../services/event_bus/events/global/updated_in_background_event.dart'; +import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import '../../../services/event_bus/global_event_bus.dart'; +import '../../../services/tor_service.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/enums/fee_rate_type_enum.dart'; +import '../../../utilities/logger.dart'; +import '../../../utilities/stack_file_system.dart'; +import '../../crypto_currency/intermediate/cryptonote_currency.dart'; +import '../../isar/models/wallet_info.dart'; +import '../../models/tx_data.dart'; +import '../wallet.dart'; +import '../wallet_mixin_interfaces/multi_address_interface.dart'; +import '../wallet_mixin_interfaces/view_only_option_interface.dart'; +import 'cryptonote_wallet.dart'; + +abstract class LibSalviumWallet + extends CryptonoteWallet + with ViewOnlyOptionInterface + implements MultiAddressInterface { + @override + int get isarTransactionVersion => 2; + + LibSalviumWallet(super.currency, this.compatType) { + final bus = GlobalEventBus.instance; + + // Listen for tor status changes. + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + if (!_torConnectingLock.isLocked) { + await _torConnectingLock.acquire(); + } + _requireMutex = true; + break; + + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + _requireMutex = false; + break; + } + }); + + // Listen for tor preference changes. + _torPreferenceListener = bus.on().listen(( + event, + ) async { + await updateNode(); + }); + + // Potentially dangerous hack. See comments in _startInit() + _startInit(); + } + // cw based wallet listener to handle synchronization of utxo frozen states + late final StreamSubscription> _streamSub; + Future _startInit() async { + // Delay required as `mainDB` is not initialized in constructor. + // This is a hack and could lead to a race condition. + Future.delayed(const Duration(seconds: 2), () { + _streamSub = mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .watch(fireImmediately: true) + .listen((utxos) async { + try { + await onUTXOsChanged(utxos); + await updateBalance(shouldUpdateUtxos: false); + } catch (e, s) { + lib_salvium.Logging.log?.i("_startInit", error: e, stackTrace: s); + } + }); + }); + } + + final lib_monero_compat.WalletType compatType; + lib_salvium.Wallet? libSalviumWallet; + + lib_monero_compat.SyncStatus? get syncStatus => _syncStatus; + lib_monero_compat.SyncStatus? _syncStatus; + int _syncedCount = 0; + void _setSyncStatus(lib_monero_compat.SyncStatus status) { + if (status is lib_monero_compat.SyncedSyncStatus) { + if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { + _syncedCount++; + } + } else { + _syncedCount = 0; + } + + if (_syncedCount < 3) { + _syncStatus = status; + syncStatusChanged(); + } + } + + final prepareSendMutex = Mutex(); + final estimateFeeMutex = Mutex(); + + bool _txRefreshLock = false; + int _lastCheckedHeight = -1; + int _txCount = 0; + int currentKnownChainHeight = 0; + double highestPercentCached = 0; + + Future loadWallet({required String path, required String password}); + + Future getCreatedWallet({ + required String path, + required String password, + required int wordCount, + required String seedOffset, + }); + + Future getRestoredWallet({ + required String path, + required String password, + required String mnemonic, + required String seedOffset, + int height = 0, + }); + + Future getRestoredFromViewKeyWallet({ + required String path, + required String password, + required String address, + required String privateViewKey, + int height = 0, + }); + + void invalidSeedLengthCheck(int length); + + bool walletExists(String path); + + String getTxKeyFor({required String txid}) { + if (libSalviumWallet == null) { + throw Exception("Cannot get tx key in uninitialized libSalviumWallet"); + } + return libSalviumWallet!.getTxKey(txid); + } + + void _setListener() { + if (libSalviumWallet != null && libSalviumWallet!.getListeners().isEmpty) { + libSalviumWallet?.addListener( + lib_salvium.WalletListener( + onSyncingUpdate: onSyncingUpdate, + onNewBlock: onNewBlock, + onBalancesChanged: onBalancesChanged, + onError: (e, s) { + Logging.instance.w("$e\n$s", error: e, stackTrace: s); + }, + ), + ); + } + } + + @override + Future open() async { + bool wasNull = false; + + if (libSalviumWallet == null) { + wasNull = true; + // libSalviumWalletT?.close(); + final path = await pathForWallet(name: walletId, type: compatType); + + final String password; + try { + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; + } catch (e, s) { + throw Exception("Password not found $e, $s"); + } + + await loadWallet(path: path, password: password); + + _setListener(); + + await updateNode(); + } + + Address? currentAddress = await getCurrentReceivingAddress(); + if (currentAddress == null) { + currentAddress = addressFor(index: 0); + await mainDB.updateOrPutAddresses([currentAddress]); + } + if (info.cachedReceivingAddress != currentAddress.value) { + await info.updateReceivingAddress( + newAddress: currentAddress.value, + isar: mainDB.isar, + ); + } + + if (wasNull) { + try { + _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + libSalviumWallet?.startSyncing(); + } catch (_) { + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // TODO log + } + } + _setListener(); + libSalviumWallet?.startListeners(); + libSalviumWallet?.startAutoSaving(); + + unawaited(refresh()); + } + + @Deprecated("Only used in the case of older wallets") + lib_monero_compat.WalletInfo? getLibSalviumWalletInfo(String walletId) { + try { + return DB.instance.moneroWalletInfoBox.values.firstWhere( + (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), + ); + } catch (_) { + return null; + } + } + + Future save() async { + if (!Platform.isWindows) { + final appRoot = await StackFileSystem.applicationRootDirectory(); + await lib_monero_compat.backupWalletFiles( + name: walletId, + type: compatType, + appRoot: appRoot, + ); + } + await libSalviumWallet!.save(); + } + + Address addressFor({required int index, int account = 0}) { + final address = libSalviumWallet!.getAddress( + accountIndex: account, + addressIndex: index, + ); + + if (address.value.contains("111")) { + throw Exception("111 address found!"); + } + + final newReceivingAddress = Address( + walletId: walletId, + derivationIndex: index, + derivationPath: null, + value: address.value, + publicKey: [], + type: AddressType.cryptonote, + subType: AddressSubType.receiving, + ); + + return newReceivingAddress; + } + + Future getKeys() async { + final base = libSalviumWallet; + + final oldInfo = getLibSalviumWalletInfo(walletId); + if (base == null || (oldInfo != null && oldInfo.name != walletId)) { + return null; + } + try { + return CWKeyData( + walletId: walletId, + publicViewKey: base.getPublicViewKey(), + privateViewKey: base.getPrivateViewKey(), + publicSpendKey: base.getPublicSpendKey(), + privateSpendKey: base.getPrivateSpendKey(), + ); + } catch (e, s) { + Logging.instance.f("getKeys failed: ", error: e, stackTrace: s); + return CWKeyData( + walletId: walletId, + publicViewKey: "ERROR", + privateViewKey: "ERROR", + publicSpendKey: "ERROR", + privateSpendKey: "ERROR", + ); + } + } + + Future<(String, String)> + hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { + final path = await pathForWallet(name: walletId, type: compatType); + final String password; + try { + password = + (await secureStorageInterface.read( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + ))!; + } catch (e, s) { + throw Exception("Password not found $e, $s"); + } + await loadWallet(path: path, password: password); + final wallet = libSalviumWallet!; + return (wallet.getAddress().value, wallet.getPrivateViewKey()); + } + + @override + Future init({bool? isRestore, int? wordCount}) async { + final path = await pathForWallet(name: walletId, type: compatType); + if (!(walletExists(path)) && isRestore != true) { + if (wordCount == null) { + throw Exception("Missing word count for new xmr/wow wallet!"); + } + try { + final password = generatePassword(); + await secureStorageInterface.write( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + value: password, + ); + final wallet = await getCreatedWallet( + path: path, + password: password, + wordCount: wordCount, + seedOffset: "", // default for non restored wallets for now + ); + + final height = wallet.getRefreshFromBlockHeight(); + + await info.updateRestoreHeight( + newRestoreHeight: height, + isar: mainDB.isar, + ); + + // special case for xmr/wow. Normally mnemonic + passphrase is saved + // before wallet.init() is called + await secureStorageInterface.write( + key: Wallet.mnemonicKey(walletId: walletId), + value: wallet.getSeed().trim(), + ); + await secureStorageInterface.write( + key: Wallet.mnemonicPassphraseKey(walletId: walletId), + value: "", + ); + } catch (e, s) { + Logging.instance.f("", error: e, stackTrace: s); + } + await updateNode(); + } + + return super.init(); + } + + @override + Future recover({required bool isRescan}) async { + if (isRescan) { + await refreshMutex.protect(() async { + // clear blockchain info + await mainDB.deleteWalletBlockchainData(walletId); + + highestPercentCached = 0; + unawaited(libSalviumWallet?.rescanBlockchain()); + libSalviumWallet?.startSyncing(); + // unawaited(save()); + }); + unawaited(refresh()); + return; + } + + if (isViewOnly) { + await recoverViewOnly(); + return; + } + + await refreshMutex.protect(() async { + final mnemonic = await getMnemonic(); + final seedOffset = await getMnemonicPassphrase(); + final seedLength = mnemonic.trim().split(" ").length; + + invalidSeedLengthCheck(seedLength); + + try { + final height = max(info.restoreHeight, 0); + + await info.updateRestoreHeight( + newRestoreHeight: height, + isar: mainDB.isar, + ); + + final String name = walletId; + + final path = await pathForWallet(name: name, type: compatType); + + try { + final password = generatePassword(); + await secureStorageInterface.write( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + value: password, + ); + final wallet = await getRestoredWallet( + path: path, + password: password, + mnemonic: mnemonic, + height: height, + seedOffset: seedOffset, + ); + + if (libSalviumWallet != null) { + await exit(); + } + + libSalviumWallet = wallet; + + _setListener(); + + final newReceivingAddress = + await getCurrentReceivingAddress() ?? + Address( + walletId: walletId, + derivationIndex: 0, + derivationPath: null, + value: wallet.getAddress().value, + publicKey: [], + type: AddressType.cryptonote, + subType: AddressSubType.receiving, + ); + + await mainDB.updateOrPutAddresses([newReceivingAddress]); + await info.updateReceivingAddress( + newAddress: newReceivingAddress.value, + isar: mainDB.isar, + ); + } catch (e, s) { + Logging.instance.f("", error: e, stackTrace: s); + rethrow; + } + await updateNode(); + _setListener(); + + // libSalviumWallet?.setRecoveringFromSeed(isRecovery: true); + unawaited(libSalviumWallet?.rescanBlockchain()); + libSalviumWallet?.startSyncing(); + + // await save(); + libSalviumWallet?.startListeners(); + libSalviumWallet?.startAutoSaving(); + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from recoverFromMnemonic(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + }); + } + + @override + Future pingCheck() async { + return (await libSalviumWallet?.isConnectedToDaemon()) ?? false; + } + + @override + Future updateNode() async { + final node = getCurrentNode(); + + final host = + node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; + ({InternetAddress host, int port})? proxy; + if (prefs.useTor) { + if (node.clearnetEnabled && !node.torEnabled) { + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + throw Exception("TOR - clearnet mismatch"); + } + proxy = TorService.sharedInstance.getProxyInfo(); + } else { + if (!node.clearnetEnabled && node.torEnabled) { + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + throw Exception("TOR - clearnet mismatch"); + } + } + + _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + try { + if (_requireMutex) { + await _torConnectingLock.protect(() async { + await libSalviumWallet?.connect( + daemonAddress: "$host:${node.port}", + daemonUsername: node.loginName, + daemonPassword: await node.getPassword(secureStorageInterface), + trusted: node.trusted ?? false, + useSSL: node.useSSL, + socksProxyAddress: + node.forceNoTor + ? null + : proxy == null + ? null + : "${proxy.host.address}:${proxy.port}", + ); + }); + } else { + await libSalviumWallet?.connect( + daemonAddress: "$host:${node.port}", + daemonUsername: node.loginName, + daemonPassword: await node.getPassword(secureStorageInterface), + trusted: node.trusted ?? false, + useSSL: node.useSSL, + socksProxyAddress: + node.forceNoTor + ? null + : proxy == null + ? null + : "${proxy.host.address}:${proxy.port}", + ); + } + libSalviumWallet?.startSyncing(); + libSalviumWallet?.startListeners(); + libSalviumWallet?.startAutoSaving(); + + _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); + } catch (e, s) { + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + Logging.instance.e( + "Exception caught in $runtimeType.updateNode(): ", + error: e, + stackTrace: s, + ); + } + + return; + } + + @override + Future updateTransactions() async { + final base = libSalviumWallet; + + if (base == null) { + return; + } + + final localTxids = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .heightGreaterThan(0) + .txidProperty() + .findAll(); + + final allTxids = await base.getAllTxids(refresh: true); + + final txidsToFetch = allTxids.toSet().difference(localTxids.toSet()); + + if (txidsToFetch.isEmpty) { + return; + } + + final transactions = await base.getTxs(txids: txidsToFetch, refresh: false); + + final allOutputs = await base.getOutputs(includeSpent: true, refresh: true); + + // final cachedTransactions = + // DB.instance.get(boxName: walletId, key: 'latest_tx_model') + // as TransactionData?; + // int latestTxnBlockHeight = + // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight") + // as int? ?? + // 0; + // + // final txidsList = DB.instance + // .get(boxName: walletId, key: "cachedTxids") as List? ?? + // []; + // + // final Set cachedTxids = Set.from(txidsList); + + // TODO: filter to skip cached + confirmed txn processing in next step + // final unconfirmedCachedTransactions = + // cachedTransactions?.getAllTransactions() ?? {}; + // unconfirmedCachedTransactions + // .removeWhere((key, value) => value.confirmedStatus); + // + // if (cachedTransactions != null) { + // for (final tx in allTxHashes.toList(growable: false)) { + // final txHeight = tx["height"] as int; + // if (txHeight > 0 && + // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) { + // if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) { + // allTxHashes.remove(tx); + // } + // } + // } + // } + + final List txns = []; + + for (final tx in transactions) { + final associatedOutputs = allOutputs.where((e) => e.hash == tx.hash); + final List inputs = []; + final List outputs = []; + TransactionType type; + if (!tx.isSpend) { + type = TransactionType.incoming; + for (final output in associatedOutputs) { + outputs.add( + OutputV2.isarCantDoRequiredInDefaultConstructor( + scriptPubKeyHex: "", + valueStringSats: output.value.toString(), + addresses: [output.address], + walletOwns: true, + ), + ); + } + } else { + type = TransactionType.outgoing; + for (final output in associatedOutputs) { + inputs.add( + InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: null, + scriptSigAsm: null, + sequence: null, + outpoint: null, + addresses: [output.address], + valueStringSats: output.value.toString(), + witness: null, + innerRedeemScriptAsm: null, + coinbase: null, + walletOwns: true, + ), + ); + } + } + + final txn = TransactionV2( + walletId: walletId, + blockHash: null, // not exposed via current cs_salvium + hash: tx.hash, + txid: tx.hash, + timestamp: (tx.timeStamp.millisecondsSinceEpoch ~/ 1000), + height: tx.blockHeight, + inputs: inputs, + outputs: outputs, + version: -1, // not exposed via current cs_salvium + type: type, + subType: TransactionSubType.none, + otherData: jsonEncode({ + TxV2OdKeys.overrideFee: + Amount( + rawValue: tx.fee, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), + TxV2OdKeys.moneroAmount: + Amount( + rawValue: tx.amount, + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), + TxV2OdKeys.moneroAccountIndex: tx.accountIndex, + TxV2OdKeys.isMoneroTransaction: true, + }), + ); + + txns.add(txn); + } + + await mainDB.updateOrPutTransactionV2s(txns); + } + + Future get availableBalance async { + try { + return Amount( + rawValue: libSalviumWallet!.getUnlockedBalance(), + fractionDigits: cryptoCurrency.fractionDigits, + ); + } catch (_) { + return info.cachedBalance.spendable; + } + } + + Future get totalBalance async { + try { + final full = libSalviumWallet?.getBalance(); + if (full != null) { + return Amount( + rawValue: full, + fractionDigits: cryptoCurrency.fractionDigits, + ); + } else { + final transactions = await libSalviumWallet!.getAllTxs(refresh: true); + BigInt transactionBalance = BigInt.zero; + for (final tx in transactions) { + if (!tx.isSpend) { + transactionBalance += tx.amount; + } else { + transactionBalance += -tx.amount - tx.fee; + } + } + + return Amount( + rawValue: transactionBalance, + fractionDigits: cryptoCurrency.fractionDigits, + ); + } + } catch (_) { + return info.cachedBalance.total; + } + } + + @override + Future exit() async { + Logging.instance.i("exit called on $walletId"); + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + await libSalviumWallet?.save(); + } + + Future pathForWalletDir({ + required String name, + required lib_monero_compat.WalletType type, + }) async { + final Directory root = await StackFileSystem.applicationRootDirectory(); + return lib_monero_compat.pathForWalletDir( + name: name, + type: type.name.toLowerCase(), + appRoot: root, + ); + } + + Future pathForWallet({ + required String name, + required lib_monero_compat.WalletType type, + }) async => await pathForWalletDir( + name: name, + type: type, + ).then((path) => '$path/$name'); + + void onSyncingUpdate({ + required int syncHeight, + required int nodeHeight, + String? message, + }) { + if (nodeHeight > 0 && syncHeight >= 0) { + currentKnownChainHeight = nodeHeight; + updateChainHeight(); + final blocksLeft = nodeHeight - syncHeight; + final lib_monero_compat.SyncStatus status; + if (blocksLeft < 100) { + status = lib_monero_compat.SyncedSyncStatus(); + + // if (!_hasSyncAfterStartup) { + // _hasSyncAfterStartup = true; + // await save(); + // } + // + // if (walletInfo.isRecovery!) { + // await setAsRecovered(); + // } + } else { + final percent = syncHeight / currentKnownChainHeight; + + status = lib_monero_compat.SyncingSyncStatus( + blocksLeft, + percent, + currentKnownChainHeight, + ); + } + + _setSyncStatus(status); + _refreshTxDataHelper(); + } + } + + void onBalancesChanged({ + required BigInt newBalance, + required BigInt newUnlockedBalance, + }) async { + try { + await updateBalance(); + await updateTransactions(); + } catch (e, s) { + Logging.instance.w("onBalancesChanged(): ", error: e, stackTrace: s); + } + } + + void onNewBlock(int nodeHeight) async { + try { + await updateTransactions(); + } catch (e, s) { + Logging.instance.w("onNewBlock(): ", error: e, stackTrace: s); + } + } + + final _utxosUpdateLock = Mutex(); + Future onUTXOsChanged(List utxos) async { + await _utxosUpdateLock.protect(() async { + final cwUtxos = await libSalviumWallet?.getOutputs(refresh: true) ?? []; + + // bool changed = false; + + for (final cw in cwUtxos) { + final match = utxos.where( + (e) => + e.keyImage != null && + e.keyImage!.isNotEmpty && + e.keyImage == cw.keyImage, + ); + + if (match.isNotEmpty) { + final u = match.first; + + if (u.isBlocked) { + if (!cw.isFrozen) { + await libSalviumWallet?.freezeOutput(cw.keyImage); + // changed = true; + } + } else { + if (cw.isFrozen) { + await libSalviumWallet?.thawOutput(cw.keyImage); + // changed = true; + } + } + } + } + + // if (changed) { + // await libSalviumWallet?.updateUTXOs(); + // } + }); + } + + void onNewTransaction() { + // TODO: [prio=low] get rid of UpdatedInBackgroundEvent and move to + // adding the v2 tx to the db which would update ui automagically since the + // db is watched by the ui + // call this here? + GlobalEventBus.instance.fire( + UpdatedInBackgroundEvent( + "New data found in $walletId ${info.name} in background!", + walletId, + ), + ); + } + + void syncStatusChanged() async { + final _syncStatus = syncStatus; + + if (_syncStatus != null) { + if (_syncStatus.progress() == 1 && refreshMutex.isLocked) { + refreshMutex.release(); + } + + WalletSyncStatus? status; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true); + + if (_syncStatus is lib_monero_compat.SyncingSyncStatus) { + final int blocksLeft = _syncStatus.blocksLeft; + + // ensure at least 1 to prevent math errors + final int height = max(1, _syncStatus.height); + + final nodeHeight = height + blocksLeft; + currentKnownChainHeight = nodeHeight; + + // final percent = height / nodeHeight; + final percent = _syncStatus.ptc; + + final highest = max(highestPercentCached, percent); + + final unchanged = highest == highestPercentCached; + if (unchanged) { + return; + } + + // update cached + if (highestPercentCached < percent) { + highestPercentCached = percent; + } + + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highest, walletId), + ); + GlobalEventBus.instance.fire( + BlocksRemainingEvent(blocksLeft, walletId), + ); + } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { + status = WalletSyncStatus.synced; + } else if (_syncStatus is lib_monero_compat.NotConnectedSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } + + if (status != null) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent(status, walletId, info.coin), + ); + } + } + } + + @override + Future checkSaveInitialReceivingAddress() async { + // this doesn't work without opening the wallet first which takes a while + } + + // ============ Private ====================================================== + Future _refreshTxDataHelper() async { + if (_txRefreshLock) return; + _txRefreshLock = true; + + final _syncStatus = syncStatus; + + if (_syncStatus != null && + _syncStatus is lib_monero_compat.SyncingSyncStatus) { + final int blocksLeft = _syncStatus.blocksLeft; + final tenKChange = blocksLeft ~/ 10000; + + // only refresh transactions periodically during a sync + if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) { + _lastCheckedHeight = tenKChange; + await _refreshTxData(); + } + } else { + await _refreshTxData(); + } + + _txRefreshLock = false; + } + + Future _refreshTxData() async { + await updateTransactions(); + final count = await mainDB.getTransactions(walletId).count(); + + if (count > _txCount) { + _txCount = count; + await updateBalance(); + GlobalEventBus.instance.fire( + UpdatedInBackgroundEvent( + "New transaction data found in $walletId ${info.name}!", + walletId, + ), + ); + } + } + + // ============ Overrides ==================================================== + + @override + FilterOperation? get changeAddressFilterOperation => null; + + @override + FilterOperation? get receivingAddressFilterOperation => null; + + @override + Future updateUTXOs() async { + final List outputArray = []; + final utxos = + await libSalviumWallet?.getOutputs(refresh: true) ?? + []; + for (final rawUTXO in utxos) { + if (!rawUTXO.spent) { + final current = + await mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .voutEqualTo(rawUTXO.vout) + .and() + .txidEqualTo(rawUTXO.hash) + .findFirst(); + final tx = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(rawUTXO.hash) + .findFirst(); + + final otherDataMap = { + UTXOOtherDataKeys.keyImage: rawUTXO.keyImage, + UTXOOtherDataKeys.spent: rawUTXO.spent, + }; + + final utxo = UTXO( + address: rawUTXO.address, + walletId: walletId, + txid: rawUTXO.hash, + vout: rawUTXO.vout, + value: rawUTXO.value.toInt(), + name: current?.name ?? "", + isBlocked: current?.isBlocked ?? rawUTXO.isFrozen, + blockedReason: current?.blockedReason ?? "", + isCoinbase: rawUTXO.coinbase, + blockHash: "", + blockHeight: + tx?.height ?? (rawUTXO.height > 0 ? rawUTXO.height : null), + blockTime: tx?.timestamp, + otherData: jsonEncode(otherDataMap), + ); + + outputArray.add(utxo); + } + } + + await mainDB.updateUTXOs(walletId, outputArray); + + return true; + } + + @override + Future updateBalance({bool shouldUpdateUtxos = true}) async { + if (shouldUpdateUtxos) { + await updateUTXOs(); + } + + final total = await totalBalance; + final available = await availableBalance; + + final balance = Balance( + total: total, + spendable: available, + blockedTotal: Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ), + pendingSpendable: total - available, + ); + + await info.updateBalance(newBalance: balance, isar: mainDB.isar); + } + + @override + Future refresh() async { + // Awaiting this lock could be dangerous. + // Since refresh is periodic (generally) + if (refreshMutex.isLocked) { + return; + } + + final node = getCurrentNode(); + + if (prefs.useTor) { + if (node.clearnetEnabled && !node.torEnabled) { + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + throw Exception("TOR - clearnet mismatch"); + } + } else { + if (!node.clearnetEnabled && node.torEnabled) { + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + throw Exception("TOR - clearnet mismatch"); + } + } + + // this acquire should be almost instant due to above check. + // Slight possibility of race but should be irrelevant + await refreshMutex.acquire(); + + libSalviumWallet?.startSyncing(); + _setSyncStatus(lib_monero_compat.StartingSyncStatus()); + + await updateTransactions(); + await updateBalance(); + + if (info.otherData[WalletInfoKeys.reuseAddress] != true) { + await checkReceivingAddressForTransactions(); + } + + if (refreshMutex.isLocked) { + refreshMutex.release(); + } + + final synced = await libSalviumWallet?.isSynced(); + + if (synced == true) { + _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); + } + } + + @override + Future generateNewReceivingAddress() async { + try { + final currentReceiving = await getCurrentReceivingAddress(); + + final newReceivingIndex = + currentReceiving == null ? 0 : currentReceiving.derivationIndex + 1; + + final newReceivingAddress = addressFor(index: newReceivingIndex); + + // Add that new receiving address + await mainDB.putAddress(newReceivingAddress); + await info.updateReceivingAddress( + newAddress: newReceivingAddress.value, + isar: mainDB.isar, + ); + } catch (e, s) { + Logging.instance.e( + "Exception in generateNewAddress(): ", + error: e, + stackTrace: s, + ); + } + } + + @override + Future checkReceivingAddressForTransactions() async { + if (info.otherData[WalletInfoKeys.reuseAddress] == true) { + try { + throw Exception(); + } catch (_, s) { + Logging.instance.e( + "checkReceivingAddressForTransactions called but reuse address flag set: $s", + error: e, + stackTrace: s, + ); + } + } + + try { + int highestIndex = -1; + final entries = await libSalviumWallet?.getAllTxs(refresh: true); + if (entries != null) { + for (final element in entries) { + if (!element.isSpend) { + final int curAddressIndex = + element.addressIndexes.isEmpty + ? 0 + : element.addressIndexes.reduce(max); + if (curAddressIndex > highestIndex) { + highestIndex = curAddressIndex; + } + } + } + } + + // Check the new receiving index + final currentReceiving = await getCurrentReceivingAddress(); + final curIndex = currentReceiving?.derivationIndex ?? -1; + + if (highestIndex >= curIndex) { + // First increment the receiving index + final newReceivingIndex = curIndex + 1; + + // Use new index to derive a new receiving address + final newReceivingAddress = addressFor(index: newReceivingIndex); + + final existing = + await mainDB + .getAddresses(walletId) + .filter() + .valueEqualTo(newReceivingAddress.value) + .findFirst(); + if (existing == null) { + // Add that new change address + await mainDB.putAddress(newReceivingAddress); + } else { + // we need to update the address + await mainDB.updateAddress(existing, newReceivingAddress); + } + if (info.otherData[WalletInfoKeys.reuseAddress] != true) { + // keep checking until address with no tx history is set as current + await checkReceivingAddressForTransactions(); + } + } + } on SocketException catch (se, s) { + Logging.instance.e( + "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s", + error: e, + stackTrace: s, + ); + return; + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from _checkReceivingAddressForTransactions(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + } + + // TODO: this needs some work. Prio's may need to be changed as well as estimated blocks + @override + Future get fees async => FeeObject( + numberOfBlocksFast: 10, + numberOfBlocksAverage: 15, + numberOfBlocksSlow: 20, + fast: BigInt.from(lib_salvium.TransactionPriority.high.value), + medium: BigInt.from(lib_salvium.TransactionPriority.medium.value), + slow: BigInt.from(lib_salvium.TransactionPriority.normal.value), + ); + + @override + Future updateChainHeight() async { + await info.updateCachedChainHeight( + newHeight: currentKnownChainHeight, + isar: mainDB.isar, + ); + } + + @override + Future checkChangeAddressForTransactions() async { + // do nothing + } + + @override + Future generateNewChangeAddress() async { + // do nothing + } + + @override + Future prepareSend({required TxData txData}) async { + try { + final feeRate = txData.feeRateType; + if (feeRate is FeeRateType) { + lib_salvium.TransactionPriority feePriority; + switch (feeRate) { + case FeeRateType.fast: + feePriority = lib_salvium.TransactionPriority.high; + break; + case FeeRateType.average: + feePriority = lib_salvium.TransactionPriority.medium; + break; + case FeeRateType.slow: + feePriority = lib_salvium.TransactionPriority.normal; + break; + default: + throw ArgumentError("Invalid use of custom fee"); + } + + try { + final bool sweep; + + if (txData.utxos == null) { + final balance = await availableBalance; + sweep = txData.amount! == balance; + } else { + final totalInputsValue = txData.utxos! + .map((e) => e.value) + .fold(BigInt.zero, (p, e) => p + BigInt.from(e)); + sweep = txData.amount!.raw == totalInputsValue; + } + + // TODO: test this one day + // cs_salvium may not support this yet properly + if (sweep && txData.recipients!.length > 1) { + throw Exception("Send all not supported with multiple recipients"); + } + + final List outputs = []; + for (final recipient in txData.recipients!) { + final output = lib_salvium.Recipient( + address: recipient.address, + amount: recipient.amount.raw, + ); + + outputs.add(output); + } + + if (outputs.isEmpty) { + throw Exception("No recipients provided"); + } + + final height = await chainHeight; + final inputs = + txData.utxos + ?.map( + (e) => lib_salvium.Output( + address: e.address!, + hash: e.txid, + keyImage: e.keyImage!, + value: BigInt.from(e.value), + isFrozen: e.isBlocked, + isUnlocked: + e.blockHeight != null && + (height - (e.blockHeight ?? 0)) >= + cryptoCurrency.minConfirms, + height: e.blockHeight ?? 0, + vout: e.vout, + spent: e.used ?? false, + spentHeight: null, // doesn't matter here + coinbase: e.isCoinbase, + ), + ) + .toList(); + + return await prepareSendMutex.protect(() async { + final lib_salvium.PendingTransaction pendingTransaction; + if (outputs.length == 1) { + pendingTransaction = await libSalviumWallet!.createTx( + output: outputs.first, + paymentId: "", + sweep: sweep, + priority: feePriority, + preferredInputs: inputs, + accountIndex: 0, // sw only uses account 0 at this time + ); + } else { + pendingTransaction = await libSalviumWallet!.createTxMultiDest( + outputs: outputs, + paymentId: "", + priority: feePriority, + preferredInputs: inputs, + sweep: sweep, + accountIndex: 0, // sw only uses account 0 at this time + ); + } + + final realFee = Amount( + rawValue: pendingTransaction.fee, + fractionDigits: cryptoCurrency.fractionDigits, + ); + + return txData.copyWith( + fee: realFee, + pendingTransaction: pendingTransaction, + ); + }); + } catch (e) { + rethrow; + } + } else { + throw ArgumentError("Invalid fee rate argument provided!"); + } + } catch (e, s) { + Logging.instance.i( + "Exception rethrown from prepare send(): ", + error: e, + stackTrace: s, + ); + + if (e.toString().contains("Incorrect unlocked balance")) { + throw Exception("Insufficient balance!"); + } else { + throw Exception("Transaction failed with error: $e"); + } + } + } + + @override + Future confirmSend({required TxData txData}) async { + try { + try { + await libSalviumWallet!.commitTx(txData.pendingTransaction!); + + Logging.instance.d( + "transaction ${txData.pendingTransaction!.txid} has been sent", + ); + return txData.copyWith(txid: txData.pendingTransaction!.txid); + } catch (e, s) { + Logging.instance.e( + "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", + error: e, + stackTrace: s, + ); + rethrow; + } + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from confirmSend(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + } + + // ============== View only ================================================== + + @override + Future recoverViewOnly() async { + await refreshMutex.protect(() async { + final data = + await getViewOnlyWalletData() as CryptonoteViewOnlyWalletData; + + try { + final height = max(info.restoreHeight, 0); + + await info.updateRestoreHeight( + newRestoreHeight: height, + isar: mainDB.isar, + ); + + final String name = walletId; + + final path = await pathForWallet(name: name, type: compatType); + + final password = generatePassword(); + await secureStorageInterface.write( + key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + value: password, + ); + final wallet = await getRestoredFromViewKeyWallet( + path: path, + password: password, + address: data.address, + privateViewKey: data.privateViewKey, + height: height, + ); + + if (libSalviumWallet != null) { + await exit(); + } + + libSalviumWallet = wallet; + + _setListener(); + + final newReceivingAddress = + await getCurrentReceivingAddress() ?? + Address( + walletId: walletId, + derivationIndex: 0, + derivationPath: null, + value: wallet.getAddress().value, + publicKey: [], + type: AddressType.cryptonote, + subType: AddressSubType.receiving, + ); + + await mainDB.updateOrPutAddresses([newReceivingAddress]); + await info.updateReceivingAddress( + newAddress: newReceivingAddress.value, + isar: mainDB.isar, + ); + + await updateNode(); + _setListener(); + + unawaited(libSalviumWallet?.rescanBlockchain()); + libSalviumWallet?.startSyncing(); + + // await save(); + libSalviumWallet?.startListeners(); + libSalviumWallet?.startAutoSaving(); + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from recoverViewOnly(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + }); + } + + // ============== Private ==================================================== + + StreamSubscription? _torStatusListener; + StreamSubscription? _torPreferenceListener; + + final Mutex _torConnectingLock = Mutex(); + bool _requireMutex = false; +} From 8029116a2b85a9f87843275b0329987722ddc446 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 13:45:51 -0500 Subject: [PATCH 073/206] fix: add optional pendingSalviumTransaction to TxData --- lib/wallets/models/tx_data.dart | 23 +++++++++++++++++++ .../intermediate/lib_salvium_wallet.dart | 8 +++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index c95fad163..96882d428 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -1,4 +1,5 @@ import 'package:cs_monero/cs_monero.dart' as lib_monero; +import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; import 'package:tezart/tezart.dart' as tezart; import 'package:web3dart/web3dart.dart' as web3dart; @@ -51,6 +52,7 @@ class TxData { final BigInt? chainId; // wownero and monero specific final lib_monero.PendingTransaction? pendingTransaction; + final lib_salvium.PendingTransaction? pendingSalviumTransaction; // firo lelantus specific final int? jMintValue; @@ -110,6 +112,7 @@ class TxData { this.nonce, this.chainId, this.pendingTransaction, + this.pendingSalviumTransaction, this.jMintValue, this.spendCoinIndexes, this.height, @@ -142,6 +145,14 @@ class TxData { ); } } + if (pendingSalviumTransaction?.amount != null && fee != null) { + if (pendingSalviumTransaction!.amount + fee!.raw == sum.raw) { + return Amount( + rawValue: pendingSalviumTransaction!.amount, + fractionDigits: recipients!.first.amount.fractionDigits, + ); + } + } return sum; } @@ -178,6 +189,14 @@ class TxData { ); } } + if (pendingSalviumTransaction?.amount != null && fee != null) { + if (pendingSalviumTransaction!.amount + fee!.raw == sum.raw) { + return Amount( + rawValue: pendingSalviumTransaction!.amount, + fractionDigits: recipients!.first.amount.fractionDigits, + ); + } + } return sum; } @@ -234,6 +253,7 @@ class TxData { int? nonce, BigInt? chainId, lib_monero.PendingTransaction? pendingTransaction, + lib_salvium.PendingTransaction? pendingSalviumTransaction, int? jMintValue, List? spendCoinIndexes, int? height, @@ -281,6 +301,8 @@ class TxData { nonce: nonce ?? this.nonce, chainId: chainId ?? this.chainId, pendingTransaction: pendingTransaction ?? this.pendingTransaction, + pendingSalviumTransaction: + pendingSalviumTransaction ?? this.pendingSalviumTransaction, jMintValue: jMintValue ?? this.jMintValue, spendCoinIndexes: spendCoinIndexes ?? this.spendCoinIndexes, height: height ?? this.height, @@ -324,6 +346,7 @@ class TxData { 'nonce: $nonce, ' 'chainId: $chainId, ' 'pendingTransaction: $pendingTransaction, ' + 'pendingSalviumTransaction: $pendingSalviumTransaction, ' 'jMintValue: $jMintValue, ' 'spendCoinIndexes: $spendCoinIndexes, ' 'height: $height, ' diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index be26f5b22..4e9c9ac6c 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -1366,7 +1366,7 @@ abstract class LibSalviumWallet return txData.copyWith( fee: realFee, - pendingTransaction: pendingTransaction, + pendingSalviumTransaction: pendingTransaction, ); }); } catch (e) { @@ -1394,12 +1394,12 @@ abstract class LibSalviumWallet Future confirmSend({required TxData txData}) async { try { try { - await libSalviumWallet!.commitTx(txData.pendingTransaction!); + await libSalviumWallet!.commitTx(txData.pendingSalviumTransaction!); Logging.instance.d( - "transaction ${txData.pendingTransaction!.txid} has been sent", + "transaction ${txData.pendingSalviumTransaction!.txid} has been sent", ); - return txData.copyWith(txid: txData.pendingTransaction!.txid); + return txData.copyWith(txid: txData.pendingSalviumTransaction!.txid); } catch (e, s) { Logging.instance.e( "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", From c6cba7eb4b9a7e81620a102d2af1399d1b5c33a1 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 14:06:44 -0500 Subject: [PATCH 074/206] fix: HACK salvium wallets are "just" monero wallets--is probably bad --- lib/wallets/wallet/impl/salvium_wallet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/wallet/impl/salvium_wallet.dart b/lib/wallets/wallet/impl/salvium_wallet.dart index 29555ef62..484526554 100644 --- a/lib/wallets/wallet/impl/salvium_wallet.dart +++ b/lib/wallets/wallet/impl/salvium_wallet.dart @@ -9,7 +9,7 @@ import '../intermediate/lib_salvium_wallet.dart'; class SalviumWallet extends LibSalviumWallet { SalviumWallet(CryptoCurrencyNetwork network) - : super(Salvium(network), lib_monero_compat.WalletType.salvium); + : super(Salvium(network), lib_monero_compat.WalletType.monero); @override Future estimateFeeFor(Amount amount, BigInt feeRate) async { From 078a70981d0e1b35f7984bbdd9a7da1105d9677e Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 14:07:13 -0500 Subject: [PATCH 075/206] fix: add Salvium to SW app config --- scripts/app_config/configure_stack_wallet.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index e46420fa0..a0d83ee97 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -85,6 +85,7 @@ final List _supportedCoins = List.unmodifiable([ Peercoin(CryptoCurrencyNetwork.test), Stellar(CryptoCurrencyNetwork.test), Xelis(CryptoCurrencyNetwork.test), + Salvium(CryptoCurrencyNetwork.main), ]); final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); From 604fd8c06f1e5524f841ee7bff413f650dc074ea Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 14:37:03 -0500 Subject: [PATCH 076/206] fix: use monero wordlist for salvium, too --- .../restore_wallet_view/restore_wallet_view.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 90ef055e2..97e960baf 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -189,7 +189,8 @@ class _RestoreWalletViewState extends ConsumerState { // TODO: check for wownero wordlist? bool _isValidMnemonicWord(String word) { // TODO: get the actual language - if (widget.coin is Monero) { + if (widget.coin is Monero || widget.coin is Salvium) { + // Salvium use's Monero's wordlists. switch (widget.seedWordsLength) { case 25: return lib_monero.getMoneroWordList("English").contains(word); From fa262c1e00e95cad3a7393832b6cf73313020ddb Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 14:39:33 -0500 Subject: [PATCH 077/206] fix: sort Salvium alphabetically in the coins list --- scripts/app_config/configure_stack_wallet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index a0d83ee97..8bec3a2a4 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -69,6 +69,7 @@ final List _supportedCoins = List.unmodifiable([ Namecoin(CryptoCurrencyNetwork.main), Particl(CryptoCurrencyNetwork.main), Peercoin(CryptoCurrencyNetwork.main), + Salvium(CryptoCurrencyNetwork.main), Solana(CryptoCurrencyNetwork.main), Stellar(CryptoCurrencyNetwork.main), Tezos(CryptoCurrencyNetwork.main), @@ -85,7 +86,6 @@ final List _supportedCoins = List.unmodifiable([ Peercoin(CryptoCurrencyNetwork.test), Stellar(CryptoCurrencyNetwork.test), Xelis(CryptoCurrencyNetwork.test), - Salvium(CryptoCurrencyNetwork.main), ]); final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); From 5c418647eaa0d39c3de6cfa0bf5bde31566a0301 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 15:06:45 -0500 Subject: [PATCH 078/206] fix: add Salvium wallet handling --- .../restore_wallet_view/restore_wallet_view.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 97e960baf..b70d9a0ef 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -45,6 +45,7 @@ import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/models/wallet_info.dart'; import '../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../wallets/wallet/impl/monero_wallet.dart'; +import '../../../wallets/wallet/impl/salvium_wallet.dart'; import '../../../wallets/wallet/impl/wownero_wallet.dart'; import '../../../wallets/wallet/impl/xelis_wallet.dart'; import '../../../wallets/wallet/intermediate/external_wallet.dart'; @@ -259,6 +260,7 @@ class _RestoreWalletViewState extends ConsumerState { if (bip39.validateMnemonic(mnemonic) == false && !(widget.coin is Monero || widget.coin is Wownero || + widget.coin is Salvium || widget.coin is Xelis)) { unawaited( showFloatingFlushBar( @@ -343,6 +345,10 @@ class _RestoreWalletViewState extends ConsumerState { await (wallet as WowneroWallet).init(isRestore: true); break; + case const (Salvium): + await (wallet as SalviumWallet).init(isRestore: true); + break; + case const (XelisWallet): await (wallet as XelisWallet).init(isRestore: true); break; From 27b6193a9d73ec32bf3f08daa2ab03414a254723 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 15:09:10 -0500 Subject: [PATCH 079/206] fix: add Salvium wallet handling --- .../new_wallet_recovery_phrase_warning_view.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index 2ad110fbd..e16ab5b0c 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -31,6 +31,7 @@ import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/models/wallet_info.dart'; import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../wallets/wallet/wallet.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -183,7 +184,7 @@ class _NewWalletRecoveryPhraseWarningViewState // TODO: Refactor these to generate each coin in their respective classes // This code should not be in a random view page file - if (coin is Monero || coin is Wownero || coin is Xelis) { + if (coin is Monero || coin is Wownero || coin is Xelis || coin is Salvium) { // currently a special case due to the // xmr/wow libraries handling their // own mnemonic generation @@ -230,6 +231,8 @@ class _NewWalletRecoveryPhraseWarningViewState if (wallet is LibMoneroWallet) { await wallet.init(wordCount: wordCount); + } else if (wallet is LibSalviumWallet) { + await wallet.init(wordCount: wordCount); } else { await wallet.init(); } From dfbbc33c77ccbea51fc70d6e1a79d0b41888014b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 15:11:18 -0500 Subject: [PATCH 080/206] fix: handle Salvium wallets --- lib/wallets/wallet/wallet.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index 9ed0c9c6e..595c1088e 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -42,6 +42,7 @@ import 'impl/namecoin_wallet.dart'; import 'impl/nano_wallet.dart'; import 'impl/particl_wallet.dart'; import 'impl/peercoin_wallet.dart'; +import 'impl/salvium_wallet.dart'; import 'impl/solana_wallet.dart'; import 'impl/stellar_wallet.dart'; import 'impl/sub_wallets/eth_token_wallet.dart'; @@ -378,6 +379,9 @@ abstract class Wallet { case const (Peercoin): return PeercoinWallet(net); + case const (Salvium): + return SalviumWallet(net); + case const (Solana): return SolanaWallet(net); From 7749c0f8819e783d306441ebc7aa695434f23fe8 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 15:17:47 -0500 Subject: [PATCH 081/206] fix: only use 25 word salvium mnemonics --- lib/wallets/wallet/intermediate/lib_salvium_wallet.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index 4e9c9ac6c..dc5373d3d 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -332,9 +332,7 @@ abstract class LibSalviumWallet Future init({bool? isRestore, int? wordCount}) async { final path = await pathForWallet(name: walletId, type: compatType); if (!(walletExists(path)) && isRestore != true) { - if (wordCount == null) { - throw Exception("Missing word count for new xmr/wow wallet!"); - } + wordCount ??= 25; try { final password = generatePassword(); await secureStorageInterface.write( From bb0401cca32d89c36a9c5a5b1ec7062dbba59492 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 17:09:06 -0500 Subject: [PATCH 082/206] fix: rip compat out --- lib/wallets/wallet/impl/salvium_wallet.dart | 6 +- .../intermediate/lib_salvium_wallet.dart | 372 ++++++++++-------- 2 files changed, 216 insertions(+), 162 deletions(-) diff --git a/lib/wallets/wallet/impl/salvium_wallet.dart b/lib/wallets/wallet/impl/salvium_wallet.dart index 484526554..f340776be 100644 --- a/lib/wallets/wallet/impl/salvium_wallet.dart +++ b/lib/wallets/wallet/impl/salvium_wallet.dart @@ -9,12 +9,12 @@ import '../intermediate/lib_salvium_wallet.dart'; class SalviumWallet extends LibSalviumWallet { SalviumWallet(CryptoCurrencyNetwork network) - : super(Salvium(network), lib_monero_compat.WalletType.monero); + : super(Salvium(network)); @override Future estimateFeeFor(Amount amount, BigInt feeRate) async { - if (libSalviumWallet == null || - syncStatus is! lib_monero_compat.SyncedSyncStatus) { + if (libSalviumWallet == null /*|| + syncStatus is! lib_monero_compat.SyncedSyncStatus*/) { return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits); } diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index dc5373d3d..bd402efe0 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:math'; -import 'package:compat/compat.dart' as lib_monero_compat; import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; import 'package:isar/isar.dart'; import 'package:mutex/mutex.dart'; @@ -47,7 +46,7 @@ abstract class LibSalviumWallet @override int get isarTransactionVersion => 2; - LibSalviumWallet(super.currency, this.compatType) { + LibSalviumWallet(super.currency) { final bus = GlobalEventBus.instance; // Listen for tor status changes. @@ -103,26 +102,25 @@ abstract class LibSalviumWallet }); } - final lib_monero_compat.WalletType compatType; lib_salvium.Wallet? libSalviumWallet; - lib_monero_compat.SyncStatus? get syncStatus => _syncStatus; - lib_monero_compat.SyncStatus? _syncStatus; - int _syncedCount = 0; - void _setSyncStatus(lib_monero_compat.SyncStatus status) { - if (status is lib_monero_compat.SyncedSyncStatus) { - if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { - _syncedCount++; - } - } else { - _syncedCount = 0; - } - - if (_syncedCount < 3) { - _syncStatus = status; - syncStatusChanged(); - } - } + // lib_monero_compat.SyncStatus? get syncStatus => _syncStatus; + // lib_monero_compat.SyncStatus? _syncStatus; + // int _syncedCount = 0; + // void _setSyncStatus(lib_monero_compat.SyncStatus status) { + // if (status is lib_monero_compat.SyncedSyncStatus) { + // if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { + // _syncedCount++; + // } + // } else { + // _syncedCount = 0; + // } + // + // if (_syncedCount < 3) { + // _syncStatus = status; + // syncStatusChanged(); + // } + // } final prepareSendMutex = Mutex(); final estimateFeeMutex = Mutex(); @@ -191,13 +189,13 @@ abstract class LibSalviumWallet if (libSalviumWallet == null) { wasNull = true; // libSalviumWalletT?.close(); - final path = await pathForWallet(name: walletId, type: compatType); + final path = await pathForWallet(name: walletId); final String password; try { password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + key: _libSalviumWalletPasswordKey(walletId.toUpperCase()), ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); @@ -224,10 +222,10 @@ abstract class LibSalviumWallet if (wasNull) { try { - _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + // _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); libSalviumWallet?.startSyncing(); } catch (_) { - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); // TODO log } } @@ -238,23 +236,22 @@ abstract class LibSalviumWallet unawaited(refresh()); } - @Deprecated("Only used in the case of older wallets") - lib_monero_compat.WalletInfo? getLibSalviumWalletInfo(String walletId) { - try { - return DB.instance.moneroWalletInfoBox.values.firstWhere( - (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), - ); - } catch (_) { - return null; - } - } + // @Deprecated("Only used in the case of older wallets") + // lib_monero_compat.WalletInfo? getLibSalviumWalletInfo(String walletId) { + // try { + // return DB.instance.moneroWalletInfoBox.values.firstWhere( + // (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), + // ); + // } catch (_) { + // return null; + // } + // } Future save() async { if (!Platform.isWindows) { final appRoot = await StackFileSystem.applicationRootDirectory(); - await lib_monero_compat.backupWalletFiles( + await _backupWalletFiles( name: walletId, - type: compatType, appRoot: appRoot, ); } @@ -287,8 +284,8 @@ abstract class LibSalviumWallet Future getKeys() async { final base = libSalviumWallet; - final oldInfo = getLibSalviumWalletInfo(walletId); - if (base == null || (oldInfo != null && oldInfo.name != walletId)) { + // final oldInfo = getLibSalviumWalletInfo(walletId); + if (base == null /*|| (oldInfo != null && oldInfo.name != walletId)*/) { return null; } try { @@ -313,12 +310,12 @@ abstract class LibSalviumWallet Future<(String, String)> hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing() async { - final path = await pathForWallet(name: walletId, type: compatType); + final path = await pathForWallet(name: walletId); final String password; try { password = (await secureStorageInterface.read( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + key: _libSalviumWalletPasswordKey(walletId), ))!; } catch (e, s) { throw Exception("Password not found $e, $s"); @@ -330,13 +327,13 @@ abstract class LibSalviumWallet @override Future init({bool? isRestore, int? wordCount}) async { - final path = await pathForWallet(name: walletId, type: compatType); + final path = await pathForWallet(name: walletId); if (!(walletExists(path)) && isRestore != true) { wordCount ??= 25; try { final password = generatePassword(); await secureStorageInterface.write( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + key: _libSalviumWalletPasswordKey(walletId), value: password, ); final wallet = await getCreatedWallet( @@ -410,12 +407,12 @@ abstract class LibSalviumWallet final String name = walletId; - final path = await pathForWallet(name: name, type: compatType); + final path = await pathForWallet(name: name); try { final password = generatePassword(); await secureStorageInterface.write( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + key: _libSalviumWalletPasswordKey(walletId), value: password, ); final wallet = await getRestoredWallet( @@ -493,7 +490,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } proxy = TorService.sharedInstance.getProxyInfo(); @@ -502,12 +499,12 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } - _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + // _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); try { if (_requireMutex) { await _torConnectingLock.protect(() async { @@ -544,9 +541,9 @@ abstract class LibSalviumWallet libSalviumWallet?.startListeners(); libSalviumWallet?.startAutoSaving(); - _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); + // _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); } catch (e, s) { - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); Logging.instance.e( "Exception caught in $runtimeType.updateNode(): ", error: e, @@ -742,22 +739,18 @@ abstract class LibSalviumWallet Future pathForWalletDir({ required String name, - required lib_monero_compat.WalletType type, }) async { final Directory root = await StackFileSystem.applicationRootDirectory(); - return lib_monero_compat.pathForWalletDir( + return _pathForWalletDir( name: name, - type: type.name.toLowerCase(), appRoot: root, ); } Future pathForWallet({ required String name, - required lib_monero_compat.WalletType type, }) async => await pathForWalletDir( name: name, - type: type, ).then((path) => '$path/$name'); void onSyncingUpdate({ @@ -769,9 +762,8 @@ abstract class LibSalviumWallet currentKnownChainHeight = nodeHeight; updateChainHeight(); final blocksLeft = nodeHeight - syncHeight; - final lib_monero_compat.SyncStatus status; if (blocksLeft < 100) { - status = lib_monero_compat.SyncedSyncStatus(); + // status = lib_monero_compat.SyncedSyncStatus(); // if (!_hasSyncAfterStartup) { // _hasSyncAfterStartup = true; @@ -784,14 +776,14 @@ abstract class LibSalviumWallet } else { final percent = syncHeight / currentKnownChainHeight; - status = lib_monero_compat.SyncingSyncStatus( - blocksLeft, - percent, - currentKnownChainHeight, - ); + // status = lib_monero_compat.SyncingSyncStatus( + // blocksLeft, + // percent, + // currentKnownChainHeight, + // ); } - _setSyncStatus(status); + // _setSyncStatus(status); _refreshTxDataHelper(); } } @@ -867,82 +859,82 @@ abstract class LibSalviumWallet ); } - void syncStatusChanged() async { - final _syncStatus = syncStatus; - - if (_syncStatus != null) { - if (_syncStatus.progress() == 1 && refreshMutex.isLocked) { - refreshMutex.release(); - } - - WalletSyncStatus? status; - xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true); - - if (_syncStatus is lib_monero_compat.SyncingSyncStatus) { - final int blocksLeft = _syncStatus.blocksLeft; - - // ensure at least 1 to prevent math errors - final int height = max(1, _syncStatus.height); - - final nodeHeight = height + blocksLeft; - currentKnownChainHeight = nodeHeight; - - // final percent = height / nodeHeight; - final percent = _syncStatus.ptc; - - final highest = max(highestPercentCached, percent); - - final unchanged = highest == highestPercentCached; - if (unchanged) { - return; - } - - // update cached - if (highestPercentCached < percent) { - highestPercentCached = percent; - } - - GlobalEventBus.instance.fire( - RefreshPercentChangedEvent(highest, walletId), - ); - GlobalEventBus.instance.fire( - BlocksRemainingEvent(blocksLeft, walletId), - ); - } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { - status = WalletSyncStatus.synced; - } else if (_syncStatus is lib_monero_compat.NotConnectedSyncStatus) { - status = WalletSyncStatus.unableToSync; - xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { - status = WalletSyncStatus.syncing; - GlobalEventBus.instance.fire( - RefreshPercentChangedEvent(highestPercentCached, walletId), - ); - } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { - status = WalletSyncStatus.unableToSync; - xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { - status = WalletSyncStatus.syncing; - GlobalEventBus.instance.fire( - RefreshPercentChangedEvent(highestPercentCached, walletId), - ); - } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { - status = WalletSyncStatus.syncing; - GlobalEventBus.instance.fire( - RefreshPercentChangedEvent(highestPercentCached, walletId), - ); - } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { - status = WalletSyncStatus.unableToSync; - xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - } - - if (status != null) { - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent(status, walletId, info.coin), - ); - } - } - } + // void syncStatusChanged() async { + // final _syncStatus = syncStatus; + // + // if (_syncStatus != null) { + // if (_syncStatus.progress() == 1 && refreshMutex.isLocked) { + // refreshMutex.release(); + // } + // + // WalletSyncStatus? status; + // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true); + // + // if (_syncStatus is lib_monero_compat.SyncingSyncStatus) { + // final int blocksLeft = _syncStatus.blocksLeft; + // + // // ensure at least 1 to prevent math errors + // final int height = max(1, _syncStatus.height); + // + // final nodeHeight = height + blocksLeft; + // currentKnownChainHeight = nodeHeight; + // + // // final percent = height / nodeHeight; + // final percent = _syncStatus.ptc; + // + // final highest = max(highestPercentCached, percent); + // + // final unchanged = highest == highestPercentCached; + // if (unchanged) { + // return; + // } + // + // // update cached + // if (highestPercentCached < percent) { + // highestPercentCached = percent; + // } + // + // GlobalEventBus.instance.fire( + // RefreshPercentChangedEvent(highest, walletId), + // ); + // GlobalEventBus.instance.fire( + // BlocksRemainingEvent(blocksLeft, walletId), + // ); + // } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { + // status = WalletSyncStatus.synced; + // } else if (_syncStatus is lib_monero_compat.NotConnectedSyncStatus) { + // status = WalletSyncStatus.unableToSync; + // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + // } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { + // status = WalletSyncStatus.syncing; + // GlobalEventBus.instance.fire( + // RefreshPercentChangedEvent(highestPercentCached, walletId), + // ); + // } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { + // status = WalletSyncStatus.unableToSync; + // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + // } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { + // status = WalletSyncStatus.syncing; + // GlobalEventBus.instance.fire( + // RefreshPercentChangedEvent(highestPercentCached, walletId), + // ); + // } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { + // status = WalletSyncStatus.syncing; + // GlobalEventBus.instance.fire( + // RefreshPercentChangedEvent(highestPercentCached, walletId), + // ); + // } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { + // status = WalletSyncStatus.unableToSync; + // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + // } + // + // if (status != null) { + // GlobalEventBus.instance.fire( + // WalletSyncStatusChangedEvent(status, walletId, info.coin), + // ); + // } + // } + // } @override Future checkSaveInitialReceivingAddress() async { @@ -954,21 +946,21 @@ abstract class LibSalviumWallet if (_txRefreshLock) return; _txRefreshLock = true; - final _syncStatus = syncStatus; - - if (_syncStatus != null && - _syncStatus is lib_monero_compat.SyncingSyncStatus) { - final int blocksLeft = _syncStatus.blocksLeft; - final tenKChange = blocksLeft ~/ 10000; + // final _syncStatus = syncStatus; - // only refresh transactions periodically during a sync - if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) { - _lastCheckedHeight = tenKChange; - await _refreshTxData(); - } - } else { - await _refreshTxData(); - } + // if (_syncStatus != null && + // _syncStatus is lib_monero_compat.SyncingSyncStatus) { + // final int blocksLeft = _syncStatus.blocksLeft; + // final tenKChange = blocksLeft ~/ 10000; + // + // // only refresh transactions periodically during a sync + // if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) { + // _lastCheckedHeight = tenKChange; + // await _refreshTxData(); + // } + // } else { + // await _refreshTxData(); + // } _txRefreshLock = false; } @@ -1090,7 +1082,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } else { @@ -1098,7 +1090,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } @@ -1108,7 +1100,7 @@ abstract class LibSalviumWallet await refreshMutex.acquire(); libSalviumWallet?.startSyncing(); - _setSyncStatus(lib_monero_compat.StartingSyncStatus()); + // _setSyncStatus(lib_monero_compat.StartingSyncStatus()); await updateTransactions(); await updateBalance(); @@ -1124,7 +1116,7 @@ abstract class LibSalviumWallet final synced = await libSalviumWallet?.isSynced(); if (synced == true) { - _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); + // _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); } } @@ -1400,7 +1392,7 @@ abstract class LibSalviumWallet return txData.copyWith(txid: txData.pendingSalviumTransaction!.txid); } catch (e, s) { Logging.instance.e( - "${info.name} ${compatType.name.toLowerCase()} confirmSend: ", + "${info.name} confirmSend: ", error: e, stackTrace: s, ); @@ -1434,11 +1426,11 @@ abstract class LibSalviumWallet final String name = walletId; - final path = await pathForWallet(name: name, type: compatType); + final path = await pathForWallet(name: name); final password = generatePassword(); await secureStorageInterface.write( - key: lib_monero_compat.libMoneroWalletPasswordKey(walletId), + key: _libSalviumWalletPasswordKey(walletId.toUpperCase()), value: password, ); final wallet = await getRestoredFromViewKeyWallet( @@ -1503,3 +1495,65 @@ abstract class LibSalviumWallet final Mutex _torConnectingLock = Mutex(); bool _requireMutex = false; } + +String _libSalviumWalletPasswordKey(String walletName) => + "SALVIUM_WALLET_PASSWORD_${walletName.toUpperCase()}"; + +String _backupFileName(String originalPath) { + final pathParts = originalPath.split('/'); + final newName = '#_${pathParts.last}'; + pathParts.removeLast(); + pathParts.add(newName); + return pathParts.join('/'); +} + +Future _backupWalletFiles({ + required String name, + required Directory appRoot, +}) async { + final path = await _pathForWallet( + name: name, + appRoot: appRoot, + ); + final cacheFile = File(path); + final keysFile = File('$path.keys'); + final addressListFile = File('$path.address.txt'); + final newCacheFilePath = _backupFileName(cacheFile.path); + final newKeysFilePath = _backupFileName(keysFile.path); + final newAddressListFilePath = _backupFileName(addressListFile.path); + + if (cacheFile.existsSync()) { + await cacheFile.copy(newCacheFilePath); + } + + if (keysFile.existsSync()) { + await keysFile.copy(newKeysFilePath); + } + + if (addressListFile.existsSync()) { + await addressListFile.copy(newAddressListFilePath); + } +} + +Future _pathForWalletDir({ + required String name, + required Directory appRoot, +}) async { + final walletsDir = Directory('${appRoot.path}/wallets'); + final walletDire = Directory('${walletsDir.path}/salvium/$name'); + + if (!walletDire.existsSync()) { + walletDire.createSync(recursive: true); + } + + return walletDire.path; +} + +Future _pathForWallet({ + required String name, + required Directory appRoot, +}) async => + await _pathForWalletDir( + name: name, + appRoot: appRoot, + ).then((path) => '$path/$name'); From 3703127722ce2cd407dbe6f19909052bf1f6a62a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 17:21:21 -0500 Subject: [PATCH 083/206] fix: handle salvium wallets in more places and comment improvement --- .../verify_recovery_phrase_view.dart | 24 +++++++++++++++++++ .../helpers/restore_create_backup.dart | 3 ++- .../wallet_settings_wallet_settings_view.dart | 5 ++-- .../firo_rescan_recovery_error_dialog.dart | 3 +++ .../tx_v2/transaction_v2_details_view.dart | 3 ++- lib/pages/wallet_view/wallet_view.dart | 3 ++- .../sub_widgets/desktop_wallet_features.dart | 2 +- .../unlock_wallet_keys_desktop.dart | 3 +++ .../sub_widgets/wallet_options_button.dart | 3 ++- lib/services/wallets.dart | 9 +++---- .../intermediate/lib_salvium_wallet.dart | 2 +- 11 files changed, 48 insertions(+), 12 deletions(-) diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart index 97c467b34..06beb584a 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart @@ -14,6 +14,8 @@ import 'dart:math'; import 'package:cs_monero/src/deprecated/get_height_by_date.dart' as cs_monero_deprecated; +import 'package:cs_salvium/src/deprecated/get_height_by_date.dart' +as cs_salvium_deprecated; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -40,6 +42,7 @@ import '../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../wallets/wallet/impl/wownero_wallet.dart'; import '../../../wallets/wallet/impl/xelis_wallet.dart'; import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../wallets/wallet/wallet.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -132,6 +135,11 @@ class _VerifyRecoveryPhraseViewState date: DateTime.now().subtract(const Duration(days: 7)), ); } + if (widget.wallet.cryptoCurrency is Salvium) { + height = cs_salvium_deprecated.getSalviumHeightByDate( + date: DateTime.now().subtract(const Duration(days: 7)), + ); + } if (height < 0) height = 0; viewOnlyWalletType = ViewOnlyWalletType.cryptonote; @@ -188,6 +196,22 @@ class _VerifyRecoveryPhraseViewState await w.exit(); + viewOnlyData = CryptonoteViewOnlyWalletData( + walletId: voInfo.walletId, + address: address, + privateViewKey: privateViewKey, + ); + } else if (widget.wallet is LibSalviumWallet) { + final w = widget.wallet as LibSalviumWallet; + + final info = + await w + .hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing(); + final address = info.$1; + final privateViewKey = info.$2; + + await w.exit(); + viewOnlyData = CryptonoteViewOnlyWalletData( walletId: voInfo.walletId, address: address, diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index 679ccc84c..57643c43b 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -57,6 +57,7 @@ import '../../../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../../../wallets/wallet/impl/wownero_wallet.dart'; import '../../../../../wallets/wallet/impl/xelis_wallet.dart'; import '../../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../../wallets/wallet/wallet.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart'; @@ -505,7 +506,7 @@ abstract class SWB { int restoreHeight = walletbackup['restoreHeight'] as int? ?? 0; if (restoreHeight <= 0) { - if (wallet is EpiccashWallet || wallet is LibMoneroWallet) { + if (wallet is EpiccashWallet || wallet is LibMoneroWallet || wallet is LibSalviumWallet) { restoreHeight = 0; } else { restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0; diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index 3917f743e..c2eca9000 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -21,6 +21,7 @@ import '../../../../utilities/text_styles.dart'; import '../../../../wallets/isar/models/wallet_info.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; @@ -416,8 +417,8 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is LibMoneroWallet) const SizedBox(height: 8), - if (wallet is LibMoneroWallet) + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) const SizedBox(height: 8), + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( diff --git a/lib/pages/special/firo_rescan_recovery_error_dialog.dart b/lib/pages/special/firo_rescan_recovery_error_dialog.dart index fa59d841a..2653db128 100644 --- a/lib/pages/special/firo_rescan_recovery_error_dialog.dart +++ b/lib/pages/special/firo_rescan_recovery_error_dialog.dart @@ -13,6 +13,7 @@ import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../widgets/background.dart'; @@ -272,6 +273,8 @@ class _FiroRescanRecoveryErrorViewState keyData = await wallet.getXPrivs(); } else if (wallet is LibMoneroWallet) { keyData = await wallet.getKeys(); + } else if (wallet is LibSalviumWallet) { + keyData = await wallet.getKeys(); } if (context.mounted) { diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index 06469c92b..a2d4e8df1 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -44,6 +44,7 @@ import '../../../../wallets/isar/models/spark_coin.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../widgets/background.dart'; @@ -187,7 +188,7 @@ class _TransactionV2DetailsViewState final wallet = ref.read(pWallets).getWallet(walletId); hasTxKeyProbably = - wallet is LibMoneroWallet && + (wallet is LibMoneroWallet || wallet is LibSalviumWallet) && (_transaction.type == TransactionType.outgoing || _transaction.type == TransactionType.sentToSelf); diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 7356e07e6..61bf31037 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -54,6 +54,7 @@ import '../../wallets/wallet/impl/bitcoin_frost_wallet.dart'; import '../../wallets/wallet/impl/firo_wallet.dart'; import '../../wallets/wallet/impl/namecoin_wallet.dart'; import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; @@ -1295,7 +1296,7 @@ class _WalletViewState extends ConsumerState { ); }, ), - if (wallet is LibMoneroWallet && !viewOnly) + if ((wallet is LibMoneroWallet || wallet is LibSalviumWallet) && !viewOnly) WalletNavigationBarItemData( label: "Churn", icon: const ChurnNavIcon(), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 814af0cd2..1f36c55b4 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -442,7 +442,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (!isViewOnly && wallet is CashFusionInterface) (WalletFeature.fusion, Assets.svg.cashFusion, _onFusionPressed), - if (!isViewOnly && wallet is LibMoneroWallet) + if (!isViewOnly && (wallet is LibMoneroWallet || wallet is LibSalviumWallet)) (WalletFeature.churn, Assets.svg.churn, _onChurnPressed), if (wallet is NamecoinWallet) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart index 938e9568a..3faf4ec80 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart @@ -24,6 +24,7 @@ import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/wallet/impl/bitcoin_frost_wallet.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -118,6 +119,8 @@ class _UnlockWalletKeysDesktopState keyData = await wallet.getXPrivs(); } else if (wallet is LibMoneroWallet) { keyData = await wallet.getKeys(); + } else if (wallet is LibSalviumWallet) { + keyData = await wallet.getKeys(); } if (mounted) { diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_options_button.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_options_button.dart index 47b590a61..8136133ca 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_options_button.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_options_button.dart @@ -30,6 +30,7 @@ import '../../../../wallets/crypto_currency/intermediate/frost_currency.dart'; import '../../../../wallets/crypto_currency/intermediate/nano_currency.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../addresses/desktop_wallet_addresses_view.dart'; @@ -296,7 +297,7 @@ class WalletOptionsPopupMenu extends ConsumerWidget { final bool canChangeRep = coin is NanoCurrency; final bool isFrost = coin is FrostCurrency; - final bool isMoneroWow = wallet is LibMoneroWallet; + final bool isMoneroWow = wallet is LibMoneroWallet || wallet is LibSalviumWallet; return Stack( children: [ diff --git a/lib/services/wallets.dart b/lib/services/wallets.dart index d47c7b66b..ce10f548b 100644 --- a/lib/services/wallets.dart +++ b/lib/services/wallets.dart @@ -25,6 +25,7 @@ import '../wallets/crypto_currency/crypto_currency.dart'; import '../wallets/isar/models/wallet_info.dart'; import '../wallets/wallet/impl/epiccash_wallet.dart'; import '../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../wallets/wallet/wallet.dart'; import 'event_bus/events/wallet_added_event.dart'; import 'event_bus/global_event_bus.dart'; @@ -230,7 +231,7 @@ class Wallets { shouldAutoSyncAll || walletIdsToEnableAutoSync.contains(walletInfo.walletId); - if (wallet is LibMoneroWallet) { + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) { // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync)); } else { walletInitFutures.add( @@ -339,7 +340,7 @@ class Wallets { nodeService: nodeService, prefs: prefs, ).then((wallet) { - if (wallet is LibMoneroWallet) { + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) { // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync)); walletIdCompleter.complete("dummy_ignore"); @@ -477,7 +478,7 @@ class Wallets { nodeService: nodeService, prefs: prefs, ).then((wallet) { - if (wallet is LibMoneroWallet) { + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) { // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync)); walletIdCompleter.complete("dummy_ignore"); @@ -588,7 +589,7 @@ class Wallets { walletIdsToEnableAutoSync.contains(wallet.walletId); if (isDesktop) { - if (wallet is LibMoneroWallet) { + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) { // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync)); } else { walletInitFutures.add( diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index bd402efe0..aeff86381 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -188,7 +188,7 @@ abstract class LibSalviumWallet if (libSalviumWallet == null) { wasNull = true; - // libSalviumWalletT?.close(); + // await libSalviumWallet?.close(); final path = await pathForWallet(name: walletId); final String password; From 554e8984577a090a4dded32a0740eb07409d827e Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 17:26:33 -0500 Subject: [PATCH 084/206] fix: add missing import --- .../wallet_view/sub_widgets/desktop_wallet_features.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 1f36c55b4..c5e40a234 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -40,6 +40,7 @@ import '../../../../wallets/crypto_currency/coins/firo.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../../wallets/wallet/impl/namecoin_wallet.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet.dart' show Wallet; import '../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; From 1cf6989e728229be06c7a4f416cf118f476c13b0 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 23 May 2025 17:48:28 -0500 Subject: [PATCH 085/206] fix: more salvium stuff --- .../manage_nodes_views/add_edit_node_view.dart | 7 ++++--- .../wallet_settings_view/wallet_settings_view.dart | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 5703db754..f22070c5f 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -36,6 +36,7 @@ import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../wallets/crypto_currency/intermediate/cryptonote_currency.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -228,7 +229,7 @@ class _AddEditNodeViewState extends ConsumerState { // strip unused path String address = formData.host!; - if (coin is LibMoneroWallet) { + if (coin is LibMoneroWallet || coin is LibSalviumWallet) { if (address.startsWith("http")) { final uri = Uri.parse(address); address = "${uri.scheme}://${uri.host}"; @@ -1067,7 +1068,7 @@ class _NodeFormState extends ConsumerState { } else { enableSSLCheckbox = true; } - } else if (widget.coin is LibMoneroWallet) { + } else if (widget.coin is LibMoneroWallet || widget.coin is LibSalviumWallet) { if (newValue.startsWith("https://")) { _useSSL = true; } else if (newValue.startsWith("http://")) { @@ -1274,7 +1275,7 @@ class _NodeFormState extends ConsumerState { ), ], ), - if (widget.coin is LibMoneroWallet) + if (widget.coin is LibMoneroWallet || widget.coin is LibSalviumWallet) Row( children: [ GestureDetector( diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index 68436c634..2c41c1c7b 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -38,6 +38,7 @@ import '../../../wallets/crypto_currency/intermediate/nano_currency.dart'; import '../../../wallets/wallet/impl/bitcoin_frost_wallet.dart'; import '../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -325,6 +326,9 @@ class _WalletSettingsViewState extends ConsumerState { } else if (wallet is LibMoneroWallet) { keyData = await wallet.getKeys(); + } else if (wallet + is LibSalviumWallet) { + keyData = await wallet.getKeys(); } if (context.mounted) { From f2460c39d4767b328701087d2b3e64c02d82b659 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 10:10:28 -0600 Subject: [PATCH 086/206] liberal use of `SafeArea` --- .../add_token_view/add_custom_token_view.dart | 140 +- .../edit_wallet_tokens_view.dart | 525 ++-- .../add_wallet_view/add_wallet_view.dart | 310 +- .../select_new_frost_import_type_view.dart | 161 +- .../name_your_wallet_view.dart | 518 ++-- .../address_book_views/address_book_view.dart | 276 +- .../subviews/add_address_book_entry_view.dart | 664 ++--- .../add_new_contact_address_view.dart | 150 +- .../subviews/address_book_filter_view.dart | 96 +- .../subviews/contact_details_view.dart | 680 +++-- .../subviews/edit_contact_address_view.dart | 175 +- .../edit_contact_name_emoji_view.dart | 281 +- lib/pages/buy_view/buy_order_details.dart | 133 +- lib/pages/buy_view/buy_quote_preview.dart | 107 +- .../sub_widgets/crypto_selection_view.dart | 94 +- .../sub_widgets/fiat_selection_view.dart | 225 +- lib/pages/cashfusion/cashfusion_view.dart | 501 ++-- .../cashfusion/fusion_progress_view.dart | 151 +- .../churning/churning_progress_view.dart | 175 +- lib/pages/churning/churning_view.dart | 199 +- .../exchange_view/choose_from_stack_view.dart | 159 +- .../confirm_change_now_send.dart | 38 +- .../exchange_view/edit_trade_note_view.dart | 155 +- .../exchange_currency_selection_view.dart | 343 +-- .../exchange_step_views/step_1_view.dart | 274 +- .../exchange_step_views/step_2_view.dart | 917 +++--- .../exchange_step_views/step_3_view.dart | 478 ++-- .../exchange_step_views/step_4_view.dart | 817 +++--- lib/pages/exchange_view/send_from_view.dart | 4 +- .../exchange_view/trade_details_view.dart | 14 +- .../wallet_initiated_exchange_view.dart | 103 +- lib/pages/generic/single_field_edit_view.dart | 220 +- lib/pages/home_view/home_view.dart | 310 +- lib/pages/intro_view.dart | 320 +-- lib/pages/loading_view.dart | 66 +- lib/pages/monkey/monkey_view.dart | 2 +- .../confirm_name_transaction_view.dart | 43 +- .../notifications_view.dart | 120 +- lib/pages/ordinals/ordinal_details_view.dart | 21 +- lib/pages/ordinals/ordinals_filter_view.dart | 383 ++- lib/pages/ordinals/ordinals_view.dart | 135 +- .../addresses/edit_address_label_view.dart | 316 +-- .../addresses/wallet_addresses_view.dart | 296 +- .../generate_receiving_uri_qr_code_view.dart | 427 +-- lib/pages/receive_view/receive_view.dart | 508 ++-- .../send_view/confirm_transaction_view.dart | 42 +- .../send_view/frost_ms/frost_send_view.dart | 295 +- lib/pages/send_view/send_view.dart | 2016 ++++++------- lib/pages/send_view/token_send_view.dart | 1114 ++++---- .../global_settings_view/about_view.dart | 633 ++--- .../advanced_settings_view.dart | 495 ++-- .../edit_coin_units_view.dart | 8 +- .../manage_coin_units_view.dart | 2 +- .../advanced_views/manage_explorer_view.dart | 121 +- .../appearance_settings_view.dart | 217 +- .../appearance_settings/manage_themes.dart | 310 +- ...ystem_brightness_theme_selection_view.dart | 161 +- .../global_settings_view/currency_view.dart | 281 +- .../global_settings_view.dart | 469 ++- .../global_settings_view/hidden_settings.dart | 596 ++-- .../global_settings_view/language_view.dart | 246 +- .../add_edit_node_view.dart | 42 +- .../manage_nodes_views/manage_nodes_view.dart | 70 +- .../manage_nodes_views/node_details_view.dart | 336 ++- .../security_views/security_view.dart | 436 +-- .../stack_backup_views/auto_backup_view.dart | 435 ++- .../create_auto_backup_view.dart | 1062 +++---- .../create_backup_information_view.dart | 101 +- .../create_backup_view.dart | 401 ++- .../edit_auto_backup_view.dart | 377 ++- .../restore_from_encrypted_string_view.dart | 345 +-- .../restore_from_file_view.dart | 326 ++- .../stack_backup_views/stack_backup_view.dart | 231 +- .../sub_views/recovery_phrase_view.dart | 83 +- .../stack_restore_progress_view.dart | 684 ++--- .../startup_preferences_view.dart | 511 ++-- .../startup_wallet_selection_view.dart | 302 +- .../global_settings_view/support_view.dart | 96 +- .../syncing_options_view.dart | 182 +- .../syncing_preferences_view.dart | 219 +- .../wallet_syncing_options_view.dart | 66 +- .../tor_settings/tor_settings_view.dart | 262 +- .../frost_ms/frost_ms_options_view.dart | 107 +- .../wallet_backup_view.dart | 250 +- .../wallet_network_settings_view.dart | 543 ++-- .../wallet_settings_view.dart | 748 ++--- .../change_representative_view.dart | 325 +-- .../delete_wallet_recovery_phrase_view.dart | 484 ++-- .../delete_wallet_warning_view.dart | 242 +- .../edit_refresh_height_view.dart | 100 +- .../lelantus_settings_view.dart | 141 +- .../rbf_settings_view.dart | 93 +- .../rename_wallet_view.dart | 185 +- .../spark_info.dart | 54 +- .../wallet_settings_wallet_settings_view.dart | 574 ++-- .../xpub_view.dart | 224 +- .../confirm_spark_name_transaction_view.dart | 42 +- .../firo_rescan_recovery_error_dialog.dart | 286 +- lib/pages/token_view/my_tokens_view.dart | 212 +- lib/pages/token_view/token_view.dart | 171 +- .../transaction_views/edit_note_view.dart | 210 +- .../transaction_details_view.dart | 2216 ++++++++------- .../transaction_search_filter_view.dart | 510 ++-- .../tx_v2/boost_transaction_view.dart | 2 +- .../tx_v2/fusion_group_details_view.dart | 84 +- .../tx_v2/transaction_v2_details_view.dart | 2506 +++++++++-------- lib/widgets/desktop/desktop_scaffold.dart | 14 +- 107 files changed, 17699 insertions(+), 18227 deletions(-) diff --git a/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart b/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart index 210fc954f..8d141eb15 100644 --- a/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart @@ -29,9 +29,7 @@ import '../../../widgets/desktop/secondary_button.dart'; import '../../../widgets/stack_dialog.dart'; class AddCustomTokenView extends ConsumerStatefulWidget { - const AddCustomTokenView({ - super.key, - }); + const AddCustomTokenView({super.key}); static const routeName = "/addCustomToken"; @@ -56,60 +54,62 @@ class _AddCustomTokenViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - body: Padding( - padding: const EdgeInsets.only( - top: 10, - left: 16, - right: 16, - bottom: 16, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only( + top: 10, + left: 16, + right: 16, + bottom: 16, + ), + child: child, + ), + ), ), - child: child, ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => Column( children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Add custom ETH token", - style: STextStyles.desktopH3(context), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Add custom ETH token", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Flexible( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + top: 16, + ), + child: child, ), ), - const DesktopDialogCloseButton(), ], ), - Flexible( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - top: 16, - ), - child: child, - ), - ), - ], - ), child: Column( children: [ if (!isDesktop) @@ -117,10 +117,7 @@ class _AddCustomTokenViewState extends ConsumerState { "Add custom ETH token", style: STextStyles.pageTitleH1(context), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), TextField( autocorrect: !isDesktop, enableSuggestions: !isDesktop, @@ -131,9 +128,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), PrimaryButton( label: "Search", onPressed: () async { @@ -157,10 +152,11 @@ class _AddCustomTokenViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => StackOkDialog( - title: "Failed to look up token", - message: response!.exception?.message, - ), + builder: + (context) => StackOkDialog( + title: "Failed to look up token", + message: response!.exception?.message, + ), ), ); } @@ -170,9 +166,7 @@ class _AddCustomTokenViewState extends ConsumerState { }); }, ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), TextField( enabled: enableSubFields, autocorrect: !isDesktop, @@ -184,9 +178,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), if (isDesktop) Row( children: [ @@ -203,9 +195,7 @@ class _AddCustomTokenViewState extends ConsumerState { ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: TextField( enabled: enableSubFields, @@ -245,10 +235,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - if (!isDesktop) - const SizedBox( - height: 8, - ), + if (!isDesktop) const SizedBox(height: 8), if (!isDesktop) TextField( enabled: enableSubFields, @@ -273,9 +260,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -286,10 +271,7 @@ class _AddCustomTokenViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - if (isDesktop) - const SizedBox( - width: 16, - ), + if (isDesktop) const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Add token", diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart index 46fa6f333..3294ce18f 100644 --- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart @@ -96,10 +96,11 @@ class _EditWalletTokensViewState extends ConsumerState { } Future onNextPressed() async { - final selectedTokens = tokenEntities - .where((e) => e.selected) - .map((e) => e.token.address) - .toList(); + final selectedTokens = + tokenEntities + .where((e) => e.selected) + .map((e) => e.token.address) + .toList(); final ethWallet = ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet; @@ -110,14 +111,13 @@ class _EditWalletTokensViewState extends ConsumerState { Navigator.of(context).pop(42); } else { if (isDesktop) { - Navigator.of(context).popUntil( - ModalRoute.withName(DesktopHomeView.routeName), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { - await Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, - ); + await Navigator.of( + context, + ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false); } if (mounted) { unawaited( @@ -138,16 +138,17 @@ class _EditWalletTokensViewState extends ConsumerState { if (isDesktop) { contract = await showDialog( context: context, - builder: (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomTokenView(), - ), + builder: + (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomTokenView(), + ), ); } else { - final result = await Navigator.of(context).pushNamed( - AddCustomTokenView.routeName, - ); + final result = await Navigator.of( + context, + ).pushNamed(AddCustomTokenView.routeName); contract = result as EthContract?; } @@ -159,8 +160,9 @@ class _EditWalletTokensViewState extends ConsumerState { if (tokenEntities .where((e) => e.token.address == contract!.address) .isEmpty) { - tokenEntities - .add(AddTokenListElementData(contract!)..selected = true); + tokenEntities.add( + AddTokenListElementData(contract!)..selected = true, + ); tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name)); } }); @@ -178,7 +180,9 @@ class _EditWalletTokensViewState extends ConsumerState { if (contracts.isEmpty) { contracts.addAll(DefaultTokens.list); - MainDB.instance.putEthContracts(contracts).then( + MainDB.instance + .putEthContracts(contracts) + .then( (_) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice(), ); } @@ -214,149 +218,135 @@ class _EditWalletTokensViewState extends ConsumerState { if (isDesktop) { return ConditionalParent( condition: !widget.isDesktopPopup, - builder: (child) => DesktopScaffold( - appBar: DesktopAppBar( - isCompactHeight: false, - useSpacers: false, - leading: const AppBarBackButton(), - overlayCenter: Text( - walletName, - style: STextStyles.desktopSubtitleH2(context), - ), - trailing: widget.contractsToMarkSelected == null - ? Padding( - padding: const EdgeInsets.only( - right: 24, - ), - child: SizedBox( - height: 56, - child: TextButton( - style: Theme.of(context) - .extension()! - .getSmallSecondaryEnabledButtonStyle(context), - onPressed: _addToken, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 30, - ), - child: Text( - "Add custom token", - style: - STextStyles.desktopButtonSmallSecondaryEnabled( - context, + builder: + (child) => DesktopScaffold( + appBar: DesktopAppBar( + isCompactHeight: false, + useSpacers: false, + leading: const AppBarBackButton(), + overlayCenter: Text( + walletName, + style: STextStyles.desktopSubtitleH2(context), + ), + trailing: + widget.contractsToMarkSelected == null + ? Padding( + padding: const EdgeInsets.only(right: 24), + child: SizedBox( + height: 56, + child: TextButton( + style: Theme.of(context) + .extension()! + .getSmallSecondaryEnabledButtonStyle(context), + onPressed: _addToken, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 30, + ), + child: Text( + "Add custom token", + style: + STextStyles.desktopButtonSmallSecondaryEnabled( + context, + ), + ), + ), ), ), + ) + : null, + ), + body: SizedBox( + width: 480, + child: Column( + children: [ + const AddTokenText(isDesktop: true), + const SizedBox(height: 16), + Expanded( + child: RoundedWhiteContainer( + radiusMultiplier: 2, + padding: const EdgeInsets.only( + left: 20, + top: 20, + right: 20, + bottom: 0, ), + child: child, ), ), - ) - : null, - ), - body: SizedBox( - width: 480, - child: Column( - children: [ - const AddTokenText( - isDesktop: true, - ), - const SizedBox( - height: 16, - ), - Expanded( - child: RoundedWhiteContainer( - radiusMultiplier: 2, - padding: const EdgeInsets.only( - left: 20, - top: 20, - right: 20, - bottom: 0, + const SizedBox(height: 26), + SizedBox( + height: 70, + width: 480, + child: PrimaryButton( + label: + widget.contractsToMarkSelected != null + ? "Save" + : "Next", + onPressed: onNextPressed, + ), ), - child: child, - ), - ), - const SizedBox( - height: 26, - ), - SizedBox( - height: 70, - width: 480, - child: PrimaryButton( - label: widget.contractsToMarkSelected != null - ? "Save" - : "Next", - onPressed: onNextPressed, - ), - ), - const SizedBox( - height: 32, + const SizedBox(height: 32), + ], ), - ], + ), ), - ), - ), child: ConditionalParent( condition: widget.isDesktopPopup, - builder: (child) => DesktopDialog( - maxHeight: 670, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxHeight: 670, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Edit tokens", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - vertical: 16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Edit tokens", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - child: child, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Add custom token", - buttonHeight: ButtonHeight.l, - onPressed: _addToken, + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 16, ), + child: child, ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Done", - buttonHeight: ButtonHeight.l, - onPressed: onNextPressed, - ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Add custom token", + buttonHeight: ButtonHeight.l, + onPressed: _addToken, + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Done", + buttonHeight: ButtonHeight.l, + onPressed: onNextPressed, + ), + ), + ], ), - ], - ), - ), - const SizedBox( - height: 32, + ), + const SizedBox(height: 32), + ], ), - ], - ), - ), + ), child: Column( children: [ ClipRRect( @@ -373,17 +363,15 @@ class _EditWalletTokensViewState extends ConsumerState { _searchTerm = value; }); }, - style: STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ), + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), decoration: standardInputDecoration( "Search", _searchFocusNode, context, ).copyWith( - contentPadding: const EdgeInsets.symmetric( - vertical: 10, - ), + contentPadding: const EdgeInsets.symmetric(vertical: 10), prefixIcon: Padding( padding: const EdgeInsets.symmetric( horizontal: 16, @@ -393,40 +381,37 @@ class _EditWalletTokensViewState extends ConsumerState { Assets.svg.search, width: 24, height: 24, - color: Theme.of(context) - .extension()! - .textFieldDefaultSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldDefaultSearchIconLeft, ), ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 10), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon( - width: 24, - height: 24, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 10), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(width: 24, height: 24), + onTap: () async { + setState(() { + _searchFieldController.text = ""; + _searchTerm = ""; + }); + }, ), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, - ), - ], + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Expanded( child: AddTokenList( walletId: widget.walletId, @@ -434,9 +419,7 @@ class _EditWalletTokensViewState extends ConsumerState { addFunction: isDesktop ? null : _addToken, ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ], ), ), @@ -454,11 +437,7 @@ class _EditWalletTokensViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 20), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -468,9 +447,10 @@ class _EditWalletTokensViewState extends ConsumerState { Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, width: 20, height: 20, ), @@ -480,92 +460,89 @@ class _EditWalletTokensViewState extends ConsumerState { ), ], ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - AddTokenText( - isDesktop: false, - walletName: walletName, - ), - const SizedBox( - height: 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchFieldController, - focusNode: _searchFocusNode, - onChanged: (value) => setState(() => _searchTerm = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + AddTokenText(isDesktop: false, walletName: walletName), + const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchFieldController, + focusNode: _searchFocusNode, + onChanged: + (value) => setState(() => _searchTerm = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchFieldController.text = + ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: AddTokenList( - walletId: widget.walletId, - items: filter(_searchTerm, tokenEntities), - addFunction: _addToken, + const SizedBox(height: 10), + Expanded( + child: AddTokenList( + walletId: widget.walletId, + items: filter(_searchTerm, tokenEntities), + addFunction: _addToken, + ), ), - ), - const SizedBox( - height: 16, - ), - PrimaryButton( - label: widget.contractsToMarkSelected != null - ? "Save" - : "Next", - onPressed: onNextPressed, - ), - ], + const SizedBox(height: 16), + PrimaryButton( + label: + widget.contractsToMarkSelected != null + ? "Save" + : "Next", + onPressed: onNextPressed, + ), + ], + ), ), ), ), diff --git a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart index 748f5074e..ef4248d0b 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart @@ -61,9 +61,7 @@ class _AddWalletViewState extends ConsumerState { String _searchTerm = ""; - final _coinsTestnet = [ - ...AppConfig.coins.where((e) => e.network.isTestNet), - ]; + final _coinsTestnet = [...AppConfig.coins.where((e) => e.network.isTestNet)]; final _coins = [ ...AppConfig.coins.where((e) => e.network == CryptoCurrencyNetwork.main), ]; @@ -98,16 +96,17 @@ class _AddWalletViewState extends ConsumerState { if (isDesktop) { contract = await showDialog( context: context, - builder: (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomTokenView(), - ), + builder: + (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomTokenView(), + ), ); } else { - contract = await Navigator.of(context).pushNamed( - AddCustomTokenView.routeName, - ); + contract = await Navigator.of( + context, + ).pushNamed(AddCustomTokenView.routeName); } if (contract != null) { @@ -143,7 +142,9 @@ class _AddWalletViewState extends ConsumerState { if (contracts.isEmpty) { contracts.addAll(DefaultTokens.list); - MainDB.instance.putEthContracts(contracts).then( + MainDB.instance + .putEthContracts(contracts) + .then( (value) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice(), ); @@ -184,12 +185,8 @@ class _AddWalletViewState extends ConsumerState { ), body: Column( children: [ - const AddWalletText( - isDesktop: true, - ), - const SizedBox( - height: 16, - ), + const AddWalletText(isDesktop: true), + const SizedBox(height: 16), Expanded( child: SizedBox( width: 480, @@ -219,10 +216,9 @@ class _AddWalletViewState extends ConsumerState { _searchTerm = value; }); }, - style: - STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ), + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), decoration: standardInputDecoration( "Search", _searchFocusNode, @@ -240,42 +236,44 @@ class _AddWalletViewState extends ConsumerState { Assets.svg.search, width: 24, height: 24, - color: Theme.of(context) - .extension()! - .textFieldDefaultSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldDefaultSearchIconLeft, ), ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 10), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon( - width: 24, - height: 24, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 10, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon( + width: 24, + height: 24, + ), + onTap: () async { + setState(() { + _searchFieldController + .text = ""; + _searchTerm = ""; + }); + }, ), - onTap: () async { - setState(() { - _searchFieldController.text = - ""; - _searchTerm = ""; - }); - }, - ), - ], + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: SingleChildScrollView( child: Column( @@ -289,8 +287,10 @@ class _AddWalletViewState extends ConsumerState { if (coinTestnetEntities.isNotEmpty) ExpandingSubListItem( title: "Testnet", - entities: - filter(_searchTerm, coinTestnetEntities), + entities: filter( + _searchTerm, + coinTestnetEntities, + ), initialState: ExpandableState.expanded, animationDurationMultiplier: 0.5, ), @@ -308,27 +308,19 @@ class _AddWalletViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ], ), ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const SizedBox( height: 70, width: 480, - child: AddWalletNextButton( - isDesktop: true, - ), - ), - const SizedBox( - height: 32, + child: AddWalletNextButton(isDesktop: true), ), + const SizedBox(height: 32), ], ), ); @@ -344,113 +336,109 @@ class _AddWalletViewState extends ConsumerState { }, ), ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const AddWalletText( - isDesktop: false, - ), - const SizedBox( - height: 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: Semantics( - label: - "Search Text Field. Inputs Text To Search In Wallets.", - excludeSemantics: true, - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchFieldController, - focusNode: _searchFocusNode, - onChanged: (value) => - setState(() => _searchTerm = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const AddWalletText(isDesktop: false), + const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: Semantics( + label: + "Search Text Field. Inputs Text To Search In Wallets.", + excludeSemantics: true, + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchFieldController, + focusNode: _searchFocusNode, + onChanged: + (value) => setState(() => _searchTerm = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchFieldController.text = + ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - ExpandingSubListItem( - title: "Coins", - entities: filter(_searchTerm, coinEntities), - initialState: ExpandableState.expanded, - ), - if (coinTestnetEntities.isNotEmpty) - ExpandingSubListItem( - title: "Testnet", - entities: - filter(_searchTerm, coinTestnetEntities), - initialState: ExpandableState.expanded, - ), - if (tokenEntities.isNotEmpty) + const SizedBox(height: 10), + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ ExpandingSubListItem( - title: "Tokens", - entities: filter(_searchTerm, tokenEntities), + title: "Coins", + entities: filter(_searchTerm, coinEntities), initialState: ExpandableState.expanded, ), - ], + if (coinTestnetEntities.isNotEmpty) + ExpandingSubListItem( + title: "Testnet", + entities: filter( + _searchTerm, + coinTestnetEntities, + ), + initialState: ExpandableState.expanded, + ), + if (tokenEntities.isNotEmpty) + ExpandingSubListItem( + title: "Tokens", + entities: filter(_searchTerm, tokenEntities), + initialState: ExpandableState.expanded, + ), + ], + ), ), ), - ), - const SizedBox( - height: 16, - ), - const AddWalletNextButton( - isDesktop: false, - ), - ], + const SizedBox(height: 16), + const AddWalletNextButton(isDesktop: false), + ], + ), ), ), ), diff --git a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart index d377eff72..e00f679cb 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; + import '../../../../frost_route_generator.dart'; import '../../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; import '../../../../themes/stack_colors.dart'; @@ -43,76 +44,77 @@ class _SelectNewFrostImportTypeViewState Widget build(BuildContext context) { return ConditionalParent( condition: Util.isDesktop, - builder: (content) => DesktopScaffold( - appBar: const DesktopAppBar( - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - isCompactHeight: false, - ), - body: SizedBox( - width: 480, - child: content, - ), - ), + builder: + (content) => DesktopScaffold( + appBar: const DesktopAppBar( + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + isCompactHeight: false, + ), + body: SizedBox(width: 480, child: content), + ), child: ConditionalParent( condition: !Util.isDesktop, - builder: (content) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - Theme.of(context) - .extension()! - .topNavIconPrimary, - BlendMode.srcIn, - ), - ), - onPressed: () async { - await showDialog( - context: context, - builder: (_) => const _FrostJoinInfoDialog(), - ); + builder: + (content) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); }, ), - ), - ], - ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (ctx, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: content, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + colorFilter: ColorFilter.mode( + Theme.of( + context, + ).extension()!.topNavIconPrimary, + BlendMode.srcIn, + ), ), + onPressed: () async { + await showDialog( + context: context, + builder: (_) => const _FrostJoinInfoDialog(), + ); + }, ), - ); - }, + ), + ], + ), + body: SafeArea( + child: Container( + color: + Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (ctx, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: content), + ), + ); + }, + ), + ), + ), ), ), ), - ), - ), child: Column( children: [ ..._ImportOption.values.map( @@ -163,9 +165,9 @@ class _SelectNewFrostImportTypeViewState break; } - await Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + await Navigator.of( + context, + ).pushNamed(FrostStepScaffold.routeName); }, ), ], @@ -232,9 +234,10 @@ class _ImportOptionCardState extends State<_ImportOptionCard> { child: Radio( value: widget.value, groupValue: widget.groupValue, - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, onChanged: (_) => widget.onPressed(), ), ), @@ -257,18 +260,17 @@ class _ImportOptionCardState extends State<_ImportOptionCard> { ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Row( children: [ Expanded( child: Text( widget.description, style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), @@ -293,21 +295,14 @@ class _FrostJoinInfoDialog extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Join a group", - style: STextStyles.w600_20(context), - ), - const SizedBox( - height: 12, - ), + Text("Join a group", style: STextStyles.w600_20(context)), + const SizedBox(height: 12), Text( "You should select 'Join a new group' if you are creating a brand " "new wallet with other people.", style: STextStyles.w600_16(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Text( "You should select 'Join an existing group' if you an existing " "group is being edited and you are being added as a participant.", diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index 91aa555f6..ec7419d96 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -110,10 +110,7 @@ class _NameYourWalletViewState extends ConsumerState { coin is ViewOnlyOptionCurrencyInterface ? NewWalletOptionsView.routeName : NewWalletRecoveryPhraseWarningView.routeName, - arguments: Tuple2( - name, - coin, - ), + arguments: Tuple2(name, coin), ), ); break; @@ -122,10 +119,7 @@ class _NameYourWalletViewState extends ConsumerState { unawaited( Navigator.of(context).pushNamed( RestoreOptionsView.routeName, - arguments: Tuple2( - name, - coin, - ), + arguments: Tuple2(name, coin), ), ); break; @@ -145,9 +139,7 @@ class _NameYourWalletViewState extends ConsumerState { .where() .nameProperty() .findAll() - .then( - (values) => namesToExclude.addAll(values), - ); + .then((values) => namesToExclude.addAll(values)); generator = NameGenerator(); addWalletType = widget.addWalletType; coin = widget.coin; @@ -177,10 +169,7 @@ class _NameYourWalletViewState extends ConsumerState { trailing: ExitToMyStackButton(), isCompactHeight: false, ), - body: SizedBox( - width: 480, - child: _content(), - ), + body: SizedBox(width: 480, child: _content()), ); } else { return Background( @@ -192,8 +181,9 @@ class _NameYourWalletViewState extends ConsumerState { onPressed: () { if (textFieldFocusNode.hasFocus) { textFieldFocusNode.unfocus(); - Future.delayed(const Duration(milliseconds: 100)) - .then((value) => Navigator.of(context).pop()); + Future.delayed( + const Duration(milliseconds: 100), + ).then((value) => Navigator.of(context).pop()); } else { if (mounted) { Navigator.of(context).pop(); @@ -202,22 +192,23 @@ class _NameYourWalletViewState extends ConsumerState { }, ), ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (ctx, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _content(), + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (ctx, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _content()), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -227,284 +218,251 @@ class _NameYourWalletViewState extends ConsumerState { } Widget _content() => Column( - crossAxisAlignment: - isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch, - children: [ - if (isDesktop) - const Spacer( - flex: 10, - ), - if (!isDesktop) - const Spacer( - flex: 1, - ), - if (!isDesktop) - CoinImage( - coin: coin, - height: 100, - width: 100, - ), - SizedBox( - height: isDesktop ? 0 : 16, - ), - Text( - "Name your ${coin.prettyName} ${coin is FrostCurrency ? "multisig " : ""}wallet", - textAlign: TextAlign.center, - style: isDesktop + crossAxisAlignment: + isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch, + children: [ + if (isDesktop) const Spacer(flex: 10), + if (!isDesktop) const Spacer(flex: 1), + if (!isDesktop) CoinImage(coin: coin, height: 100, width: 100), + SizedBox(height: isDesktop ? 0 : 16), + Text( + "Name your ${coin.prettyName} ${coin is FrostCurrency ? "multisig " : ""}wallet", + textAlign: TextAlign.center, + style: + isDesktop ? STextStyles.desktopH2(context) : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - Text( - "Enter a label for your wallet (e.g. ${coin is FrostCurrency ? "Multisig" : "Savings"})", - textAlign: TextAlign.center, - style: isDesktop + ), + SizedBox(height: isDesktop ? 16 : 8), + Text( + "Enter a label for your wallet (e.g. ${coin is FrostCurrency ? "Multisig" : "Savings"})", + textAlign: TextAlign.center, + style: + isDesktop ? STextStyles.desktopSubtitleH2(context) : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 40 : 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - onChanged: (string) { - if (string.isEmpty) { - if (_nextEnabled) { - setState(() { - _nextEnabled = false; - _showDiceIcon = true; - }); - } - } else { - if (!_nextEnabled) { - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - } - } - }, - focusNode: textFieldFocusNode, - controller: textEditingController, - style: isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) + ), + SizedBox(height: isDesktop ? 40 : 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + onChanged: (string) { + if (string.isEmpty) { + if (_nextEnabled) { + setState(() { + _nextEnabled = false; + _showDiceIcon = true; + }); + } + } else { + if (!_nextEnabled) { + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + } + } + }, + focusNode: textFieldFocusNode, + controller: textEditingController, + style: + isDesktop + ? STextStyles.desktopTextMedium(context).copyWith(height: 2) : STextStyles.field(context), - decoration: standardInputDecoration( - "Enter wallet name", - textFieldFocusNode, - context, - ).copyWith( - suffixIcon: Padding( - padding: EdgeInsets.only(right: isDesktop ? 6 : 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - key: const Key("genRandomWalletNameButtonKey"), - child: _showDiceIcon + decoration: standardInputDecoration( + "Enter wallet name", + textFieldFocusNode, + context, + ).copyWith( + suffixIcon: Padding( + padding: EdgeInsets.only(right: isDesktop ? 6 : 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + key: const Key("genRandomWalletNameButtonKey"), + child: + _showDiceIcon ? Semantics( - label: - "Generate Random Wallet Name Button. Generates A Random Name For Wallet.", - excludeSemantics: true, - child: DiceIcon( - width: isDesktop ? 20 : 17, - height: isDesktop ? 20 : 17, - ), - ) + label: + "Generate Random Wallet Name Button. Generates A Random Name For Wallet.", + excludeSemantics: true, + child: DiceIcon( + width: isDesktop ? 20 : 17, + height: isDesktop ? 20 : 17, + ), + ) : Semantics( - label: - "Clear Wallet Name Field Button. Clears the wallet name field.", - excludeSemantics: true, - child: XIcon( - width: isDesktop ? 21 : 18, - height: isDesktop ? 21 : 18, - ), + label: + "Clear Wallet Name Field Button. Clears the wallet name field.", + excludeSemantics: true, + child: XIcon( + width: isDesktop ? 21 : 18, + height: isDesktop ? 21 : 18, ), - onTap: () async { - if (_showDiceIcon) { - textEditingController.text = - await _generateRandomWalletName(); - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - } else { - textEditingController.text = ""; - setState(() { - _nextEnabled = false; - _showDiceIcon = true; - }); - } - }, - ), - ], + ), + onTap: () async { + if (_showDiceIcon) { + textEditingController.text = + await _generateRandomWalletName(); + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + } else { + textEditingController.text = ""; + setState(() { + _nextEnabled = false; + _showDiceIcon = true; + }); + } + }, ), - ), + ], ), ), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - GestureDetector( - onTap: () async { - textEditingController.text = await _generateRandomWalletName(); - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - }, - child: RoundedWhiteContainer( - child: Center( - child: Text( - "Roll the dice to pick a random name.", - style: isDesktop + ), + ), + SizedBox(height: isDesktop ? 16 : 8), + GestureDetector( + onTap: () async { + textEditingController.text = await _generateRandomWalletName(); + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + }, + child: RoundedWhiteContainer( + child: Center( + child: Text( + "Roll the dice to pick a random name.", + style: + isDesktop ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ) + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ) : STextStyles.itemSubtitle(context), - ), - ), ), ), - if (!isDesktop) - const Spacer( - flex: 4, - ), - if (isDesktop) - const SizedBox( - height: 32, - ), - if (widget.coin is FrostCurrency) - if (widget.addWalletType == AddWalletType.Restore) - PrimaryButton( - label: "Next", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + ), + ), + if (!isDesktop) const Spacer(flex: 4), + if (isDesktop) const SizedBox(height: 32), + if (widget.coin is FrostCurrency) + if (widget.addWalletType == AddWalletType.Restore) + PrimaryButton( + label: "Next", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - RestoreFrostMsWalletView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - if (widget.coin is FrostCurrency && - widget.addWalletType == AddWalletType.New) - Column( - children: [ - PrimaryButton( - label: "Create new group", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + await Navigator.of(context).pushNamed( + RestoreFrostMsWalletView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, + ), + if (widget.coin is FrostCurrency && + widget.addWalletType == AddWalletType.New) + Column( + children: [ + PrimaryButton( + label: "Create new group", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - CreateNewFrostMsWalletView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Join group", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + await Navigator.of(context).pushNamed( + CreateNewFrostMsWalletView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Join group", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - SelectNewFrostImportTypeView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - // SecondaryButton( - // label: "Import multisig config", - // enabled: _nextEnabled, - // onPressed: () async { - // final name = textEditingController.text; - // - // await Navigator.of(context).pushNamed( - // ImportNewFrostMsWalletView.routeName, - // arguments: ( - // walletName: name, - // coin: coin, - // ), - // ); - // }, - // ), - // const SizedBox( - // height: 12, - // ), - // SecondaryButton( - // label: "Import resharer config", - // enabled: _nextEnabled, - // onPressed: () async { - // final name = textEditingController.text; - // - // await Navigator.of(context).pushNamed( - // NewImportResharerConfigView.routeName, - // arguments: ( - // walletName: name, - // coin: coin, - // ), - // ); - // }, - // ), - ], + await Navigator.of(context).pushNamed( + SelectNewFrostImportTypeView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, ), - if (widget.coin is! FrostCurrency) - ConstrainedBox( - constraints: BoxConstraints( - minWidth: isDesktop ? 480 : 0, - minHeight: isDesktop ? 70 : 0, - ), - child: TextButton( - onPressed: _nextEnabled ? _nextPressed : null, - style: _nextEnabled + // SecondaryButton( + // label: "Import multisig config", + // enabled: _nextEnabled, + // onPressed: () async { + // final name = textEditingController.text; + // + // await Navigator.of(context).pushNamed( + // ImportNewFrostMsWalletView.routeName, + // arguments: ( + // walletName: name, + // coin: coin, + // ), + // ); + // }, + // ), + // const SizedBox( + // height: 12, + // ), + // SecondaryButton( + // label: "Import resharer config", + // enabled: _nextEnabled, + // onPressed: () async { + // final name = textEditingController.text; + // + // await Navigator.of(context).pushNamed( + // NewImportResharerConfigView.routeName, + // arguments: ( + // walletName: name, + // coin: coin, + // ), + // ); + // }, + // ), + ], + ), + if (widget.coin is! FrostCurrency) + ConstrainedBox( + constraints: BoxConstraints( + minWidth: isDesktop ? 480 : 0, + minHeight: isDesktop ? 70 : 0, + ), + child: TextButton( + onPressed: _nextEnabled ? _nextPressed : null, + style: + _nextEnabled ? Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context) : Theme.of(context) .extension()! .getPrimaryDisabledButtonStyle(context), - child: Text( - "Next", - style: isDesktop + child: Text( + "Next", + style: + isDesktop ? _nextEnabled ? STextStyles.desktopButtonEnabled(context) : STextStyles.desktopButtonDisabled(context) : STextStyles.button(context), - ), - ), - ), - if (isDesktop) - const Spacer( - flex: 15, ), - ], - ); + ), + ), + if (isDesktop) const Spacer(flex: 15), + ], + ); } diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart index 852803f6f..64af27507 100644 --- a/lib/pages/address_book_views/address_book_view.dart +++ b/lib/pages/address_book_views/address_book_view.dart @@ -15,7 +15,6 @@ import 'package:flutter_svg/svg.dart'; import '../../app_config.dart'; import '../../models/isar/models/blockchain_data/address.dart'; import '../../models/isar/models/contact_entry.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/global/address_book_service_provider.dart'; import '../../providers/providers.dart'; import '../../providers/ui/address_book_providers/address_book_filter_provider.dart'; @@ -38,11 +37,7 @@ import 'subviews/add_address_book_entry_view.dart'; import 'subviews/address_book_filter_view.dart'; class AddressBookView extends ConsumerStatefulWidget { - const AddressBookView({ - super.key, - this.coin, - this.filterTerm, - }); + const AddressBookView({super.key, this.coin, this.filterTerm}); static const String routeName = "/addressBook"; @@ -67,9 +62,7 @@ class _AddressBookViewState extends ConsumerState { if (widget.coin == null) { final coins = [...AppConfig.coins]; - coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + coins.removeWhere((e) => e is Firo && e.network.isTestNet); final bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins; @@ -77,7 +70,9 @@ class _AddressBookViewState extends ConsumerState { if (showTestNet) { ref.read(addressBookFilterProvider).addAll(coins, false); } else { - ref.read(addressBookFilterProvider).addAll( + ref + .read(addressBookFilterProvider) + .addAll( coins.where((e) => e.network != CryptoCurrencyNetwork.test), false, ); @@ -132,8 +127,9 @@ class _AddressBookViewState extends ConsumerState { @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final contacts = - ref.watch(addressBookServiceProvider.select((value) => value.contacts)); + final contacts = ref.watch( + addressBookServiceProvider.select((value) => value.contacts), + ); final isDesktop = Util.isDesktop; return ConditionalParent( @@ -166,21 +162,23 @@ class _AddressBookViewState extends ConsumerState { key: const Key("addressBookFilterViewButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), onPressed: () { - Navigator.of(context).pushNamed( - AddressBookFilterView.routeName, - ); + Navigator.of( + context, + ).pushNamed(AddressBookFilterView.routeName); }, ), ), @@ -197,56 +195,60 @@ class _AddressBookViewState extends ConsumerState { key: const Key("addressBookAddNewContactViewButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.plus, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), onPressed: () { - Navigator.of(context).pushNamed( - AddAddressBookEntryView.routeName, - ); + Navigator.of( + context, + ).pushNamed(AddAddressBookEntryView.routeName); }, ), ), ), ], ), - body: LayoutBuilder( - builder: (builderContext, 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: ConstrainedBox( - constraints: BoxConstraints( - minHeight: - MediaQuery.of(context).size.height - 271, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: ConstrainedBox( + constraints: BoxConstraints( + minHeight: + MediaQuery.of(context).size.height - 271, + ), + child: child, ), - child: child, ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -258,66 +260,63 @@ class _AddressBookViewState extends ConsumerState { borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), - child: !isDesktop - ? TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (value) { - setState(() { - _searchTerm = value; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + child: + !isDesktop + ? TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (value) { + setState(() { + _searchTerm = value; + }); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, - ), - ) - : null, + ), + ) + : null, + ), + ) + : null, ), if (!isDesktop) const SizedBox(height: 16), - Text( - "Favorites", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + Text("Favorites", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), if (contacts.isNotEmpty) RoundedWhiteContainer( padding: EdgeInsets.all(!isDesktop ? 0 : 15), @@ -325,15 +324,16 @@ class _AddressBookViewState extends ConsumerState { children: [ ...contacts .where( - (element) => element.addressesSorted - .where( - (e) => ref.watch( - addressBookFilterProvider.select( - (value) => value.coins.contains(e.coin), - ), - ), - ) - .isNotEmpty, + (element) => + element.addressesSorted + .where( + (e) => ref.watch( + addressBookFilterProvider.select( + (value) => value.coins.contains(e.coin), + ), + ), + ) + .isNotEmpty, ) .where( (e) => @@ -361,16 +361,9 @@ class _AddressBookViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), - Text( - "All contacts", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 16), + Text("All contacts", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), if (contacts.isNotEmpty) Column( children: [ @@ -382,15 +375,17 @@ class _AddressBookViewState extends ConsumerState { children: [ ...contacts .where( - (element) => element.addressesSorted - .where( - (e) => ref.watch( - addressBookFilterProvider.select( - (value) => value.coins.contains(e.coin), - ), - ), - ) - .isNotEmpty, + (element) => + element.addressesSorted + .where( + (e) => ref.watch( + addressBookFilterProvider.select( + (value) => + value.coins.contains(e.coin), + ), + ), + ) + .isNotEmpty, ) .where( (e) => ref @@ -399,8 +394,9 @@ class _AddressBookViewState extends ConsumerState { ) .map( (e) => AddressBookCard( - key: - Key("desktopContactCard_${e.customId}_key"), + key: Key( + "desktopContactCard_${e.customId}_key", + ), contactId: e.customId, ), ), diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart index 66b4b1aa9..22ecb4407 100644 --- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart +++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart @@ -163,18 +163,20 @@ class _AddAddressBookEntryViewState key: const Key("addAddressBookEntryFavoriteButtonKey"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.star, - color: _isFavorite - ? Theme.of(context) - .extension()! - .favoriteStarActive - : Theme.of(context) - .extension()! - .favoriteStarInactive, + color: + _isFavorite + ? Theme.of( + context, + ).extension()!.favoriteStarActive + : Theme.of(context) + .extension()! + .favoriteStarInactive, width: 20, height: 20, ), @@ -188,7 +190,7 @@ class _AddAddressBookEntryViewState ), ], ), - body: child, + body: SafeArea(child: child), ), ); }, @@ -252,155 +254,160 @@ class _AddAddressBookEntryViewState if (!isDesktop) const SizedBox(height: 4), isDesktop ? Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - height: 56, - width: 56, - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - if (_selectedEmoji != null) { - setState(() { - _selectedEmoji = null; - }); - return; - } + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 56, + width: 56, + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + if (_selectedEmoji != null) { + setState(() { + _selectedEmoji = null; + }); + return; + } - showDialog( - context: context, - builder: (context) { - return const DesktopDialog( - maxHeight: 700, - maxWidth: 600, - child: Padding( - padding: EdgeInsets.only( - left: 32, - right: 20, - top: 32, - bottom: 32, - ), - child: EmojiSelectSheet(), + showDialog( + context: context, + builder: (context) { + return const DesktopDialog( + maxHeight: 700, + maxWidth: 600, + child: Padding( + padding: EdgeInsets.only( + left: 32, + right: 20, + top: 32, + bottom: 32, ), - ); - }, - ).then((value) { - if (value is Emoji) { - setState(() { - _selectedEmoji = value; - }); - } - }); - }, - child: Stack( - children: [ - Container( - height: 56, - width: 56, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(100), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + child: EmojiSelectSheet(), ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ); + }, + ).then((value) { + if (value is Emoji) { + setState(() { + _selectedEmoji = value; + }); + } + }); + }, + child: Stack( + children: [ + Container( + height: 56, + width: 56, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(100), + color: + Theme.of(context) + .extension()! + .textFieldActiveBG, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.user, height: 30, width: 30, ) - : Text( + : Text( _selectedEmoji!.char, - style: STextStyles - .pageTitleH1( - context, - ), + style: + STextStyles.pageTitleH1( + context, + ), ), - ), ), - Align( - alignment: Alignment.bottomRight, - child: Container( - height: 14, - width: 14, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular( - 14, - ), - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ), + Align( + alignment: Alignment.bottomRight, + child: Container( + height: 14, + width: 14, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(14), + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.plus, - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 12, height: 12, ) - : SvgPicture.asset( + : SvgPicture.asset( Assets.svg.thickX, - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 8, height: 8, ), - ), ), ), - ], - ), + ), + ], ), ), ), - const SizedBox(width: 8), - SizedBox( - width: isDesktop ? 450 : null, - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: - Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: nameController, - focusNode: nameFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter contact name", - nameFocusNode, + ), + const SizedBox(width: 8), + SizedBox( + width: isDesktop ? 450 : null, + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: + Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: nameController, + focusNode: nameFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter contact name", + nameFocusNode, + context, + ).copyWith( + labelStyle: STextStyles.fieldLabel( context, - ).copyWith( - labelStyle: - STextStyles.fieldLabel(context), - suffixIcon: ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state - ? Padding( + ), + suffixIcon: + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state + ? Padding( padding: const EdgeInsets.only( - right: 0, - ), + right: 0, + ), child: UnconstrainedBox( child: Row( children: [ @@ -417,143 +424,153 @@ class _AddAddressBookEntryViewState ), ), ) - : null, - ), - onChanged: (newValue) { - ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state = newValue.isNotEmpty; - }, + : null, ), + onChanged: (newValue) { + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state = newValue.isNotEmpty; + }, ), ), - ], - ) + ), + ], + ) : Column( - children: [ - GestureDetector( - onTap: () { - if (_selectedEmoji != null) { + children: [ + GestureDetector( + onTap: () { + if (_selectedEmoji != null) { + setState(() { + _selectedEmoji = null; + }); + return; + } + + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) => const EmojiSelectSheet(), + ).then((value) { + if (value is Emoji) { setState(() { - _selectedEmoji = null; + _selectedEmoji = value; }); - return; } - - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - const EmojiSelectSheet(), - ).then((value) { - if (value is Emoji) { - setState(() { - _selectedEmoji = value; - }); - } - }); - }, - child: SizedBox( - height: 48, - width: 48, - child: Stack( - children: [ - Container( - height: 48, - width: 48, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + }); + }, + child: SizedBox( + height: 48, + width: 48, + child: Stack( + children: [ + Container( + height: 48, + width: 48, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + 24, ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + color: + Theme.of(context) + .extension()! + .textFieldActiveBG, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.user, height: 24, width: 24, ) - : Text( + : Text( _selectedEmoji!.char, - style: STextStyles - .pageTitleH1(context), + style: + STextStyles.pageTitleH1( + context, + ), ), - ), ), - Align( - alignment: Alignment.bottomRight, - child: Container( - height: 14, - width: 14, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(14), - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ), + Align( + alignment: Alignment.bottomRight, + child: Container( + height: 14, + width: 14, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(14), + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.plus, - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 12, height: 12, ) - : SvgPicture.asset( + : SvgPicture.asset( Assets.svg.thickX, - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 8, height: 8, ), - ), ), ), - ], - ), + ), + ], ), ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: - Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: nameController, - focusNode: nameFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter contact name", - nameFocusNode, - context, - ).copyWith( - suffixIcon: ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state - ? Padding( + ), + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: nameController, + focusNode: nameFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter contact name", + nameFocusNode, + context, + ).copyWith( + suffixIcon: + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state + ? Padding( padding: const EdgeInsets.only( right: 0, ), @@ -573,34 +590,29 @@ class _AddAddressBookEntryViewState ), ), ) - : null, - ), - onChanged: (newValue) { - ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state = newValue.isNotEmpty; - }, + : null, ), + onChanged: (newValue) { + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state = newValue.isNotEmpty; + }, ), - ], - ), + ), + ], + ), const SizedBox(height: 8), - if (forms.length <= 1) - const SizedBox( - height: 8, - ), + if (forms.length <= 1) const SizedBox(height: 8), if (forms.length <= 1) forms[0], if (forms.length > 1) for (int i = 0; i < forms.length; i++) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -617,15 +629,11 @@ class _AddAddressBookEntryViewState ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), forms[i], ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), CustomTextButton( onTap: () { _addForm(); @@ -644,9 +652,7 @@ class _AddAddressBookEntryViewState // style: STextStyles.largeMedium14(context), // ), // ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -668,18 +674,17 @@ class _AddAddressBookEntryViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: Builder( builder: (context) { - final bool nameExists = ref - .watch( - contactNameIsNotEmptyStateProvider - .state, - ) - .state; + final bool nameExists = + ref + .watch( + contactNameIsNotEmptyStateProvider + .state, + ) + .state; final bool validForms = ref.watch( validContactStateProvider( @@ -697,55 +702,62 @@ class _AddAddressBookEntryViewState buttonHeight: isDesktop ? ButtonHeight.m : null, enabled: shouldEnableSave, - onPressed: shouldEnableSave - ? () async { - if (FocusScope.of(context) - .hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration( - milliseconds: 75, - ), - ); - } - final List - entries = []; - for (int i = 0; + onPressed: + shouldEnableSave + ? () async { + if (FocusScope.of( + context, + ).hasFocus) { + FocusScope.of( + context, + ).unfocus(); + await Future.delayed( + const Duration( + milliseconds: 75, + ), + ); + } + final List + entries = []; + for ( + int i = 0; i < forms.length; - i++) { - entries.add( - ref - .read( - addressEntryDataProvider( - forms[i].id, - ), - ) - .buildAddressEntry(), - ); - } - final ContactEntry contact = - ContactEntry( - emojiChar: _selectedEmoji?.char, - name: nameController.text, - addresses: entries, - isFavorite: _isFavorite, - customId: const Uuid().v1(), - ); + i++ + ) { + entries.add( + ref + .read( + addressEntryDataProvider( + forms[i].id, + ), + ) + .buildAddressEntry(), + ); + } + final ContactEntry contact = + ContactEntry( + emojiChar: + _selectedEmoji?.char, + name: nameController.text, + addresses: entries, + isFavorite: _isFavorite, + customId: const Uuid().v1(), + ); - if (await ref - .read( - addressBookServiceProvider, - ) - .addContact(contact)) { - if (mounted) { - Navigator.of(context).pop(); + if (await ref + .read( + addressBookServiceProvider, + ) + .addContact(contact)) { + if (mounted) { + Navigator.of(context).pop(); + } + // TODO show success notification + } else { + // TODO show error notification } - // TODO show success notification - } else { - // TODO show error notification } - } - : null, + : null, ); }, ), diff --git a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart index fc59eca68..2954c4d3f 100644 --- a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart @@ -68,61 +68,67 @@ class _AddNewContactAddressViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final isDesktop = Util.isDesktop; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Add new address", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Add new address", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: 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: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -132,31 +138,28 @@ class _AddNewContactAddressViewState width: 48, decoration: BoxDecoration( borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + child: + contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (isDesktop) - Text( - contact.name, - style: STextStyles.pageTitleH2(context), - ), + Text(contact.name, style: STextStyles.pageTitleH2(context)), if (!isDesktop) Expanded( child: FittedBox( @@ -169,17 +172,13 @@ class _AddNewContactAddressViewState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), NewContactAddressEntryForm( id: 0, barcodeScanner: barcodeScanner, clipboard: clipboard, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -200,9 +199,7 @@ class _AddNewContactAddressViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -222,8 +219,9 @@ class _AddNewContactAddressViewState ref.read(addressEntryDataProvider(0)).buildAddressEntry(), ); - final ContactEntry editedContact = - contact.copyWith(addresses: entries); + final ContactEntry editedContact = contact.copyWith( + addresses: entries, + ); if (await ref .read(addressBookServiceProvider) diff --git a/lib/pages/address_book_views/subviews/address_book_filter_view.dart b/lib/pages/address_book_views/subviews/address_book_filter_view.dart index 9feaa0a37..47d14c8bb 100644 --- a/lib/pages/address_book_views/subviews/address_book_filter_view.dart +++ b/lib/pages/address_book_views/subviews/address_book_filter_view.dart @@ -42,9 +42,7 @@ class _AddressBookFilterViewState extends ConsumerState { @override void initState() { final coins = [...AppConfig.coins]; - coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + coins.removeWhere((e) => e is Firo && e.network.isTestNet); final showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins; @@ -81,45 +79,43 @@ class _AddressBookFilterViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Text( - "Only selected cryptocurrency addresses will be displayed.", - style: STextStyles.itemSubtitle(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Text( + "Only selected cryptocurrency addresses will be displayed.", + style: STextStyles.itemSubtitle(context), + ), ), - ), - const SizedBox( - height: 12, - ), - Text( - "Select cryptocurrency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), - child, - ], + const SizedBox(height: 12), + Text( + "Select cryptocurrency", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 12), + child, + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -157,8 +153,9 @@ class _AddressBookFilterViewState extends ConsumerState { child: Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: 32), + padding: const EdgeInsets.symmetric( + horizontal: 32, + ), child: child, ), ], @@ -170,8 +167,10 @@ class _AddressBookFilterViewState extends ConsumerState { ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: 32, vertical: 32), + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 32, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -234,8 +233,9 @@ class _AddressBookFilterViewState extends ConsumerState { child: Checkbox( value: ref .watch( - addressBookFilterProvider - .select((value) => value.coins), + addressBookFilterProvider.select( + (value) => value.coins, + ), ) .contains(coin), onChanged: (value) { @@ -254,9 +254,7 @@ class _AddressBookFilterViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -264,9 +262,7 @@ class _AddressBookFilterViewState extends ConsumerState { coin.prettyName, style: STextStyles.largeMedium14(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( coin.ticker, style: STextStyles.itemSubtitle(context), diff --git a/lib/pages/address_book_views/subviews/contact_details_view.dart b/lib/pages/address_book_views/subviews/contact_details_view.dart index b343c3092..0ee0e6b93 100644 --- a/lib/pages/address_book_views/subviews/contact_details_view.dart +++ b/lib/pages/address_book_views/subviews/contact_details_view.dart @@ -62,24 +62,26 @@ class _ContactDetailsViewState extends ConsumerState { List> _cachedTransactions = []; Future>> - _filteredTransactionsByContact() async { - final contact = - ref.read(addressBookServiceProvider).getContactById(_contactId); + _filteredTransactionsByContact() async { + final contact = ref + .read(addressBookServiceProvider) + .getContactById(_contactId); // TODO: optimise - final transactions = await ref - .read(mainDBProvider) - .isar - .transactions - .where() - .filter() - .anyOf( - contact.addresses.map((e) => e.address), - (q, String e) => q.address((q) => q.valueEqualTo(e)), - ) - .sortByTimestampDesc() - .findAll(); + final transactions = + await ref + .read(mainDBProvider) + .isar + .transactions + .where() + .filter() + .anyOf( + contact.addresses.map((e) => e.address), + (q, String e) => q.address((q) => q.valueEqualTo(e)), + ) + .sortByTimestampDesc() + .findAll(); final List> result = []; @@ -111,8 +113,9 @@ class _ContactDetailsViewState extends ConsumerState { debugPrint("BUILD: $runtimeType"); final _contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(_contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(_contactId), + ), ); return Background( @@ -130,11 +133,7 @@ class _ContactDetailsViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -144,20 +143,23 @@ class _ContactDetailsViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.star, - color: _contact.isFavorite - ? Theme.of(context) - .extension()! - .favoriteStarActive - : Theme.of(context) - .extension()! - .favoriteStarInactive, + color: + _contact.isFavorite + ? Theme.of( + context, + ).extension()!.favoriteStarActive + : Theme.of( + context, + ).extension()!.favoriteStarInactive, width: 20, height: 20, ), onPressed: () { final bool isFavorite = _contact.isFavorite; - ref.read(addressBookServiceProvider).editContact( + ref + .read(addressBookServiceProvider) + .editContact( _contact.copyWith(isFavorite: !isFavorite), ); }, @@ -165,11 +167,7 @@ class _ContactDetailsViewState extends ConsumerState { ), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -179,9 +177,10 @@ class _ContactDetailsViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.trash, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -190,43 +189,44 @@ class _ContactDetailsViewState extends ConsumerState { context: context, useSafeArea: true, barrierDismissible: true, - builder: (_) => StackDialog( - title: "Delete ${_contact.name}?", - message: "Contact will be deleted permanently!", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Cancel", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Delete", - style: STextStyles.button(context), + builder: + (_) => StackDialog( + title: "Delete ${_contact.name}?", + message: "Contact will be deleted permanently!", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Delete", + style: STextStyles.button(context), + ), + onPressed: () { + ref + .read(addressBookServiceProvider) + .removeContact(_contact.customId); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.success, + message: "${_contact.name} deleted", + context: context, + ); + }, + ), ), - onPressed: () { - ref - .read(addressBookServiceProvider) - .removeContact(_contact.customId); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.success, - message: "${_contact.name} deleted", - context: context, - ); - }, - ), - ), ); }, ), @@ -234,308 +234,292 @@ class _ContactDetailsViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 12, - ), - Row( - children: [ - Container( - height: 48, - width: 48, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, - ), - child: Center( - child: _contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - _contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 12), + Row( + children: [ + Container( + height: 48, + width: 48, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, + ), + child: Center( + child: + _contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + _contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), + ), ), - ), - const SizedBox( - width: 16, - ), - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - _contact.name, - textAlign: TextAlign.left, - style: STextStyles.pageTitleH2(context), + const SizedBox(width: 16), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + _contact.name, + textAlign: TextAlign.left, + style: STextStyles.pageTitleH2(context), + ), ), - ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.of(context).pushNamed( - EditContactNameEmojiView.routeName, - arguments: _contact.customId, - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context)! - .copyWith( - minimumSize: MaterialStateProperty.all( - const Size(46, 32), + const Spacer(), + TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + EditContactNameEmojiView.routeName, + arguments: _contact.customId, + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context)! + .copyWith( + minimumSize: MaterialStateProperty.all( + const Size(46, 32), + ), ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.buttonSmall(context), + ), + ], ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.buttonSmall(context), - ), - ], ), ), - ), - ], - ), - const SizedBox( - height: 24, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Addresses", - style: STextStyles.itemSubtitle(context), - ), - CustomTextButton( - text: "Add new", - onTap: () { - Navigator.of(context).pushNamed( - AddNewContactAddressView.routeName, - arguments: _contact.customId, - ); - }, - ), - ], - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( + ], + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ..._contact.addressesSorted.map( - (e) => Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - SvgPicture.file( - File( - ref.watch(coinIconProvider(e.coin)), + Text( + "Addresses", + style: STextStyles.itemSubtitle(context), + ), + CustomTextButton( + text: "Add new", + onTap: () { + Navigator.of(context).pushNamed( + AddNewContactAddressView.routeName, + arguments: _contact.customId, + ); + }, + ), + ], + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._contact.addressesSorted.map( + (e) => Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + SvgPicture.file( + File(ref.watch(coinIconProvider(e.coin))), + height: 24, ), - height: 24, - ), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "${e.label} (${e.coin.ticker})", - style: - STextStyles.itemSubtitle12(context), - ), - const SizedBox( - height: 2, - ), - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - e.address, - style: - STextStyles.itemSubtitle(context) - .copyWith( - fontSize: 8, + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "${e.label} (${e.coin.ticker})", + style: STextStyles.itemSubtitle12( + context, ), ), - ), - ], + const SizedBox(height: 2), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + e.address, + style: STextStyles.itemSubtitle( + context, + ).copyWith(fontSize: 8), + ), + ), + ], + ), ), - ), - GestureDetector( - onTap: () { - ref - .read(addressEntryDataProvider(0)) - .address = e.address; - ref - .read(addressEntryDataProvider(0)) - .addressLabel = e.label; - ref.read(addressEntryDataProvider(0)).coin = - e.coin; + GestureDetector( + onTap: () { + ref + .read(addressEntryDataProvider(0)) + .address = e.address; + ref + .read(addressEntryDataProvider(0)) + .addressLabel = e.label; + ref + .read(addressEntryDataProvider(0)) + .coin = e.coin; - Navigator.of(context).pushNamed( - EditContactAddressView.routeName, - arguments: Tuple2(_contact.customId, e), - ); - }, - child: RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - padding: const EdgeInsets.all(6), - child: SvgPicture.asset( - Assets.svg.pencil, - width: 14, - height: 14, - color: Theme.of(context) - .extension()! - .accentColorDark, + Navigator.of(context).pushNamed( + EditContactAddressView.routeName, + arguments: Tuple2(_contact.customId, e), + ); + }, + child: RoundedContainer( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + Assets.svg.pencil, + width: 14, + height: 14, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - const SizedBox( - width: 4, - ), - GestureDetector( - onTap: () { - clipboard.setData( - ClipboardData(text: e.address), - ); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - }, - child: RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - padding: const EdgeInsets.all(6), - child: SvgPicture.asset( - Assets.svg.copy, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(width: 4), + GestureDetector( + onTap: () { + clipboard.setData( + ClipboardData(text: e.address), + ); + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + }, + child: RoundedContainer( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + Assets.svg.copy, + width: 16, + height: 16, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 24, - ), - Text( - "Transaction history", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 12, - ), - FutureBuilder( - future: _filteredTransactionsByContact(), - builder: ( - _, - AsyncSnapshot>> snapshot, - ) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - _cachedTransactions = snapshot.data!; + const SizedBox(height: 24), + Text( + "Transaction history", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 12), + FutureBuilder( + future: _filteredTransactionsByContact(), + builder: ( + _, + AsyncSnapshot>> + snapshot, + ) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + _cachedTransactions = snapshot.data!; - if (_cachedTransactions.isNotEmpty) { - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ..._cachedTransactions.map( - (e) => TransactionCard( - key: Key( - "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + if (_cachedTransactions.isNotEmpty) { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._cachedTransactions.map( + (e) => TransactionCard( + key: Key( + "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + ), + transaction: e.item2, + walletId: e.item1, ), - transaction: e.item2, - walletId: e.item1, ), + ], + ), + ); + } else { + return RoundedWhiteContainer( + child: Center( + child: Text( + "No transactions found", + style: STextStyles.itemSubtitle(context), ), - ], - ), - ); - } else { - return RoundedWhiteContainer( - child: Center( - child: Text( - "No transactions found", - style: STextStyles.itemSubtitle(context), ), - ), - ); - } - } else { - // TODO: proper loading animation - if (_cachedTransactions.isEmpty) { - return const LoadingIndicator(); + ); + } } else { - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ..._cachedTransactions.map( - (e) => TransactionCard( - key: Key( - "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + // TODO: proper loading animation + if (_cachedTransactions.isEmpty) { + return const LoadingIndicator(); + } else { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._cachedTransactions.map( + (e) => TransactionCard( + key: Key( + "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + ), + transaction: e.item2, + walletId: e.item1, ), - transaction: e.item2, - walletId: e.item1, ), - ), - ], - ), - ); + ], + ), + ); + } } - } - }, - ), - const SizedBox( - height: 16, - ), - ], + }, + ), + const SizedBox(height: 16), + ], + ), ), ), ), diff --git a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart index 1d5ebd21c..774fac6be 100644 --- a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart @@ -62,9 +62,7 @@ class _EditContactAddressViewState Future save(ContactEntry contact) async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); + await Future.delayed(const Duration(milliseconds: 75)); } final List entries = contact.addresses.toList(); @@ -108,61 +106,67 @@ class _EditContactAddressViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final bool isDesktop = Util.isDesktop; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit address", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Edit address", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: 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: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -172,31 +176,28 @@ class _EditContactAddressViewState width: 48, decoration: BoxDecoration( borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + child: + contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (isDesktop) - Text( - contact.name, - style: STextStyles.pageTitleH2(context), - ), + Text(contact.name, style: STextStyles.pageTitleH2(context)), if (!isDesktop) Expanded( child: FittedBox( @@ -209,23 +210,18 @@ class _EditContactAddressViewState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), NewContactAddressEntryForm( id: 0, barcodeScanner: barcodeScanner, clipboard: clipboard, ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: () async { // delete address @@ -240,11 +236,13 @@ class _EditContactAddressViewState //Deleting an entry directly from _addresses gives error // "Cannot remove from a fixed-length list", so we remove the // entry from a copy - final tempAddresses = - List.from(_addresses); + final tempAddresses = List.from( + _addresses, + ); tempAddresses.remove(entry); - final ContactEntry editedContact = - contact.copyWith(addresses: tempAddresses); + final ContactEntry editedContact = contact.copyWith( + addresses: tempAddresses, + ); if (await ref .read(addressBookServiceProvider) .editContact(editedContact)) { @@ -254,16 +252,11 @@ class _EditContactAddressViewState // TODO show error notification } }, - child: Text( - "Delete address", - style: STextStyles.link(context), - ), + child: Text("Delete address", style: STextStyles.link(context)), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -283,9 +276,7 @@ class _EditContactAddressViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", diff --git a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart index a552aca29..412da64d6 100644 --- a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart +++ b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart @@ -33,10 +33,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditContactNameEmojiView extends ConsumerStatefulWidget { - const EditContactNameEmojiView({ - super.key, - required this.contactId, - }); + const EditContactNameEmojiView({super.key, required this.contactId}); static const String routeName = "/editContactNameEmoji"; @@ -63,8 +60,9 @@ class _EditContactNameEmojiViewState nameFocusNode = FocusNode(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - final contact = - ref.read(addressBookServiceProvider).getContactById(contactId); + final contact = ref + .read(addressBookServiceProvider) + .getContactById(contactId); nameController.text = contact.name; setState(() { @@ -84,8 +82,9 @@ class _EditContactNameEmojiViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final isDesktop = Util.isDesktop; @@ -93,53 +92,58 @@ class _EditContactNameEmojiViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit contact", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Edit contact", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: 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: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -208,23 +212,26 @@ class _EditContactNameEmojiViewState width: emojiSize, decoration: BoxDecoration( borderRadius: BorderRadius.circular(emojiSize / 2), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( - Assets.svg.user, - height: emojiSize / 2, - width: emojiSize / 2, - ) - : Text( - _selectedEmoji!.char, - style: isDesktop - ? STextStyles.desktopH3(context) - : STextStyles.pageTitleH1(context), - ), + child: + _selectedEmoji == null + ? SvgPicture.asset( + Assets.svg.user, + height: emojiSize / 2, + width: emojiSize / 2, + ) + : Text( + _selectedEmoji!.char, + style: + isDesktop + ? STextStyles.desktopH3(context) + : STextStyles.pageTitleH1(context), + ), ), ), Align( @@ -234,28 +241,32 @@ class _EditContactNameEmojiViewState width: 14, decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( - Assets.svg.plus, - color: Theme.of(context) - .extension()! - .textWhite, - width: 12, - height: 12, - ) - : SvgPicture.asset( - Assets.svg.thickX, - color: Theme.of(context) - .extension()! - .textWhite, - width: 8, - height: 8, - ), + child: + _selectedEmoji == null + ? SvgPicture.asset( + Assets.svg.plus, + color: + Theme.of( + context, + ).extension()!.textWhite, + width: 12, + height: 12, + ) + : SvgPicture.asset( + Assets.svg.thickX, + color: + Theme.of( + context, + ).extension()!.textWhite, + width: 8, + height: 8, + ), ), ), ), @@ -263,10 +274,7 @@ class _EditContactNameEmojiViewState ), ), ), - if (isDesktop) - const SizedBox( - width: 8, - ), + if (isDesktop) const SizedBox(width: 8), if (isDesktop) Expanded( child: ClipRRect( @@ -285,35 +293,33 @@ class _EditContactNameEmojiViewState nameFocusNode, context, ).copyWith( - suffixIcon: nameController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - nameController.text = ""; - }); - }, - ), - ], + suffixIcon: + nameController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + nameController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), ], ), - if (!isDesktop) - const SizedBox( - height: 8, - ), + if (!isDesktop) const SizedBox(height: 8), if (!isDesktop) ClipRRect( borderRadius: BorderRadius.circular( @@ -331,32 +337,31 @@ class _EditContactNameEmojiViewState nameFocusNode, context, ).copyWith( - suffixIcon: nameController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - nameController.text = ""; - }); - }, - ), - ], + suffixIcon: + nameController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + nameController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -376,9 +381,7 @@ class _EditContactNameEmojiViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -398,9 +401,9 @@ class _EditContactNameEmojiViewState _selectedEmoji == null ? null : _selectedEmoji!.char, ); unawaited( - ref.read(addressBookServiceProvider).editContact( - editedContact, - ), + ref + .read(addressBookServiceProvider) + .editContact(editedContact), ); if (mounted) { Navigator.of(context).pop(); diff --git a/lib/pages/buy_view/buy_order_details.dart b/lib/pages/buy_view/buy_order_details.dart index 7021309a2..30b6060d8 100644 --- a/lib/pages/buy_view/buy_order_details.dart +++ b/lib/pages/buy_view/buy_order_details.dart @@ -29,10 +29,7 @@ import '../../widgets/desktop/primary_button.dart'; import '../../widgets/rounded_white_container.dart'; class BuyOrderDetailsView extends ConsumerStatefulWidget { - const BuyOrderDetailsView({ - super.key, - required this.order, - }); + const BuyOrderDetailsView({super.key, required this.order}); final SimplexOrder order; @@ -74,29 +71,31 @@ Provider: Simplex style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -104,21 +103,13 @@ Provider: Simplex child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Simplex order", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 16, - ), + Text("Simplex order", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 16), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Purchase ID", - style: STextStyles.label(context), - ), + Text("Purchase ID", style: STextStyles.label(context)), Text( widget.order.paymentId, style: STextStyles.label(context).copyWith( @@ -128,17 +119,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "User ID", - style: STextStyles.label(context), - ), + Text("User ID", style: STextStyles.label(context)), Text( widget.order.userId, style: STextStyles.label(context).copyWith( @@ -148,17 +134,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quote ID", - style: STextStyles.label(context), - ), + Text("Quote ID", style: STextStyles.label(context)), Text( widget.order.quote.id, style: STextStyles.label(context).copyWith( @@ -168,17 +149,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quoted cost", - style: STextStyles.label(context), - ), + Text("Quoted cost", style: STextStyles.label(context)), Text( "${widget.order.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.order.quote.fiat.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -188,9 +164,7 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), // RoundedWhiteContainer( // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -215,10 +189,7 @@ Provider: Simplex child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quoted amount", - style: STextStyles.label(context), - ), + Text("Quoted amount", style: STextStyles.label(context)), Text( "${widget.order.quote.youReceiveCryptoAmount} ${widget.order.quote.crypto.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -228,9 +199,7 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -248,32 +217,23 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Provider", - style: STextStyles.label(context), - ), + Text("Provider", style: STextStyles.label(context)), SizedBox( width: 64, height: 32, child: SvgPicture.asset( - Assets.buy.simplexLogo( - ref.watch(themeProvider).brightness, - ), + Assets.buy.simplexLogo(ref.watch(themeProvider).brightness), ), ), ], ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -307,18 +267,15 @@ Provider: Simplex Assets.svg.copy, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), + const SizedBox(width: 10), Text( "Copy to clipboard", - style: STextStyles.desktopButtonSecondaryEnabled( - context, - ), + style: STextStyles.desktopButtonSecondaryEnabled(context), ), ], ), diff --git a/lib/pages/buy_view/buy_quote_preview.dart b/lib/pages/buy_view/buy_quote_preview.dart index 7d736e3a6..8137bce71 100644 --- a/lib/pages/buy_view/buy_quote_preview.dart +++ b/lib/pages/buy_view/buy_quote_preview.dart @@ -14,8 +14,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:intl/intl.dart'; + import '../../models/buy/response_objects/quote.dart'; -import 'sub_widgets/buy_warning_popup.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; import '../../utilities/assets.dart'; @@ -26,12 +26,10 @@ import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/desktop/primary_button.dart'; import '../../widgets/rounded_white_container.dart'; +import 'sub_widgets/buy_warning_popup.dart'; class BuyQuotePreviewView extends ConsumerStatefulWidget { - const BuyQuotePreviewView({ - super.key, - required this.quote, - }); + const BuyQuotePreviewView({super.key, required this.quote}); final SimplexQuote quote; @@ -48,9 +46,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { Future _buyWarning() async { await showDialog( context: context, - builder: (context) => BuyWarningPopup( - quote: widget.quote, - ), + builder: (context) => BuyWarningPopup(quote: widget.quote), ); } @@ -76,29 +72,31 @@ class _BuyQuotePreviewViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -110,17 +108,12 @@ class _BuyQuotePreviewViewState extends ConsumerState { "Buy ${widget.quote.crypto.ticker.toUpperCase()}", style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "You pay", - style: STextStyles.label(context), - ), + Text("You pay", style: STextStyles.label(context)), Text( "${format.simpleCurrencySymbol(widget.quote.fiat.ticker.toUpperCase())}${widget.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.quote.fiat.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -130,9 +123,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), // RoundedWhiteContainer( // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -157,10 +148,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "You receive", - style: STextStyles.label(context), - ), + Text("You receive", style: STextStyles.label(context)), Text( "${widget.quote.youReceiveCryptoAmount} ${widget.quote.crypto.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -170,9 +158,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -190,17 +176,12 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quote ID", - style: STextStyles.label(context), - ), + Text("Quote ID", style: STextStyles.label(context)), Text( widget.quote.id, style: STextStyles.label(context).copyWith( @@ -210,37 +191,25 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Provider", - style: STextStyles.label(context), - ), + Text("Provider", style: STextStyles.label(context)), SizedBox( width: 64, height: 32, child: SvgPicture.asset( - Assets.buy.simplexLogo( - ref.watch(themeProvider).brightness, - ), + Assets.buy.simplexLogo(ref.watch(themeProvider).brightness), ), ), ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), const Spacer(), - PrimaryButton( - label: "Buy", - onPressed: _buyWarning, - ), + PrimaryButton(label: "Buy", onPressed: _buyWarning), ], ), ); diff --git a/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart b/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart index 432a3435a..089b492af 100644 --- a/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart +++ b/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart @@ -32,10 +32,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class CryptoSelectionView extends ConsumerStatefulWidget { - const CryptoSelectionView({ - super.key, - required this.coins, - }); + const CryptoSelectionView({super.key, required this.coins}); final List coins; @@ -122,11 +119,11 @@ class _CryptoSelectionViewState extends ConsumerState { style: STextStyles.pageTitleH2(context), ), ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, ), - child: child, ), ), ); @@ -135,10 +132,7 @@ class _CryptoSelectionViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, children: [ - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -168,39 +162,33 @@ class _CryptoSelectionViewState extends ConsumerState { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - }); - filter(""); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + }); + filter(""); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 10, - ), - Text( - "All coins", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 10), + Text("All coins", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), Flexible( child: RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -226,9 +214,7 @@ class _CryptoSelectionViewState extends ConsumerState { ticker: _coins[index].ticker, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -237,16 +223,16 @@ class _CryptoSelectionViewState extends ConsumerState { _coins[index].name, style: STextStyles.largeMedium14(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( _coins[index].ticker.toUpperCase(), - style: STextStyles.smallMed12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ), ], @@ -297,9 +283,7 @@ class CoinIconForTicker extends ConsumerWidget { try { final coin = AppConfig.getCryptoCurrencyForTicker(ticker)!; return SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: size, height: size, ); diff --git a/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart b/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart index 4fee72444..05bb3a6df 100644 --- a/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart +++ b/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart @@ -28,10 +28,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class FiatSelectionView extends StatefulWidget { - const FiatSelectionView({ - super.key, - required this.fiats, - }); + const FiatSelectionView({super.key, required this.fiats}); final List fiats; @@ -122,11 +119,11 @@ class _FiatSelectionViewState extends State { style: STextStyles.pageTitleH2(context), ), ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, ), - child: child, ), ), ); @@ -135,10 +132,7 @@ class _FiatSelectionViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, children: [ - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -168,39 +162,33 @@ class _FiatSelectionViewState extends State { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - }); - filter(""); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + }); + filter(""); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 10, - ), - Text( - "All currencies", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 10), + Text("All currencies", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), Flexible( child: SingleChildScrollView( child: RoundedWhiteContainer( @@ -212,95 +200,92 @@ class _FiatSelectionViewState extends State { }, defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ - ..._fiats.map( - (e) { - return TableRow( - children: [ - TableCell( - verticalAlignment: - TableCellVerticalAlignment.fill, - child: GestureDetector( - onTap: () => Navigator.of(context).pop(e), - child: Container( - color: Colors.transparent, - padding: const EdgeInsets.only(left: 12), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Container( - padding: const EdgeInsets.all(7.5), - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .currencyListItemBG, - borderRadius: - BorderRadius.circular(4), + ..._fiats.map((e) { + return TableRow( + children: [ + TableCell( + verticalAlignment: TableCellVerticalAlignment.fill, + child: GestureDetector( + onTap: () => Navigator.of(context).pop(e), + child: Container( + color: Colors.transparent, + padding: const EdgeInsets.only(left: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Container( + padding: const EdgeInsets.all(7.5), + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .currencyListItemBG, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + format.simpleCurrencySymbol( + e.ticker.toUpperCase(), ), - child: Text( - format.simpleCurrencySymbol( - e.ticker.toUpperCase(), - ), - style: STextStyles.subtitle(context) - .apply( - fontSizeFactor: (1 / - format - .simpleCurrencySymbol( - e.ticker.toUpperCase(), - ) - .length * // Couldn't get pow() working here - format - .simpleCurrencySymbol( - e.ticker.toUpperCase(), - ) - .length), - ), - textAlign: TextAlign.center, + style: STextStyles.subtitle( + context, + ).apply( + fontSizeFactor: + (1 / + format + .simpleCurrencySymbol( + e.ticker.toUpperCase(), + ) + .length * // Couldn't get pow() working here + format + .simpleCurrencySymbol( + e.ticker.toUpperCase(), + ) + .length), ), + textAlign: TextAlign.center, ), - ], - ), + ), + ], ), ), ), - GestureDetector( - onTap: () => Navigator.of(context).pop(e), - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - e.name, - style: - STextStyles.largeMedium14(context), - ), - const SizedBox( - height: 2, - ), - Text( - e.ticker.toUpperCase(), - style: STextStyles.smallMed12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), + ), + GestureDetector( + onTap: () => Navigator.of(context).pop(e), + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + e.name, + style: STextStyles.largeMedium14(context), + ), + const SizedBox(height: 2), + Text( + e.ticker.toUpperCase(), + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), - ], - ), + ), + ], ), ), ), - ], - ); - }, - ), + ), + ], + ); + }), ], ), diff --git a/lib/pages/cashfusion/cashfusion_view.dart b/lib/pages/cashfusion/cashfusion_view.dart index 4579dbc52..53da25374 100644 --- a/lib/pages/cashfusion/cashfusion_view.dart +++ b/lib/pages/cashfusion/cashfusion_view.dart @@ -37,10 +37,7 @@ import 'fusion_progress_view.dart'; import 'fusion_rounds_selection_sheet.dart'; class CashFusionView extends ConsumerStatefulWidget { - const CashFusionView({ - super.key, - required this.walletId, - }); + const CashFusionView({super.key, required this.walletId}); static const routeName = "/cashFusionView"; @@ -74,15 +71,16 @@ class _CashFusionViewState extends ConsumerState { ); } catch (e) { if (!e.toString().contains( - "FusionProgressUIState was already set for ${widget.walletId}", - )) { + "FusionProgressUIState was already set for ${widget.walletId}", + )) { rethrow; } } - final int rounds = _option == FusionOption.continuous - ? 0 - : int.parse(fusionRoundController.text); + final int rounds = + _option == FusionOption.continuous + ? 0 + : int.parse(fusionRoundController.text); final newInfo = FusionInfo( host: serverController.text, @@ -94,16 +92,11 @@ class _CashFusionViewState extends ConsumerState { // update user prefs (persistent) ref.read(prefsChangeNotifierProvider).setFusionServerInfo(coin, newInfo); - unawaited( - fusionWallet.fuse( - fusionInfo: newInfo, - ), - ); + unawaited(fusionWallet.fuse(fusionInfo: newInfo)); - await Navigator.of(context).pushNamed( - FusionProgressView.routeName, - arguments: widget.walletId, - ); + await Navigator.of( + context, + ).pushNamed(FusionProgressView.routeName, arguments: widget.walletId); } @override @@ -118,8 +111,9 @@ class _CashFusionViewState extends ConsumerState { coin = ref.read(pWalletCoin(widget.walletId)); - final info = - ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin); + final info = ref + .read(prefsChangeNotifierProvider) + .getFusionServerInfo(coin); serverController.text = info.host; portController.text = info.port.toString(); @@ -156,10 +150,7 @@ class _CashFusionViewState extends ConsumerState { appBar: AppBar( automaticallyImplyLeading: false, leading: const AppBarBackButton(), - title: Text( - "Fusion", - style: STextStyles.navBarTitle(context), - ), + title: Text("Fusion", style: STextStyles.navBarTitle(context)), titleSpacing: 0, actions: [ AspectRatio( @@ -170,9 +161,10 @@ class _CashFusionViewState extends ConsumerState { Assets.svg.circleQuestion, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { //' TODO show about? @@ -181,225 +173,89 @@ class _CashFusionViewState extends ConsumerState { ), ], ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Text( - "Fusion helps anonymize your coins by mixing them.", - style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Text( + "Fusion helps anonymize your coins by mixing them.", + style: STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), ), ), - ), - const SizedBox( - height: 16, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Server settings", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Server settings", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + ), + CustomTextButton( + text: "Default", + onTap: () { + final def = + kFusionServerInfoDefaults[coin]!; + serverController.text = def.host; + portController.text = def.port.toString(); + fusionRoundController.text = + def.rounds.toString(); + _option = FusionOption.continuous; + setState(() { + _enableSSLCheckbox = def.ssl; + }); + }, ), + ], + ), + const SizedBox(height: 12), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - CustomTextButton( - text: "Default", - onTap: () { - final def = kFusionServerInfoDefaults[coin]!; - serverController.text = def.host; - portController.text = def.port.toString(); - fusionRoundController.text = - def.rounds.toString(); - _option = FusionOption.continuous; + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: serverController, + focusNode: serverFocusNode, + onChanged: (value) { setState(() { - _enableSSLCheckbox = def.ssl; + _enableStartButton = + value.isNotEmpty && + portController.text.isNotEmpty && + fusionRoundController.text.isNotEmpty; }); }, - ), - ], - ), - const SizedBox( - height: 12, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: false, - enableSuggestions: false, - controller: serverController, - focusNode: serverFocusNode, - onChanged: (value) { - setState(() { - _enableStartButton = value.isNotEmpty && - portController.text.isNotEmpty && - fusionRoundController.text.isNotEmpty; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Server", - serverFocusNode, - context, - desktopMed: true, - ), - ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: false, - enableSuggestions: false, - controller: portController, - focusNode: portFocusNode, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - keyboardType: TextInputType.number, - onChanged: (value) { - setState(() { - _enableStartButton = value.isNotEmpty && - serverController.text.isNotEmpty && - fusionRoundController.text.isNotEmpty; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Port", - portFocusNode, - context, - ), - ), - ), - const SizedBox( - height: 10, - ), - GestureDetector( - onTap: () { - setState(() { - _enableSSLCheckbox = !_enableSSLCheckbox; - }); - }, - child: Container( - color: Colors.transparent, - child: Row( - children: [ - SizedBox( - width: 20, - height: 20, - child: Checkbox( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - value: _enableSSLCheckbox, - onChanged: (newValue) { - setState( - () { - _enableSSLCheckbox = - !_enableSSLCheckbox; - }, - ); - }, - ), - ), - const SizedBox( - width: 12, - ), - Text( - "Use SSL", - style: STextStyles.itemSubtitle12(context), - ), - ], - ), - ), - ), - const SizedBox( - height: 16, - ), - Text( - "Rounds of fusion", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - ), - const SizedBox( - height: 12, - ), - RoundedContainer( - onPressed: () async { - final option = - await showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Server", + serverFocusNode, + context, + desktopMed: true, ), - builder: (_) { - return FusionRoundCountSelectSheet( - currentOption: _option, - ); - }, - ); - if (option != null) { - setState(() { - _option = option; - }); - } - }, - color: Theme.of(context) - .extension()! - .textFieldActiveBG, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - _option.name.capitalize(), - style: STextStyles.w500_12(context), - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ], ), ), - ), - if (_option == FusionOption.custom) - const SizedBox( - height: 10, - ), - if (_option == FusionOption.custom) + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -407,45 +263,176 @@ class _CashFusionViewState extends ConsumerState { child: TextField( autocorrect: false, enableSuggestions: false, - controller: fusionRoundController, - focusNode: fusionRoundFocusNode, + controller: portController, + focusNode: portFocusNode, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], keyboardType: TextInputType.number, onChanged: (value) { setState(() { - _enableStartButton = value.isNotEmpty && + _enableStartButton = + value.isNotEmpty && serverController.text.isNotEmpty && - portController.text.isNotEmpty; + fusionRoundController.text.isNotEmpty; }); }, style: STextStyles.field(context), decoration: standardInputDecoration( - "Number of fusions", - fusionRoundFocusNode, + "Port", + portFocusNode, context, - ).copyWith( - labelText: "Enter number of fusions..", ), ), ), - const SizedBox( - height: 16, - ), - const Spacer(), - PrimaryButton( - label: "Start", - enabled: _enableStartButton, - onPressed: _startFusion, - ), - ], + const SizedBox(height: 10), + GestureDetector( + onTap: () { + setState(() { + _enableSSLCheckbox = !_enableSSLCheckbox; + }); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: Checkbox( + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _enableSSLCheckbox, + onChanged: (newValue) { + setState(() { + _enableSSLCheckbox = + !_enableSSLCheckbox; + }); + }, + ), + ), + const SizedBox(width: 12), + Text( + "Use SSL", + style: STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + Text( + "Rounds of fusion", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + ), + const SizedBox(height: 12), + RoundedContainer( + onPressed: () async { + final option = + await showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) { + return FusionRoundCountSelectSheet( + currentOption: _option, + ); + }, + ); + if (option != null) { + setState(() { + _option = option; + }); + } + }, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + _option.name.capitalize(), + style: STextStyles.w500_12(context), + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ], + ), + ), + ), + if (_option == FusionOption.custom) + const SizedBox(height: 10), + if (_option == FusionOption.custom) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: fusionRoundController, + focusNode: fusionRoundFocusNode, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + keyboardType: TextInputType.number, + onChanged: (value) { + setState(() { + _enableStartButton = + value.isNotEmpty && + serverController.text.isNotEmpty && + portController.text.isNotEmpty; + }); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Number of fusions", + fusionRoundFocusNode, + context, + ).copyWith( + labelText: "Enter number of fusions..", + ), + ), + ), + const SizedBox(height: 16), + const Spacer(), + PrimaryButton( + label: "Start", + enabled: _enableStartButton, + onPressed: _startFusion, + ), + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/cashfusion/fusion_progress_view.dart b/lib/pages/cashfusion/fusion_progress_view.dart index 022fa0861..021a8ef69 100644 --- a/lib/pages/cashfusion/fusion_progress_view.dart +++ b/lib/pages/cashfusion/fusion_progress_view.dart @@ -33,10 +33,7 @@ import '../../widgets/rounded_container.dart'; import '../../widgets/stack_dialog.dart'; class FusionProgressView extends ConsumerStatefulWidget { - const FusionProgressView({ - super.key, - required this.walletId, - }); + const FusionProgressView({super.key, required this.walletId}); static const routeName = "/cashFusionProgressView"; @@ -52,23 +49,24 @@ class _FusionProgressViewState extends ConsumerState { final shouldCancel = await showDialog( context: context, barrierDismissible: false, - builder: (_) => StackDialog( - title: "Cancel fusion?", - leftButton: SecondaryButton( - label: "No", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: PrimaryButton( - label: "Yes", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), + builder: + (_) => StackDialog( + title: "Cancel fusion?", + leftButton: SecondaryButton( + label: "No", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: PrimaryButton( + label: "Yes", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); if (shouldCancel == true && mounted) { @@ -113,9 +111,10 @@ class _FusionProgressViewState extends ConsumerState { final bool _failed = ref.watch(fusionProgressUIStateProvider(widget.walletId)).failed; - final int _fusionRoundsCompleted = ref - .watch(fusionProgressUIStateProvider(widget.walletId)) - .fusionRoundsCompleted; + final int _fusionRoundsCompleted = + ref + .watch(fusionProgressUIStateProvider(widget.walletId)) + .fusionRoundsCompleted; WakelockPlus.enable(); @@ -124,28 +123,28 @@ class _FusionProgressViewState extends ConsumerState { return await _requestAndProcessCancel(); }, child: Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: AppBarBackButton( - onPressed: () async { - if (await _requestAndProcessCancel()) { - if (mounted) { - Navigator.of(context).pop(); - } + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: AppBarBackButton( + onPressed: () async { + if (await _requestAndProcessCancel()) { + if (mounted) { + Navigator.of(context).pop(); } - }, - ), - title: Text( - "Fusion progress", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, + } + }, ), - body: LayoutBuilder( + title: Text( + "Fusion progress", + style: STextStyles.navBarTitle(context), + ), + titleSpacing: 0, + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( @@ -160,64 +159,57 @@ class _FusionProgressViewState extends ConsumerState { children: [ if (_fusionRoundsCompleted == 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackError, + color: + Theme.of(context) + .extension()! + .snackBarBackError, child: Text( "Do not close this window. If you exit, " "the process will be canceled.", - style: - STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextError, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .snackBarTextError, ), textAlign: TextAlign.center, ), ), if (_fusionRoundsCompleted > 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackInfo, + color: + Theme.of(context) + .extension()! + .snackBarBackInfo, child: Text( "Fusion rounds completed: $_fusionRoundsCompleted", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextInfo, + color: + Theme.of(context) + .extension()! + .snackBarTextInfo, ), textAlign: TextAlign.center, ), ), - const SizedBox( - height: 20, - ), - FusionProgress( - walletId: widget.walletId, - ), + const SizedBox(height: 20), + FusionProgress(walletId: widget.walletId), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (_succeeded) PrimaryButton( label: "Fuse again", onPressed: _fuseAgain, ), - if (_succeeded) - const SizedBox( - height: 16, - ), + if (_succeeded) const SizedBox(height: 16), if (_failed) PrimaryButton( label: "Try again", onPressed: _fuseAgain, ), - if (_failed) - const SizedBox( - height: 16, - ), + if (_failed) const SizedBox(height: 16), SecondaryButton( label: "Cancel", onPressed: () async { @@ -247,8 +239,9 @@ class _FusionProgressViewState extends ConsumerState { final fusionWallet = ref.read(pWallets).getWallet(widget.walletId) as CashFusionInterface; - final fusionInfo = - ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin); + final fusionInfo = ref + .read(prefsChangeNotifierProvider) + .getFusionServerInfo(coin); try { fusionWallet.uiState = ref.read( @@ -256,8 +249,8 @@ class _FusionProgressViewState extends ConsumerState { ); } catch (e) { if (!e.toString().contains( - "FusionProgressUIState was already set for ${widget.walletId}", - )) { + "FusionProgressUIState was already set for ${widget.walletId}", + )) { rethrow; } } diff --git a/lib/pages/churning/churning_progress_view.dart b/lib/pages/churning/churning_progress_view.dart index 55319738a..a214640c6 100644 --- a/lib/pages/churning/churning_progress_view.dart +++ b/lib/pages/churning/churning_progress_view.dart @@ -19,10 +19,7 @@ import '../../widgets/stack_dialog.dart'; import 'churn_error_dialog.dart'; class ChurningProgressView extends ConsumerStatefulWidget { - const ChurningProgressView({ - super.key, - required this.walletId, - }); + const ChurningProgressView({super.key, required this.walletId}); static const routeName = "/churningProgressView"; @@ -37,23 +34,24 @@ class _ChurningProgressViewState extends ConsumerState { final shouldCancel = await showDialog( context: context, barrierDismissible: false, - builder: (_) => StackDialog( - title: "Cancel churning?", - leftButton: SecondaryButton( - label: "No", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: PrimaryButton( - label: "Yes", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), + builder: + (_) => StackDialog( + title: "Cancel churning?", + leftButton: SecondaryButton( + label: "No", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: PrimaryButton( + label: "Yes", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); if (shouldCancel == true && mounted) { @@ -102,10 +100,11 @@ class _ChurningProgressViewState extends ConsumerState { if (context.mounted) { showDialog( context: context, - builder: (context) => ChurnErrorDialog( - error: n.toString(), - walletId: widget.walletId, - ), + builder: + (context) => ChurnErrorDialog( + error: n.toString(), + walletId: widget.walletId, + ), ); } } @@ -117,28 +116,28 @@ class _ChurningProgressViewState extends ConsumerState { return await _requestAndProcessCancel(); }, child: Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: AppBarBackButton( - onPressed: () async { - if (await _requestAndProcessCancel()) { - if (context.mounted) { - Navigator.of(context).pop(); - } + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: AppBarBackButton( + onPressed: () async { + if (await _requestAndProcessCancel()) { + if (context.mounted) { + Navigator.of(context).pop(); } - }, - ), - title: Text( - "Churning progress", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, + } + }, + ), + title: Text( + "Churning progress", + style: STextStyles.navBarTitle(context), ), - body: LayoutBuilder( + titleSpacing: 0, + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( @@ -153,91 +152,85 @@ class _ChurningProgressViewState extends ConsumerState { children: [ if (_roundsCompleted == 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackError, + color: + Theme.of(context) + .extension()! + .snackBarBackError, child: Text( "Do not close this window. If you exit, " "the process will be canceled.", - style: - STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextError, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .snackBarTextError, ), textAlign: TextAlign.center, ), ), if (_roundsCompleted > 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackInfo, + color: + Theme.of(context) + .extension()! + .snackBarBackInfo, child: Text( "Churning rounds completed: $_roundsCompleted", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextInfo, + color: + Theme.of(context) + .extension()! + .snackBarTextInfo, ), textAlign: TextAlign.center, ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), const MoneroChanDance(), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ProgressItem( iconAsset: Assets.svg.alertCircle, - label: "Waiting for balance to unlock ${ref.watch( - pChurningService(widget.walletId) - .select((s) => s.confirmsInfo), - ) ?? ""}", + label: + "Waiting for balance to unlock ${ref.watch(pChurningService(widget.walletId).select((s) => s.confirmsInfo)) ?? ""}", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.waitingForUnlockedBalance), + pChurningService( + widget.walletId, + ).select((s) => s.waitingForUnlockedBalance), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ProgressItem( iconAsset: Assets.svg.churn, label: "Creating churn transaction", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.makingChurnTransaction), + pChurningService( + widget.walletId, + ).select((s) => s.makingChurnTransaction), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ProgressItem( iconAsset: Assets.svg.checkCircle, label: "Complete", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.completedStatus), + pChurningService( + widget.walletId, + ).select((s) => s.completedStatus), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (_succeeded) PrimaryButton( label: "Churn again", - onPressed: ref - .read(pChurningService(widget.walletId)) - .churn, - ), - if (_succeeded) - const SizedBox( - height: 16, + onPressed: + ref + .read(pChurningService(widget.walletId)) + .churn, ), + if (_succeeded) const SizedBox(height: 16), SecondaryButton( label: "Cancel", onPressed: () async { diff --git a/lib/pages/churning/churning_view.dart b/lib/pages/churning/churning_view.dart index d59042e5e..6b23ed8f7 100644 --- a/lib/pages/churning/churning_view.dart +++ b/lib/pages/churning/churning_view.dart @@ -23,10 +23,7 @@ import 'churning_progress_view.dart'; import 'churning_rounds_selection_sheet.dart'; class ChurningView extends ConsumerStatefulWidget { - const ChurningView({ - super.key, - required this.walletId, - }); + const ChurningView({super.key, required this.walletId}); static const routeName = "/churnView"; @@ -47,16 +44,16 @@ class _ChurnViewState extends ConsumerState { Future _startChurn() async { final churningService = ref.read(pChurningService(widget.walletId)); - final int rounds = _option == ChurnOption.continuous - ? 0 - : int.parse(churningRoundController.text); + final int rounds = + _option == ChurnOption.continuous + ? 0 + : int.parse(churningRoundController.text); churningService.rounds = rounds; - await Navigator.of(context).pushNamed( - ChurningProgressView.routeName, - arguments: widget.walletId, - ); + await Navigator.of( + context, + ).pushNamed(ChurningProgressView.routeName, arguments: widget.walletId); } @override @@ -86,61 +83,58 @@ class _ChurnViewState extends ConsumerState { @override Widget build(BuildContext context) { return Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: const AppBarBackButton(), - title: Text( - "Churn", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: () async { - await showDialog( - context: context, - builder: (context) => const StackOkDialog( - title: "What is churning?", - message: "Churning in a Monero wallet involves" - " sending Monero to oneself in multiple" - " transactions, which can enhance privacy" - " by making it harder for observers to " - "link your transactions. This process" - " re-mixes the funds within the network," - " helping obscure transaction history. " - "Churning is optional and mainly beneficial" - " in scenarios where maximum privacy is" - " desired or if you received the Monero from" - " a source from which you'd like to disassociate.", - ), - ); - }, + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: const AppBarBackButton(), + title: Text("Churn", style: STextStyles.navBarTitle(context)), + titleSpacing: 0, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () async { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "What is churning?", + message: + "Churning in a Monero wallet involves" + " sending Monero to oneself in multiple" + " transactions, which can enhance privacy" + " by making it harder for observers to " + "link your transactions. This process" + " re-mixes the funds within the network," + " helping obscure transaction history. " + "Churning is optional and mainly beneficial" + " in scenarios where maximum privacy is" + " desired or if you received the Monero from" + " a source from which you'd like to disassociate.", + ), + ); + }, ), - ], - ), - body: LayoutBuilder( + ), + ], + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), + constraints: BoxConstraints(minHeight: constraints.maxHeight), child: IntrinsicHeight( child: Padding( padding: const EdgeInsets.all(16), @@ -151,55 +145,52 @@ class _ChurnViewState extends ConsumerState { child: Text( "Churning helps anonymize your coins by mixing them.", style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), - const SizedBox( - height: 16, - ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), + const SizedBox(height: 16), Text( "Configuration", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedContainer( onPressed: () async { final option = await showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) { - return ChurnRoundCountSelectSheet( - currentOption: _option, + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) { + return ChurnRoundCountSelectSheet( + currentOption: _option, + ); + }, ); - }, - ); if (option != null) { setState(() { _option = option; }); } }, - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( @@ -213,18 +204,17 @@ class _ChurnViewState extends ConsumerState { SvgPicture.asset( Assets.svg.chevronDown, width: 12, - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ], ), ), ), if (_option == ChurnOption.custom) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (_option == ChurnOption.custom) ClipRRect( borderRadius: BorderRadius.circular( @@ -254,23 +244,20 @@ class _ChurnViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), CheckboxTextButton( label: "Pause on errors", - initialValue: !ref - .read(pChurningService(widget.walletId)) - .ignoreErrors, + initialValue: + !ref + .read(pChurningService(widget.walletId)) + .ignoreErrors, onChanged: (value) { ref .read(pChurningService(widget.walletId)) .ignoreErrors = !value; }, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), PrimaryButton( label: "Start", diff --git a/lib/pages/exchange_view/choose_from_stack_view.dart b/lib/pages/exchange_view/choose_from_stack_view.dart index 73d79f647..d4cc11dac 100644 --- a/lib/pages/exchange_view/choose_from_stack_view.dart +++ b/lib/pages/exchange_view/choose_from_stack_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/constants.dart'; @@ -23,10 +24,7 @@ import '../../widgets/wallet_info_row/sub_widgets/wallet_info_row_balance.dart'; import '../../widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart'; class ChooseFromStackView extends ConsumerStatefulWidget { - const ChooseFromStackView({ - super.key, - required this.coin, - }); + const ChooseFromStackView({super.key, required this.coin}); final CryptoCurrency coin; @@ -48,12 +46,13 @@ class _ChooseFromStackViewState extends ConsumerState { @override Widget build(BuildContext context) { - final walletIds = ref - .watch(pWallets) - .wallets - .where((e) => e.info.coin == coin) - .map((e) => e.walletId) - .toList(); + final walletIds = + ref + .watch(pWallets) + .wallets + .where((e) => e.info.coin == coin) + .map((e) => e.walletId) + .toList(); return Background( child: Scaffold( @@ -65,80 +64,84 @@ class _ChooseFromStackViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: walletIds.isEmpty - ? Column( - children: [ - RoundedWhiteContainer( - child: Center( - child: Text( - "No ${coin.ticker.toUpperCase()} wallets", - style: STextStyles.itemSubtitle(context), - ), - ), - ), - ], - ) - : ListView.builder( - itemCount: walletIds.length, - itemBuilder: (context, index) { - final walletId = walletIds[index]; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + walletIds.isEmpty + ? Column( + children: [ + RoundedWhiteContainer( + child: Center( + child: Text( + "No ${coin.ticker.toUpperCase()} wallets", + style: STextStyles.itemSubtitle(context), + ), ), ), - padding: const EdgeInsets.all(0), - // color: Theme.of(context).extension()!.popupBG, - elevation: 0, - onPressed: () async { - if (mounted) { - Navigator.of(context).pop(walletId); - } - }, - child: RoundedWhiteContainer( - // color: Colors.transparent, - child: Row( - children: [ - WalletInfoCoinIcon(coin: coin), - const SizedBox( - width: 12, + ], + ) + : ListView.builder( + itemCount: walletIds.length, + itemBuilder: (context, index) { + final walletId = walletIds[index]; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context), - overflow: TextOverflow.ellipsis, + ), + padding: const EdgeInsets.all(0), + // color: Theme.of(context).extension()!.popupBG, + elevation: 0, + onPressed: () async { + if (mounted) { + Navigator.of(context).pop(walletId); + } + }, + child: RoundedWhiteContainer( + // color: Colors.transparent, + child: Row( + children: [ + WalletInfoCoinIcon(coin: coin), + const SizedBox(width: 12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( + context, + ), + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + WalletInfoRowBalance( + walletId: walletIds[index], + ), + ], ), - const SizedBox( - height: 2, - ), - WalletInfoRowBalance( - walletId: walletIds[index], - ), - ], - ), + ), + ], ), - ], + ), ), - ), - ), - ); - }, - ), + ); + }, + ), + ), ), ), ); diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index d28bc8277..69e77f13c 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -295,25 +295,31 @@ class _ConfirmChangeNowSendViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/edit_trade_note_view.dart b/lib/pages/exchange_view/edit_trade_note_view.dart index db918be65..1406d87e3 100644 --- a/lib/pages/exchange_view/edit_trade_note_view.dart +++ b/lib/pages/exchange_view/edit_trade_note_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../providers/exchange/trade_note_service_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/constants.dart'; @@ -79,86 +80,94 @@ class _EditNoteViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _noteController, - style: STextStyles.field(context), - focusNode: noteFieldFocusNode, - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Note", - noteFieldFocusNode, - context, - ).copyWith( - suffixIcon: _noteController.text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _noteController.text = ""; - }); - }, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: _noteController, + style: STextStyles.field(context), + focusNode: noteFieldFocusNode, + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Note", + noteFieldFocusNode, + context, + ).copyWith( + suffixIcon: + _noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _noteController.text = + ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const Spacer(), - TextButton( - onPressed: () async { - await ref.read(tradeNoteServiceProvider).set( - tradeId: widget.tradeId, - note: _noteController.text, - ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), + const Spacer(), + TextButton( + onPressed: () async { + await ref + .read(tradeNoteServiceProvider) + .set( + tradeId: widget.tradeId, + note: _noteController.text, + ); + if (mounted) { + Navigator.of(context).pop(); + } + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Save", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 5801cf869..5c51ac134 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -262,186 +262,191 @@ class _ExchangeCurrencySelectionViewState ), ); }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, - children: [ - if (!isDesktop) const SizedBox(height: 16), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (value) => setState(() => _searchString = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + child: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, + children: [ + if (!isDesktop) const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (value) => setState(() => _searchString = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: - _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, + ), ), ), - ), - const SizedBox(height: 20), - Flexible( - child: Builder( - builder: (context) { - final coins = AppConfig.coins.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, - ) - .toList(); - - // sort alphabetically by name - items.sort((a, b) => a.name.compareTo(b.name)); - - // reverse sort walletCoins to prepare for next step - walletCoins.sort((a, b) => b.name.compareTo(a.name)); - - // insert wallet coins at beginning - for (final c in walletCoins) { - items.remove(c); - items.insert(0, c); - } - - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: ListView.builder( - shrinkWrap: true, - primary: isDesktop ? false : null, - itemCount: items.length, - itemBuilder: (builderContext, index) { - final bool hasImageUrl = items[index].image.startsWith( - "http", - ); - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: GestureDetector( - onTap: () { - Navigator.of(context).pop(items[index]); - }, - child: RoundedWhiteContainer( - child: Row( - children: [ - SizedBox( - width: 24, - height: 24, - child: - AppConfig.isStackCoin(items[index].ticker) - ? CoinIconForTicker( - ticker: items[index].ticker, - size: 24, - ) - // ? getIconForTicker( - // items[index].ticker, - // size: 24, - // ) - : hasImageUrl - ? SvgPicture.network( - items[index].image, - width: 24, - height: 24, - placeholderBuilder: - (_) => const LoadingIndicator(), - ) - : const SizedBox( - width: 24, - height: 24, + const SizedBox(height: 20), + Flexible( + child: Builder( + builder: (context) { + final coins = AppConfig.coins.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, + ) + .toList(); + + // sort alphabetically by name + items.sort((a, b) => a.name.compareTo(b.name)); + + // reverse sort walletCoins to prepare for next step + walletCoins.sort((a, b) => b.name.compareTo(a.name)); + + // insert wallet coins at beginning + for (final c in walletCoins) { + items.remove(c); + items.insert(0, c); + } + + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: ListView.builder( + shrinkWrap: true, + primary: isDesktop ? false : null, + itemCount: items.length, + itemBuilder: (builderContext, index) { + final bool hasImageUrl = items[index].image.startsWith( + "http", + ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: GestureDetector( + onTap: () { + Navigator.of(context).pop(items[index]); + }, + child: RoundedWhiteContainer( + child: Row( + children: [ + SizedBox( + width: 24, + height: 24, + child: + AppConfig.isStackCoin( + items[index].ticker, + ) + ? CoinIconForTicker( + ticker: items[index].ticker, + size: 24, + ) + // ? getIconForTicker( + // items[index].ticker, + // size: 24, + // ) + : hasImageUrl + ? SvgPicture.network( + items[index].image, + width: 24, + height: 24, + placeholderBuilder: + (_) => + const LoadingIndicator(), + ) + : const SizedBox( + width: 24, + height: 24, + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + items[index].name, + style: STextStyles.largeMedium14( + context, ), - ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - items[index].name, - style: STextStyles.largeMedium14( - context, ), - ), - const SizedBox(height: 2), - Text( - items[index].ticker.toUpperCase(), - style: STextStyles.smallMed12( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, + const SizedBox(height: 2), + Text( + items[index].ticker.toUpperCase(), + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, - ), - ); - }, + ); + }, + ), + ); + }, + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/pages/exchange_view/exchange_step_views/step_1_view.dart b/lib/pages/exchange_view/exchange_step_views/step_1_view.dart index 8e582dab9..96c168a8d 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_1_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_1_view.dart @@ -66,159 +66,157 @@ class _Step1ViewState extends State { } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 0, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Confirm amount", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Network fees and other exchange charges are included in the rate.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "You send", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 0, width: width), + const SizedBox(height: 14), + Text( + "Confirm amount", + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 8), + Text( + "Network fees and other exchange charges are included in the rate.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "You send", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - Text( - "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "You receive", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "You receive", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - Text( - "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - model.rateType == ExchangeRateType.estimated - ? "Estimated rate" - : "Fixed rate", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + model.rateType == ExchangeRateType.estimated + ? "Estimated rate" + : "Fixed rate", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemLabel, + ), ), - ), - Text( - model.rateInfo, - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + model.rateInfo, + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.of(context).pushNamed( - Step2View.routeName, - arguments: model, - ); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Next", - style: STextStyles.button(context), + const SizedBox(height: 12), + const Spacer(), + TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + Step2View.routeName, + arguments: model, + ); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Next", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart index 951c211b9..618bafb05 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart @@ -85,7 +85,8 @@ class _Step2ViewState extends ConsumerState { model.refundAddress = _refundController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && _refundController.text.isNotEmpty; }); } else { @@ -93,7 +94,8 @@ class _Step2ViewState extends ConsumerState { model.refundAddress = _refundController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && _refundController.text.isNotEmpty; }); } @@ -121,7 +123,8 @@ class _Step2ViewState extends ConsumerState { model.recipientAddress = _toController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && (_refundController.text.isNotEmpty || !ref.read(efExchangeProvider).supportsRefundAddress); }); @@ -130,7 +133,8 @@ class _Step2ViewState extends ConsumerState { model.recipientAddress = _toController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && (_refundController.text.isNotEmpty || !!ref.read(efExchangeProvider).supportsRefundAddress); }); @@ -165,9 +169,9 @@ class _Step2ViewState extends ConsumerState { .getWallet(tuple.item1) .getCurrentReceivingAddress() .then((value) { - _toController.text = value!.value; - model.recipientAddress = _toController.text; - }); + _toController.text = value!.value; + model.recipientAddress = _toController.text; + }); } else { if (model.sendTicker.toUpperCase() == tuple.item2.ticker.toUpperCase()) { @@ -176,9 +180,9 @@ class _Step2ViewState extends ConsumerState { .getWallet(tuple.item1) .getCurrentReceivingAddress() .then((value) { - _refundController.text = value!.value; - model.refundAddress = _refundController.text; - }); + _refundController.text = value!.value; + model.refundAddress = _refundController.text; + }); } } } @@ -216,303 +220,45 @@ class _Step2ViewState extends ConsumerState { } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 1, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Exchange details", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Enter your recipient and refund addresses", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Recipient Wallet", - style: STextStyles.smallMed12(context), - ), - if (AppConfig.isStackCoin(model.receiveTicker)) - CustomTextButton( - text: "Choose from ${AppConfig.prefix}", - onTap: () { - try { - final coin = AppConfig.coins.firstWhere( - (e) => - e.ticker.toLowerCase() == - model.receiveTicker.toLowerCase(), - ); - - Navigator.of(context) - .pushNamed( - ChooseFromStackView.routeName, - arguments: coin, - ) - .then((value) async { - if (value is String) { - final wallet = ref - .read(pWallets) - .getWallet(value); - - _toController.text = wallet.info.name; - model.recipientAddress = (await wallet - .getCurrentReceivingAddress()) - ?.value ?? - wallet - .info.cachedReceivingAddress; - - setState(() { - enableNext = - _toController.text.isNotEmpty && - (_refundController - .text.isNotEmpty || - !supportsRefund); - }); - } - }); - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - } - }, - ), - ], - ), - const SizedBox( - height: 4, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - onTap: () {}, - key: const Key( - "recipientExchangeStep2ViewAddressFieldKey", - ), - controller: _toController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - // inputFormatters: [ - // FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")), - // ], - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, - ), - focusNode: _toFocusNode, - style: STextStyles.field(context), - onChanged: (value) { - model.recipientAddress = _toController.text; - setState(() { - enableNext = _toController.text.isNotEmpty && - (_refundController.text.isNotEmpty || - !supportsRefund); - }); - }, - decoration: standardInputDecoration( - "Enter the ${model.receiveTicker.toUpperCase()} payout address", - _toFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _toController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _toController.text.isNotEmpty - ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - _toController.text = ""; - model.recipientAddress = - _toController.text; - - setState(() { - enableNext = _toController - .text.isNotEmpty && - (_refundController.text - .isNotEmpty || - !supportsRefund); - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - final content = - data.text!.trim(); - - _toController.text = - content; - model.recipientAddress = - _toController.text; - - setState(() { - enableNext = _toController - .text - .isNotEmpty && - (_refundController - .text - .isNotEmpty || - !supportsRefund); - }); - } - }, - child: - _toController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (_toController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = true; - Navigator.of(context) - .pushNamed( - AddressBookView.routeName, - ) - .then((_) { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = false; - - final address = ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, - ) - .state; - if (address.isNotEmpty) { - _toController.text = address; - model.recipientAddress = - _toController.text; - ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, - ) - .state = ""; - } - setState(() { - enableNext = _toController - .text.isNotEmpty && - (_refundController.text - .isNotEmpty || - !supportsRefund); - }); - }); - }, - child: const AddressBookIcon(), - ), - if (_toController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", - ), - onTap: _onToQrTapped, - child: const QrCodeIcon(), - ), - ], - ), - ), - ), - ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 1, width: width), + const SizedBox(height: 14), + Text( + "Exchange details", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox( - height: 6, - ), - RoundedWhiteContainer( - child: Text( - "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.", - style: STextStyles.label(context), + const SizedBox(height: 8), + Text( + "Enter your recipient and refund addresses", + style: STextStyles.itemSubtitle(context), ), - ), - const SizedBox( - height: 24, - ), - if (supportsRefund) + const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Refund Wallet (required)", + "Recipient Wallet", style: STextStyles.smallMed12(context), ), - if (AppConfig.isStackCoin(model.sendTicker)) + if (AppConfig.isStackCoin(model.receiveTicker)) CustomTextButton( text: "Choose from ${AppConfig.prefix}", onTap: () { @@ -520,36 +266,45 @@ class _Step2ViewState extends ConsumerState { final coin = AppConfig.coins.firstWhere( (e) => e.ticker.toLowerCase() == - model.sendTicker.toLowerCase(), + model.receiveTicker.toLowerCase(), ); Navigator.of(context) .pushNamed( - ChooseFromStackView.routeName, - arguments: coin, - ) + ChooseFromStackView.routeName, + arguments: coin, + ) .then((value) async { - if (value is String) { - final wallet = ref - .read(pWallets) - .getWallet(value); - - _refundController.text = - wallet.info.name; - model.refundAddress = (await wallet - .getCurrentReceivingAddress())! - .value; - } - setState(() { - enableNext = - _toController.text.isNotEmpty && - _refundController - .text.isNotEmpty; - }); - }); + if (value is String) { + final wallet = ref + .read(pWallets) + .getWallet(value); + + _toController.text = + wallet.info.name; + model.recipientAddress = + (await wallet + .getCurrentReceivingAddress()) + ?.value ?? + wallet + .info + .cachedReceivingAddress; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + } + }); } catch (e, s) { - Logging.instance.i( - "$e\n$s", + Logging.instance.e( + "", error: e, stackTrace: s, ); @@ -558,20 +313,17 @@ class _Step2ViewState extends ConsumerState { ), ], ), - if (supportsRefund) - const SizedBox( - height: 4, - ), - if (supportsRefund) + const SizedBox(height: 4), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), child: TextField( + onTap: () {}, key: const Key( - "refundExchangeStep2ViewAddressFieldKey", + "recipientExchangeStep2ViewAddressFieldKey", ), - controller: _refundController, + controller: _toController, readOnly: false, autocorrect: false, enableSuggestions: false, @@ -584,19 +336,20 @@ class _Step2ViewState extends ConsumerState { paste: true, selectAll: false, ), - focusNode: _refundFocusNode, + focusNode: _toFocusNode, style: STextStyles.field(context), onChanged: (value) { - model.refundAddress = _refundController.text; + model.recipientAddress = _toController.text; setState(() { enableNext = _toController.text.isNotEmpty && - _refundController.text.isNotEmpty; + (_refundController.text.isNotEmpty || + !supportsRefund); }); }, decoration: standardInputDecoration( - "Enter ${model.sendTicker.toUpperCase()} refund address", - _refundFocusNode, + "Enter the ${model.receiveTicker.toUpperCase()} payout address", + _toFocusNode, context, ).copyWith( contentPadding: const EdgeInsets.only( @@ -606,16 +359,272 @@ class _Step2ViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _refundController.text.isEmpty - ? const EdgeInsets.only(right: 16) - : const EdgeInsets.only(right: 0), + padding: + _toController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - _refundController.text.isNotEmpty + _toController.text.isNotEmpty ? TextFieldIconButton( + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + _toController.text = ""; + model.recipientAddress = + _toController.text; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + final content = + data.text!.trim(); + + _toController.text = + content; + model.recipientAddress = + _toController.text; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + } + }, + child: + _toController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (_toController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewAddressBookButtonKey", + ), + onTap: () { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = true; + Navigator.of( + context, + ).pushNamed(AddressBookView.routeName).then(( + _, + ) { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = false; + + final address = + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state; + if (address.isNotEmpty) { + _toController.text = + address; + model.recipientAddress = + _toController.text; + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state = ""; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + }); + }, + child: const AddressBookIcon(), + ), + if (_toController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewScanQrButtonKey", + ), + onTap: _onToQrTapped, + child: const QrCodeIcon(), + ), + ], + ), + ), + ), + ), + ), + ), + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Text( + "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.", + style: STextStyles.label(context), + ), + ), + const SizedBox(height: 24), + if (supportsRefund) + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Refund Wallet (required)", + style: STextStyles.smallMed12(context), + ), + if (AppConfig.isStackCoin(model.sendTicker)) + CustomTextButton( + text: "Choose from ${AppConfig.prefix}", + onTap: () { + try { + final coin = AppConfig.coins + .firstWhere( + (e) => + e.ticker.toLowerCase() == + model.sendTicker + .toLowerCase(), + ); + + Navigator.of(context) + .pushNamed( + ChooseFromStackView.routeName, + arguments: coin, + ) + .then((value) async { + if (value is String) { + final wallet = ref + .read(pWallets) + .getWallet(value); + + _refundController.text = + wallet.info.name; + model.refundAddress = + (await wallet + .getCurrentReceivingAddress())! + .value; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + _refundController + .text + .isNotEmpty; + }); + }); + } catch (e, s) { + Logging.instance.i( + "$e\n$s", + error: e, + stackTrace: s, + ); + } + }, + ), + ], + ), + if (supportsRefund) const SizedBox(height: 4), + if (supportsRefund) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "refundExchangeStep2ViewAddressFieldKey", + ), + controller: _refundController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + // inputFormatters: [ + // FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")), + // ], + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, + ), + focusNode: _refundFocusNode, + style: STextStyles.field(context), + onChanged: (value) { + model.refundAddress = + _refundController.text; + setState(() { + enableNext = + _toController.text.isNotEmpty && + _refundController.text.isNotEmpty; + }); + }, + decoration: standardInputDecoration( + "Enter ${model.sendTicker.toUpperCase()} refund address", + _refundFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + _refundController.text.isEmpty + ? const EdgeInsets.only(right: 16) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _refundController.text.isNotEmpty + ? TextFieldIconButton( key: const Key( "sendViewClearAddressFieldButtonKey", ), @@ -625,27 +634,30 @@ class _Step2ViewState extends ConsumerState { _refundController.text; setState(() { - enableNext = _toController + enableNext = + _toController .text .isNotEmpty && _refundController - .text.isNotEmpty; + .text + .isNotEmpty; }); }, child: const XIcon(), ) - : TextFieldIconButton( + : TextFieldIconButton( key: const Key( "sendViewPasteAddressFieldButtonKey", ), onTap: () async { final ClipboardData? data = await clipboard.getData( - Clipboard.kTextPlain, - ); + Clipboard.kTextPlain, + ); if (data?.text != null && data! - .text!.isNotEmpty) { + .text! + .isNotEmpty) { final content = data.text!.trim(); @@ -656,7 +668,8 @@ class _Step2ViewState extends ConsumerState { .text; setState(() { - enableNext = _toController + enableNext = + _toController .text .isNotEmpty && _refundController @@ -665,131 +678,139 @@ class _Step2ViewState extends ConsumerState { }); } }, - child: _refundController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + child: + _refundController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), ), - if (_refundController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = true; - Navigator.of(context) - .pushNamed( - AddressBookView.routeName, - ) - .then((_) { + if (_refundController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewAddressBookButtonKey", + ), + onTap: () { ref .read( exchangeFlowIsActiveStateProvider .state, ) - .state = false; - final address = ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, + .state = true; + Navigator.of(context) + .pushNamed( + AddressBookView + .routeName, ) - .state; - if (address.isNotEmpty) { - _refundController.text = - address; - model.refundAddress = - _refundController.text; - } - setState(() { - enableNext = _toController - .text.isNotEmpty && - _refundController - .text.isNotEmpty; - }); - }); - }, - child: const AddressBookIcon(), - ), - if (_refundController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", + .then((_) { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = false; + final address = + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state; + if (address + .isNotEmpty) { + _refundController + .text = address; + model.refundAddress = + _refundController + .text; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + _refundController + .text + .isNotEmpty; + }); + }); + }, + child: const AddressBookIcon(), ), - onTap: _onRefundQrTapped, - child: const QrCodeIcon(), - ), - ], + if (_refundController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewScanQrButtonKey", + ), + onTap: _onRefundQrTapped, + child: const QrCodeIcon(), + ), + ], + ), ), ), ), ), ), - ), - if (supportsRefund) - const SizedBox( - height: 6, - ), - if (supportsRefund) - RoundedWhiteContainer( - child: Text( - "In case something goes wrong during the exchange, we might need a refund address so we can return your coins back to you.", - style: STextStyles.label(context), + if (supportsRefund) const SizedBox(height: 6), + if (supportsRefund) + RoundedWhiteContainer( + child: Text( + "In case something goes wrong during the exchange, we might need a refund address so we can return your coins back to you.", + style: STextStyles.label(context), + ), ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Back", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + const SizedBox(height: 16), + const Spacer(), + Row( + children: [ + Expanded( + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Back", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, + ), ), ), ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Next", - enabled: enableNext, - onPressed: () { - Navigator.of(context).pushNamed( - Step3View.routeName, - arguments: model, - ); - }, + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Next", + enabled: enableNext, + onPressed: () { + Navigator.of(context).pushNamed( + Step3View.routeName, + arguments: model, + ); + }, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart index 92c713acb..46457ae2a 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart @@ -81,285 +81,293 @@ class _Step3ViewState extends ConsumerState { ), title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow(count: 4, current: 2, width: width), - const SizedBox(height: 14), - Text( - "Confirm exchange details", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox(height: 24), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "You send", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 2, width: width), + const SizedBox(height: 14), + Text( + "Confirm exchange details", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "You receive", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - "${model.receiveAmount.toString()} ${model.receiveTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "You send", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "Estimated rate", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - model.rateInfo, - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "You receive", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + "${model.receiveAmount.toString()} ${model.receiveTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Recipient ${model.receiveTicker.toUpperCase()} address", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox(height: 4), - Text( - model.recipientAddress!, - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "Estimated rate", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + model.rateInfo, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - if (supportsRefund) const SizedBox(height: 8), - if (supportsRefund) + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Refund ${model.sendTicker.toUpperCase()} address", + "Recipient ${model.receiveTicker.toUpperCase()} address", style: STextStyles.itemSubtitle(context), ), const SizedBox(height: 4), Text( - model.refundAddress!, + model.recipientAddress!, style: STextStyles.itemSubtitle12(context), ), ], ), ), - const SizedBox(height: 8), - const Spacer(), - Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Back", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, + if (supportsRefund) const SizedBox(height: 8), + if (supportsRefund) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Refund ${model.sendTicker.toUpperCase()} address", + style: STextStyles.itemSubtitle(context), ), - ), + const SizedBox(height: 4), + Text( + model.refundAddress!, + style: STextStyles.itemSubtitle12( + context, + ), + ), + ], ), ), - const SizedBox(width: 16), - Expanded( - child: TextButton( - onPressed: () async { - unawaited( - showDialog( - context: context, - barrierDismissible: false, - builder: - (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: - const CustomLoadingOverlay( - message: - "Creating a trade", - eventBus: null, - ), - ), - ), + const SizedBox(height: 8), + const Spacer(), + Row( + children: [ + Expanded( + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Back", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), - ); + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: TextButton( + onPressed: () async { + unawaited( + showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.6), + child: + const CustomLoadingOverlay( + message: + "Creating a trade", + eventBus: null, + ), + ), + ), + ), + ); - final ExchangeResponse response = - await ref - .read(efExchangeProvider) - .createTrade( - from: model.sendTicker, - fromNetwork: model.sendNetwork, - to: model.receiveTicker, - toNetwork: model.receiveNetwork, - fixedRate: - model.rateType != - ExchangeRateType.estimated, - amount: - model.reversed - ? model.receiveAmount - : model.sendAmount, - addressTo: - model.recipientAddress!, - extraId: null, - addressRefund: - supportsRefund - ? model.refundAddress! - : "", - refundExtraId: "", - estimate: model.estimate, - reversed: model.reversed, - ); + final ExchangeResponse response = + await ref + .read(efExchangeProvider) + .createTrade( + from: model.sendTicker, + fromNetwork: model.sendNetwork, + to: model.receiveTicker, + toNetwork: model.receiveNetwork, + fixedRate: + model.rateType != + ExchangeRateType.estimated, + amount: + model.reversed + ? model.receiveAmount + : model.sendAmount, + addressTo: + model.recipientAddress!, + extraId: null, + addressRefund: + supportsRefund + ? model.refundAddress! + : "", + refundExtraId: "", + estimate: model.estimate, + reversed: model.reversed, + ); - if (response.value == null) { - if (context.mounted) { - Navigator.of(context).pop(); + if (response.value == null) { + if (context.mounted) { + Navigator.of(context).pop(); - // TODO: better errors - String? message; - if (response.exception != null) { - message = - response.exception!.toString(); - if (message.startsWith( - "FormatException:", - ) && - message.contains("")) { + // TODO: better errors + String? message; + if (response.exception != null) { message = - "${ref.read(efExchangeProvider).name} server error"; + response.exception!.toString(); + if (message.startsWith( + "FormatException:", + ) && + message.contains("")) { + message = + "${ref.read(efExchangeProvider).name} server error"; + } } - } - unawaited( - showDialog( - context: context, - barrierDismissible: true, - builder: - (_) => StackDialog( - title: - "Failed to create trade", - message: message ?? "", - ), - ), - ); + unawaited( + showDialog( + context: context, + barrierDismissible: true, + builder: + (_) => StackDialog( + title: + "Failed to create trade", + message: message ?? "", + ), + ), + ); + } + return; } - return; - } - - // save trade to hive - await ref - .read(tradesServiceProvider) - .add( - trade: response.value!, - shouldNotifyListeners: true, - ); - String status = response.value!.status; + // save trade to hive + await ref + .read(tradesServiceProvider) + .add( + trade: response.value!, + shouldNotifyListeners: true, + ); - model.trade = response.value!; + String status = response.value!.status; - // extra info if status is waiting - if (status == "Waiting") { - status += " for deposit"; - } + model.trade = response.value!; - if (mounted) { - Navigator.of(context).pop(); - } + // extra info if status is waiting + if (status == "Waiting") { + status += " for deposit"; + } - unawaited( - NotificationApi.showNotification( - changeNowId: model.trade!.tradeId, - title: status, - body: - "Trade ID ${model.trade!.tradeId}", - walletId: "", - iconAssetName: Assets.svg.arrowRotate, - date: model.trade!.timestamp, - shouldWatchForUpdates: true, - coinName: "coinName", - ), - ); + if (mounted) { + Navigator.of(context).pop(); + } - if (mounted) { unawaited( - Navigator.of(context).pushNamed( - Step4View.routeName, - arguments: model, + NotificationApi.showNotification( + changeNowId: model.trade!.tradeId, + title: status, + body: + "Trade ID ${model.trade!.tradeId}", + walletId: "", + iconAssetName: Assets.svg.arrowRotate, + date: model.trade!.timestamp, + shouldWatchForUpdates: true, + coinName: "coinName", ), ); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Next", - style: STextStyles.button(context), + + if (mounted) { + unawaited( + Navigator.of(context).pushNamed( + Step4View.routeName, + arguments: model, + ), + ); + } + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Next", + style: STextStyles.button(context), + ), ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index be9c3ac37..72d2ff241 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -366,186 +366,136 @@ class _Step4ViewState extends ConsumerState { ), title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow(count: 4, current: 3, width: width), - const SizedBox(height: 14), - Text( - "Send ${model.sendTicker.toUpperCase()} to the address below", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox(height: 8), - Text( - "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox(height: 12), - RoundedContainer( - color: - Theme.of( - context, - ).extension()!.warningBackground, - child: RichText( - text: TextSpan( - text: - "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ", - style: STextStyles.label700(context).copyWith( - color: - Theme.of(context) - .extension()! - .warningForeground, - ), - children: [ - TextSpan( - text: - "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.", - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .warningForeground, - ), - ), - ], - ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 3, width: width), + const SizedBox(height: 14), + Text( + "Send ${model.sendTicker.toUpperCase()} to the address below", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + const SizedBox(height: 8), + Text( + "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 12), + RoundedContainer( + color: + Theme.of(context) + .extension()! + .warningBackground, + child: RichText( + text: TextSpan( + text: + "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ", + style: STextStyles.label700( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, + ), children: [ - Text( - "Amount", - style: STextStyles.itemSubtitle( + TextSpan( + text: + "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.", + style: STextStyles.label( context, - ), - ), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.sendAmount.toString(), - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 10, - ), - const SizedBox(width: 4), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], + ).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, ), ), ], ), - const SizedBox(height: 4), - Text( - "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Send ${model.sendTicker.toUpperCase()} to this address", - style: STextStyles.itemSubtitle( - context, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.itemSubtitle( + context, + ), ), - ), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.trade!.payInAddress, - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.sendAmount.toString(), ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 10, - ), - const SizedBox(width: 4), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + width: 10, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2( + context, + ), + ), + ], + ), ), + ], + ), + const SizedBox(height: 4), + Text( + "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, ), - ], - ), - const SizedBox(height: 4), - Text( - model.trade!.payInAddress, - style: STextStyles.itemSubtitle12(context), - ), - ], + ), + ], + ), ), - ), - const SizedBox(height: 6), - if (model.trade!.payInExtraId.isNotEmpty) + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -555,7 +505,7 @@ class _Step4ViewState extends ConsumerState { MainAxisAlignment.spaceBetween, children: [ Text( - "Memo", + "Send ${model.sendTicker.toUpperCase()} to this address", style: STextStyles.itemSubtitle( context, ), @@ -563,7 +513,7 @@ class _Step4ViewState extends ConsumerState { GestureDetector( onTap: () async { final data = ClipboardData( - text: model.trade!.payInExtraId, + text: model.trade!.payInAddress, ); await clipboard.setData(data); if (context.mounted) { @@ -603,7 +553,7 @@ class _Step4ViewState extends ConsumerState { ), const SizedBox(height: 4), Text( - model.trade!.payInExtraId, + model.trade!.payInAddress, style: STextStyles.itemSubtitle12( context, ), @@ -611,262 +561,337 @@ class _Step4ViewState extends ConsumerState { ], ), ), - if (model.trade!.payInExtraId.isNotEmpty) const SizedBox(height: 6), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "Trade ID", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Row( + if (model.trade!.payInExtraId.isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Memo", + style: STextStyles.itemSubtitle( + context, + ), + ), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.trade!.payInExtraId, + ); + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + width: 10, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 4), Text( - model.trade!.tradeId, + model.trade!.payInExtraId, style: STextStyles.itemSubtitle12( context, ), ), - const SizedBox(width: 10), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.trade!.tradeId, - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 12, - ), - ), ], ), - ], + ), + if (model.trade!.payInExtraId.isNotEmpty) + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "Trade ID", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Row( + children: [ + Text( + model.trade!.tradeId, + style: STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.trade!.tradeId, + ); + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + width: 12, + ), + ), + ], + ), + ], + ), ), - ), - const SizedBox(height: 6), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: STextStyles.itemSubtitle(context), - ), - Text( - _statusString, - style: STextStyles.itemSubtitle( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .colorForStatus(_statusString), + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Status", + style: STextStyles.itemSubtitle(context), ), - ), - ], + Text( + _statusString, + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: Theme.of(context) + .extension()! + .colorForStatus(_statusString), + ), + ), + ], + ), ), - ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: () { - showDialog( - context: context, - barrierDismissible: true, - builder: (_) { - return StackDialogBase( - child: Column( - children: [ - const SizedBox(height: 8), - Center( - child: Text( - "Send ${model.sendTicker} to this address", - style: STextStyles.pageTitleH2( - context, + const Spacer(), + const SizedBox(height: 12), + TextButton( + onPressed: () { + showDialog( + context: context, + barrierDismissible: true, + builder: (_) { + return StackDialogBase( + child: Column( + children: [ + const SizedBox(height: 8), + Center( + child: Text( + "Send ${model.sendTicker} to this address", + style: STextStyles.pageTitleH2( + context, + ), ), ), - ), - const SizedBox(height: 24), - Center( - child: QR( - // TODO: grab coin uri scheme from somewhere - // data: "${coin.uriScheme}:$receivingAddress", - data: model.trade!.payInAddress, - size: - MediaQuery.of( - context, - ).size.width / - 2, + const SizedBox(height: 24), + Center( + child: QR( + // TODO: grab coin uri scheme from somewhere + // data: "${coin.uriScheme}:$receivingAddress", + data: model.trade!.payInAddress, + size: + MediaQuery.of( + context, + ).size.width / + 2, + ), ), - ), - const SizedBox(height: 24), - Row( - children: [ - const Spacer(), - Expanded( - child: TextButton( - onPressed: - () => - Navigator.of( - context, - ).pop(), - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( + const SizedBox(height: 24), + Row( + children: [ + const Spacer(), + Expanded( + child: TextButton( + onPressed: + () => + Navigator.of( + context, + ).pop(), + style: Theme.of(context) + .extension< + StackColors + >()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Cancel", + style: STextStyles.button( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonTextSecondary, ), - child: Text( - "Cancel", - style: STextStyles.button( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .buttonTextSecondary, ), ), ), - ), - ], - ), - ], - ), - ); - }, - ); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Show QR Code", - style: STextStyles.button(context), + ], + ), + ], + ), + ); + }, + ); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Show QR Code", + style: STextStyles.button(context), + ), ), - ), - if (isWalletCoin) const SizedBox(height: 12), - if (isWalletCoin) - Builder( - builder: (context) { - String buttonTitle = - "Send from ${AppConfig.appName}"; - - final tuple = - ref - .read( - exchangeSendFromWalletIdStateProvider - .state, - ) - .state; - if (tuple != null && - model.sendTicker.toLowerCase() == - tuple.item2.ticker.toLowerCase()) { - final walletName = + if (isWalletCoin) const SizedBox(height: 12), + if (isWalletCoin) + Builder( + builder: (context) { + String buttonTitle = + "Send from ${AppConfig.appName}"; + + final tuple = ref - .read(pWallets) - .getWallet(tuple.item1) - .info - .name; - buttonTitle = "Send from $walletName"; - } - - return TextButton( - onPressed: - tuple != null && - model.sendTicker - .toLowerCase() == - tuple.item2.ticker - .toLowerCase() - ? () async { - await _confirmSend(tuple); - } - : () { - Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: ( - BuildContext context, - ) { - final coin = AppConfig.coins - .firstWhere( - (e) => - e.ticker - .toLowerCase() == - model - .trade! - .payInCurrency - .toLowerCase(), - ); - - return SendFromView( - coin: coin, - amount: model.sendAmount - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - address: - model - .trade! - .payInAddress, - trade: model.trade!, - ); - }, - settings: const RouteSettings( - name: - SendFromView.routeName, + .read( + exchangeSendFromWalletIdStateProvider + .state, + ) + .state; + if (tuple != null && + model.sendTicker.toLowerCase() == + tuple.item2.ticker.toLowerCase()) { + final walletName = + ref + .read(pWallets) + .getWallet(tuple.item1) + .info + .name; + buttonTitle = "Send from $walletName"; + } + + return TextButton( + onPressed: + tuple != null && + model.sendTicker + .toLowerCase() == + tuple.item2.ticker + .toLowerCase() + ? () async { + await _confirmSend(tuple); + } + : () { + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: ( + BuildContext context, + ) { + final coin = AppConfig + .coins + .firstWhere( + (e) => + e.ticker + .toLowerCase() == + model + .trade! + .payInCurrency + .toLowerCase(), + ); + + return SendFromView( + coin: coin, + amount: model.sendAmount + .toAmount( + fractionDigits: + coin.fractionDigits, + ), + address: + model + .trade! + .payInAddress, + trade: model.trade!, + ); + }, + settings: + const RouteSettings( + name: + SendFromView + .routeName, + ), ), - ), - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + buttonTitle, + style: STextStyles.button( context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), - child: Text( - buttonTitle, - style: STextStyles.button( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 850623031..bad0a3aac 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -116,7 +116,9 @@ class _SendFromViewState extends ConsumerState { ), title: Text("Send from", style: STextStyles.navBarTitle(context)), ), - body: Padding(padding: const EdgeInsets.all(16), child: child), + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), + ), ), ); }, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 8bb6017c2..a0ccd79a5 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -226,12 +226,14 @@ class _TradeDetailsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), diff --git a/lib/pages/exchange_view/wallet_initiated_exchange_view.dart b/lib/pages/exchange_view/wallet_initiated_exchange_view.dart index bfdb0e647..a2ffe26db 100644 --- a/lib/pages/exchange_view/wallet_initiated_exchange_view.dart +++ b/lib/pages/exchange_view/wallet_initiated_exchange_view.dart @@ -12,9 +12,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../models/isar/models/isar_models.dart'; -import 'exchange_form.dart'; -import 'sub_widgets/step_row.dart'; import '../../providers/exchange/exchange_form_state_provider.dart'; import '../../providers/global/prefs_provider.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; @@ -25,6 +24,8 @@ import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_loading_overlay.dart'; +import 'exchange_form.dart'; +import 'sub_widgets/step_row.dart'; class WalletInitiatedExchangeView extends ConsumerStatefulWidget { const WalletInitiatedExchangeView({ @@ -110,10 +111,9 @@ class _WalletInitiatedExchangeViewState children: [ child, Material( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.6), child: const CustomLoadingOverlay( message: "Updating exchange data", subMessage: "This could take a few minutes", @@ -139,62 +139,51 @@ class _WalletInitiatedExchangeViewState } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 0, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Exchange amount", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Network fees and other exchange charges are included in the rate.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - ExchangeForm( - walletId: walletId, - coin: coin, - contract: widget.contract, - ), - ], + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 0, width: width), + const SizedBox(height: 14), + Text( + "Exchange amount", + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 8), + Text( + "Network fees and other exchange charges are included in the rate.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 24), + ExchangeForm( + walletId: walletId, + coin: coin, + contract: widget.contract, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/generic/single_field_edit_view.dart b/lib/pages/generic/single_field_edit_view.dart index 5ffb7196f..ee8ac8b12 100644 --- a/lib/pages/generic/single_field_edit_view.dart +++ b/lib/pages/generic/single_field_edit_view.dart @@ -65,61 +65,58 @@ class _SingleFieldEditViewState extends State { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit ${widget.label}", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit ${widget.label}", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ); + }, ), - ); - }, + ), + ), ), ), - ), - ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - if (!isDesktop) - const SizedBox( - height: 10, - ), + if (!isDesktop) const SizedBox(height: 10), if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), + padding: const EdgeInsets.only(left: 32, bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -132,11 +129,10 @@ class _SingleFieldEditViewState extends State { ), ), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -145,14 +141,16 @@ class _SingleFieldEditViewState extends State { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _textController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: _textFocusNode, decoration: standardInputDecoration( widget.label.capitalize(), @@ -160,33 +158,35 @@ class _SingleFieldEditViewState extends State { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _textController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _textController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _textController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _textController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -196,30 +196,27 @@ class _SingleFieldEditViewState extends State { ConditionalParent( condition: isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.all(32), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: ButtonHeight.l, - onPressed: () { - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.all(32), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: () { + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + const SizedBox(width: 16), + Expanded(child: child), + ], ), - const SizedBox( - width: 16, - ), - Expanded( - child: child, - ), - ], - ), - ), + ), child: PrimaryButton( label: "Save", buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -230,10 +227,7 @@ class _SingleFieldEditViewState extends State { }, ), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ], ), ); diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 7619a5d34..d937ac4a7 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -83,13 +83,14 @@ class _HomeViewState extends ConsumerState { await showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async { - _exitEnabled = true; - return true; - }, - child: const StackDialog(title: "Tap back again to exit"), - ), + builder: + (_) => WillPopScope( + onWillPop: () async { + _exitEnabled = true; + return true; + }, + child: const StackDialog(title: "Tap back again to exit"), + ), ).timeout( timeout, onTimeout: () { @@ -176,16 +177,17 @@ class _HomeViewState extends ConsumerState { // dirty hack ref.listen( - prefsChangeNotifierProvider.select((value) => value.enableExchange), - (prev, next) { - if (next == false && - mounted && - ref.read(homeViewPageIndexStateProvider) != 0) { - WidgetsBinding.instance.addPostFrameCallback( - (_) => ref.read(homeViewPageIndexStateProvider.state).state = 0, - ); - } - }); + prefsChangeNotifierProvider.select((value) => value.enableExchange), + (prev, next) { + if (next == false && + mounted && + ref.read(homeViewPageIndexStateProvider) != 0) { + WidgetsBinding.instance.addPostFrameCallback( + (_) => ref.read(homeViewPageIndexStateProvider.state).state = 0, + ); + } + }, + ); return WillPopScope( onWillPop: _onWillPop, @@ -202,18 +204,13 @@ class _HomeViewState extends ConsumerState { GestureDetector( onTap: _hiddenOptions, child: RotateIcon( - icon: const AppIcon( - width: 24, - height: 24, - ), + icon: const AppIcon(width: 24, height: 24), curve: Curves.easeInOutCubic, rotationPercent: 1.0, controller: _rotateIconController, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Text( "My ${AppConfig.prefix}", style: STextStyles.navBarTitle(context), @@ -222,22 +219,11 @@ class _HomeViewState extends ConsumerState { ), actions: [ const Padding( - padding: EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: SmallTorIcon(), - ), + padding: EdgeInsets.only(top: 10, bottom: 10, right: 10), + child: AspectRatio(aspectRatio: 1, child: SmallTorIcon()), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -246,65 +232,77 @@ class _HomeViewState extends ConsumerState { key: const Key("walletsViewAlertsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, - icon: ref.watch( - notificationsProvider - .select((value) => value.hasUnreadNotifications), - ) - ? SvgPicture.file( - File( - ref.watch( - themeProvider.select( - (value) => value.assets.bellNew, - ), - ), - ), - width: 20, - height: 20, - color: ref.watch( + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + icon: + ref.watch( notificationsProvider.select( (value) => value.hasUnreadNotifications, ), ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ) - : SvgPicture.asset( - Assets.svg.bell, - width: 20, - height: 20, - color: ref.watch( - notificationsProvider.select( - (value) => value.hasUnreadNotifications, + ? SvgPicture.file( + File( + ref.watch( + themeProvider.select( + (value) => value.assets.bellNew, + ), + ), ), + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => + value.hasUnreadNotifications, + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ), + : SvgPicture.asset( + Assets.svg.bell, + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => + value.hasUnreadNotifications, + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, + ), onPressed: () { // reset unread state ref.refresh(unreadNotificationsStateProvider); - Navigator.of(context) - .pushNamed(NotificationsView.routeName) - .then((_) { - final Set unreadNotificationIds = ref - .read(unreadNotificationsStateProvider.state) - .state; + Navigator.of( + context, + ).pushNamed(NotificationsView.routeName).then((_) { + final Set unreadNotificationIds = + ref + .read(unreadNotificationsStateProvider.state) + .state; if (unreadNotificationIds.isEmpty) return; final List> futures = []; - for (int i = 0; - i < unreadNotificationIds.length - 1; - i++) { + for ( + int i = 0; + i < unreadNotificationIds.length - 1; + i++ + ) { futures.add( - ref.read(notificationsProvider).markAsRead( + ref + .read(notificationsProvider) + .markAsRead( unreadNotificationIds.elementAt(i), false, ), @@ -324,11 +322,7 @@ class _HomeViewState extends ConsumerState { ), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -336,89 +330,99 @@ class _HomeViewState extends ConsumerState { key: const Key("walletsViewSettingsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, icon: SvgPicture.asset( Assets.svg.gear, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, width: 20, height: 20, ), onPressed: () { //todo: check if print needed // debugPrint("main view settings tapped"); - Navigator.of(context) - .pushNamed(GlobalSettingsView.routeName); + Navigator.of( + context, + ).pushNamed(GlobalSettingsView.routeName); }, ), ), ), ], ), - body: Column( - children: [ - if (_children.length > 1 && - ref.watch(prefsChangeNotifierProvider).enableExchange) - Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - boxShadow: Theme.of(context) - .extension()! - .homeViewButtonBarBoxShadow != - null - ? [ - Theme.of(context) - .extension()! - .homeViewButtonBarBoxShadow!, - ] - : null, - ), - child: const Padding( - padding: EdgeInsets.only( - left: 16, - bottom: 12, - right: 16, - top: 0, + body: SafeArea( + child: Column( + children: [ + if (_children.length > 1 && + ref.watch(prefsChangeNotifierProvider).enableExchange) + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + boxShadow: + Theme.of(context) + .extension()! + .homeViewButtonBarBoxShadow != + null + ? [ + Theme.of(context) + .extension()! + .homeViewButtonBarBoxShadow!, + ] + : null, + ), + child: const Padding( + padding: EdgeInsets.only( + left: 16, + bottom: 12, + right: 16, + top: 0, + ), + child: HomeViewButtonBar(), ), - child: HomeViewButtonBar(), ), - ), - Expanded( - child: Consumer( - builder: (_, _ref, __) { - _ref.listen(homeViewPageIndexStateProvider, - (previous, next) { - if (next is int && next >= 0 && next <= 2) { - // if (next == 1) { - // _exchangeDataLoadingService.loadAll(ref); - // } - // if (next == 2) { - // _buyDataLoadingService.loadAll(ref); - // } - - _lock = true; - _animateToPage(next).then((value) => _lock = false); - } - }); - return PageView( - controller: _pageController, - children: _children, - onPageChanged: (pageIndex) { - if (!_lock) { - ref.read(homeViewPageIndexStateProvider.state).state = - pageIndex; + Expanded( + child: Consumer( + builder: (_, _ref, __) { + _ref.listen(homeViewPageIndexStateProvider, ( + previous, + next, + ) { + if (next is int && next >= 0 && next <= 2) { + // if (next == 1) { + // _exchangeDataLoadingService.loadAll(ref); + // } + // if (next == 2) { + // _buyDataLoadingService.loadAll(ref); + // } + + _lock = true; + _animateToPage(next).then((value) => _lock = false); } - }, - ); - }, + }); + return PageView( + controller: _pageController, + children: _children, + onPageChanged: (pageIndex) { + if (!_lock) { + ref + .read(homeViewPageIndexStateProvider.state) + .state = pageIndex; + } + }, + ); + }, + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/intro_view.dart b/lib/pages/intro_view.dart index 7a97eb4a0..ef84551d4 100644 --- a/lib/pages/intro_view.dart +++ b/lib/pages/intro_view.dart @@ -49,145 +49,99 @@ class _IntroViewState extends ConsumerState { @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType "); - final stack = - ref.watch(themeProvider.select((value) => value.assets.stack)); + final stack = ref.watch( + themeProvider.select((value) => value.assets.stack), + ); return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, - body: Center( - child: !isDesktop - ? Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer( - flex: 2, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 300, + body: SafeArea( + child: Center( + child: + !isDesktop + ? Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Spacer(flex: 2), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 300), + child: SizedBox( + width: isDesktop ? 324 : 266, + height: isDesktop ? 324 : 266, + child: + (stack.endsWith(".png")) + ? Image.file(File(stack)) + : SvgPicture.file( + File(stack), + width: isDesktop ? 324 : 266, + height: isDesktop ? 324 : 266, + ), + ), + ), ), - child: SizedBox( - width: isDesktop ? 324 : 266, - height: isDesktop ? 324 : 266, - child: (stack.endsWith(".png")) - ? Image.file( - File( - stack, - ), - ) - : SvgPicture.file( - File( - stack, - ), - width: isDesktop ? 324 : 266, - height: isDesktop ? 324 : 266, - ), + const Spacer(flex: 1), + AppNameText(isDesktop: isDesktop), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 48), + child: IntroAboutText(isDesktop: isDesktop), ), - ), - ), - const Spacer( - flex: 1, - ), - AppNameText( - isDesktop: isDesktop, - ), - const SizedBox( - height: 8, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 48, - ), - child: IntroAboutText( - isDesktop: isDesktop, - ), - ), - const Spacer( - flex: 4, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), - child: PrivacyAndTOSText( - isDesktop: isDesktop, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - child: Row( + const Spacer(flex: 4), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: PrivacyAndTOSText(isDesktop: isDesktop), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: Row( + children: [ + Expanded( + child: GetStartedButton(isDesktop: isDesktop), + ), + ], + ), + ), + ], + ) + : SizedBox( + width: 350, + height: 540, + child: Column( children: [ - Expanded( - child: GetStartedButton( - isDesktop: isDesktop, - ), + const Spacer(flex: 2), + const SizedBox( + width: 130, + height: 130, + child: AppIcon(), ), + const Spacer(flex: 42), + AppNameText(isDesktop: isDesktop), + const Spacer(flex: 24), + IntroAboutText(isDesktop: isDesktop), + const Spacer(flex: 42), + GetStartedButton(isDesktop: isDesktop), + if (isDesktop) const SizedBox(height: 20), + if (isDesktop) + SecondaryButton( + label: "Restore from ${AppConfig.prefix} backup", + onPressed: () { + Navigator.of(context).pushNamed( + CreatePasswordView.routeName, + arguments: true, + ); + }, + ), + const Spacer(flex: 65), + PrivacyAndTOSText(isDesktop: isDesktop), ], ), ), - ], - ) - : SizedBox( - width: 350, - height: 540, - child: Column( - children: [ - const Spacer( - flex: 2, - ), - const SizedBox( - width: 130, - height: 130, - child: AppIcon(), - ), - const Spacer( - flex: 42, - ), - AppNameText( - isDesktop: isDesktop, - ), - const Spacer( - flex: 24, - ), - IntroAboutText( - isDesktop: isDesktop, - ), - const Spacer( - flex: 42, - ), - GetStartedButton( - isDesktop: isDesktop, - ), - if (isDesktop) - const SizedBox( - height: 20, - ), - if (isDesktop) - SecondaryButton( - label: "Restore from ${AppConfig.prefix} backup", - onPressed: () { - Navigator.of(context).pushNamed( - CreatePasswordView.routeName, - arguments: true, - ); - }, - ), - const Spacer( - flex: 65, - ), - PrivacyAndTOSText( - isDesktop: isDesktop, - ), - ], - ), - ), + ), ), ), ); @@ -204,11 +158,10 @@ class AppNameText extends StatelessWidget { return Text( AppConfig.appName, textAlign: TextAlign.center, - style: !isDesktop - ? STextStyles.pageTitleH1(context) - : STextStyles.pageTitleH1(context).copyWith( - fontSize: 40, - ), + style: + !isDesktop + ? STextStyles.pageTitleH1(context) + : STextStyles.pageTitleH1(context).copyWith(fontSize: 40), ); } } @@ -223,11 +176,10 @@ class IntroAboutText extends StatelessWidget { return Text( AppConfig.shortDescriptionText, textAlign: TextAlign.center, - style: !isDesktop - ? STextStyles.subtitle(context) - : STextStyles.subtitle(context).copyWith( - fontSize: 24, - ), + style: + !isDesktop + ? STextStyles.subtitle(context) + : STextStyles.subtitle(context).copyWith(fontSize: 24), ); } } @@ -246,29 +198,34 @@ class PrivacyAndTOSText extends StatelessWidget { style: STextStyles.label(context).copyWith(fontSize: fontSize), children: [ const TextSpan( - text: "By using ${AppConfig.appName}, you agree to the "), + text: "By using ${AppConfig.appName}, you agree to the ", + ), TextSpan( text: "Terms of service", style: STextStyles.richLink(context).copyWith(fontSize: fontSize), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com/terms-of-service.html"), - mode: LaunchMode.externalApplication, - ); - }, + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/terms-of-service.html", + ), + mode: LaunchMode.externalApplication, + ); + }, ), const TextSpan(text: " and "), TextSpan( text: "Privacy policy", style: STextStyles.richLink(context).copyWith(fontSize: fontSize), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com/privacy-policy.html"), - mode: LaunchMode.externalApplication, - ); - }, + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse("https://stackwallet.com/privacy-policy.html"), + mode: LaunchMode.externalApplication, + ); + }, ), ], ), @@ -285,39 +242,34 @@ class GetStartedButton extends StatelessWidget { Widget build(BuildContext context) { return !isDesktop ? TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + onPressed: () { + Prefs.instance.externalCalls = true; + Navigator.of( + context, + ).pushNamed(StackPrivacyCalls.routeName, arguments: false); + }, + child: Text("Get started", style: STextStyles.button(context)), + ) + : SizedBox( + width: double.infinity, + height: 70, + child: TextButton( + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), onPressed: () { - Prefs.instance.externalCalls = true; - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: false, - ); + Navigator.of( + context, + ).pushNamed(StackPrivacyCalls.routeName, arguments: false); }, child: Text( - "Get started", - style: STextStyles.button(context), + "Create new ${AppConfig.prefix}", + style: STextStyles.button(context).copyWith(fontSize: 20), ), - ) - : SizedBox( - width: double.infinity, - height: 70, - child: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: false, - ); - }, - child: Text( - "Create new ${AppConfig.prefix}", - style: STextStyles.button(context).copyWith(fontSize: 20), - ), - ), - ); + ), + ); } } diff --git a/lib/pages/loading_view.dart b/lib/pages/loading_view.dart index e347860ec..c3ec1ffa1 100644 --- a/lib/pages/loading_view.dart +++ b/lib/pages/loading_view.dart @@ -14,6 +14,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lottie/lottie.dart'; + import '../themes/stack_colors.dart'; import '../themes/theme_providers.dart'; import '../utilities/assets.dart'; @@ -36,40 +37,41 @@ class LoadingView extends ConsumerWidget { return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, - body: Container( - color: Theme.of(context).extension()!.background, - child: Center( - child: ConditionalParent( - condition: Theme.of(context).extension()!.themeId == - "oled_black", - builder: (child) => RoundedContainer( - color: const Color(0xFFDEDEDE), - radiusMultiplier: 100, - width: width * 1.35, - height: width * 1.35, - child: child, - ), - child: SizedBox( - width: width, - child: assetPath != null - ? Image.file( - File( - assetPath, - ), - ) - : Lottie.asset( - Assets.lottie.test2, - animate: true, - repeat: true, - ), + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Center( + child: ConditionalParent( + condition: + Theme.of(context).extension()!.themeId == + "oled_black", + builder: + (child) => RoundedContainer( + color: const Color(0xFFDEDEDE), + radiusMultiplier: 100, + width: width * 1.35, + height: width * 1.35, + child: child, + ), + child: SizedBox( + width: width, + child: + assetPath != null + ? Image.file(File(assetPath)) + : Lottie.asset( + Assets.lottie.test2, + animate: true, + repeat: true, + ), + ), ), + // child: Image( + // image: AssetImage( + // Assets.png.splash, + // ), + // width: MediaQuery.of(context).size.width * 0.5, + // ), ), - // child: Image( - // image: AssetImage( - // Assets.png.splash, - // ), - // width: MediaQuery.of(context).size.width * 0.5, - // ), ), ), ), diff --git a/lib/pages/monkey/monkey_view.dart b/lib/pages/monkey/monkey_view.dart index ab39021cb..79cadf9a0 100644 --- a/lib/pages/monkey/monkey_view.dart +++ b/lib/pages/monkey/monkey_view.dart @@ -288,7 +288,7 @@ class _MonkeyViewState extends ConsumerState { ), ], ), - body: child, + body: SafeArea(child: child), ), child: ConditionalParent( condition: isDesktop, diff --git a/lib/pages/namecoin_names/confirm_name_transaction_view.dart b/lib/pages/namecoin_names/confirm_name_transaction_view.dart index 11dbb5c16..ff2f0b74a 100644 --- a/lib/pages/namecoin_names/confirm_name_transaction_view.dart +++ b/lib/pages/namecoin_names/confirm_name_transaction_view.dart @@ -21,7 +21,6 @@ import '../../models/isar/models/transaction_note.dart'; import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/global/secure_store_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; @@ -296,29 +295,31 @@ class _ConfirmNameTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/notification_views/notifications_view.dart b/lib/pages/notification_views/notifications_view.dart index 7a20efffd..417d10bae 100644 --- a/lib/pages/notification_views/notifications_view.dart +++ b/lib/pages/notification_views/notifications_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../notifications/notification_card.dart'; import '../../providers/providers.dart'; import '../../providers/ui/unread_notifications_provider.dart'; @@ -20,10 +21,7 @@ import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/rounded_white_container.dart'; class NotificationsView extends ConsumerStatefulWidget { - const NotificationsView({ - super.key, - this.walletId, - }); + const NotificationsView({super.key, this.walletId}); final String? walletId; @@ -46,75 +44,81 @@ class _NotificationsViewState extends ConsumerState { @override Widget build(BuildContext context) { - final notifications = widget.walletId == null - ? ref - .watch(notificationsProvider.select((value) => value.notifications)) - : ref - .watch(notificationsProvider.select((value) => value.notifications)) - .where((element) => element.walletId == widget.walletId) - .toList(growable: false); + final notifications = + widget.walletId == null + ? ref.watch( + notificationsProvider.select((value) => value.notifications), + ) + : ref + .watch( + notificationsProvider.select((value) => value.notifications), + ) + .where((element) => element.walletId == widget.walletId) + .toList(growable: false); return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, appBar: AppBar( - title: Text( - "Notifications", - style: STextStyles.navBarTitle(context), - ), + title: Text("Notifications", style: STextStyles.navBarTitle(context)), leading: AppBarBackButton( onPressed: () async { Navigator.of(context).pop(); }, ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: notifications.isNotEmpty - ? Column( - children: [ - Expanded( - child: ListView.builder( - shrinkWrap: true, - itemCount: notifications.length, - itemBuilder: (builderContext, index) { - final notification = notifications[index]; - if (notification.read == false) { - ref - .read(unreadNotificationsStateProvider.state) - .state - .add(notification.id); - } - return Padding( - padding: const EdgeInsets.all(4), - child: NotificationCard( - notification: notifications[index], - ), - ); - }, - ), - ), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: RoundedWhiteContainer( - child: Center( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - "Notifications will appear here", - style: STextStyles.itemSubtitle(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: + notifications.isNotEmpty + ? Column( + children: [ + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: notifications.length, + itemBuilder: (builderContext, index) { + final notification = notifications[index]; + if (notification.read == false) { + ref + .read( + unreadNotificationsStateProvider.state, + ) + .state + .add(notification.id); + } + return Padding( + padding: const EdgeInsets.all(4), + child: NotificationCard( + notification: notifications[index], + ), + ); + }, + ), + ), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(4), + child: RoundedWhiteContainer( + child: Center( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "Notifications will appear here", + style: STextStyles.itemSubtitle(context), + ), + ), ), ), ), - ), + ], ), - ], - ), + ), ), ), ); diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart index 40ba0333e..05d7eb227 100644 --- a/lib/pages/ordinals/ordinal_details_view.dart +++ b/lib/pages/ordinals/ordinal_details_view.dart @@ -61,20 +61,19 @@ class _OrdinalDetailsViewState extends ConsumerState { final coin = ref.watch(pWalletCoin(widget.walletId)); return Background( - child: SafeArea( - child: Scaffold( + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: const AppBarBackButton(), - title: Text( - "Ordinal details", - style: STextStyles.navBarTitle(context), - ), + leading: const AppBarBackButton(), + title: Text( + "Ordinal details", + style: STextStyles.navBarTitle(context), ), - body: SingleChildScrollView( + ), + body: SafeArea( + child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( diff --git a/lib/pages/ordinals/ordinals_filter_view.dart b/lib/pages/ordinals/ordinals_filter_view.dart index 4c7d0b398..93c7e0dd7 100644 --- a/lib/pages/ordinals/ordinals_filter_view.dart +++ b/lib/pages/ordinals/ordinals_filter_view.dart @@ -69,9 +69,7 @@ class OrdinalFilter { final ordinalFilterProvider = StateProvider((_) => null); class OrdinalsFilterView extends ConsumerStatefulWidget { - const OrdinalsFilterView({ - super.key, - }); + const OrdinalsFilterView({super.key}); static const String routeName = "/ordinalsFilterView"; @@ -127,9 +125,10 @@ class _OrdinalsFilterViewState extends ConsumerState { return Text( isDateSelected ? "From..." : _fromDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -139,9 +138,10 @@ class _OrdinalsFilterViewState extends ConsumerState { return Text( isDateSelected ? "To..." : _toDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -154,13 +154,14 @@ class _OrdinalsFilterViewState extends ConsumerState { const middleSeparatorWidth = 12.0; final isDesktop = Util.isDesktop; - final width = isDesktop - ? null - : (MediaQuery.of(context).size.width - - (middleSeparatorWidth + - (2 * middleSeparatorPadding) + - (2 * Constants.size.standardPadding))) / - 2; + final width = + isDesktop + ? null + : (MediaQuery.of(context).size.width - + (middleSeparatorWidth + + (2 * middleSeparatorPadding) + + (2 * Constants.size.standardPadding))) / + 2; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -181,7 +182,8 @@ class _OrdinalsFilterViewState extends ConsumerState { _selectedFromDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedToDate != null && + final flag = + _selectedToDate != null && !_selectedFromDate!.isBefore(_selectedToDate!); if (flag) { _selectedToDate = DateTime.fromMillisecondsSinceEpoch( @@ -191,13 +193,15 @@ class _OrdinalsFilterViewState extends ConsumerState { setState(() { if (flag) { - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); } - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); }); } } @@ -205,15 +209,18 @@ class _OrdinalsFilterViewState extends ConsumerState { child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -228,18 +235,15 @@ class _OrdinalsFilterViewState extends ConsumerState { Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateFromText, - ), + child: FittedBox(child: _dateFromText), ), ], ), @@ -248,8 +252,9 @@ class _OrdinalsFilterViewState extends ConsumerState { ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: middleSeparatorPadding), + padding: const EdgeInsets.symmetric( + horizontal: middleSeparatorPadding, + ), child: Container( width: middleSeparatorWidth, // height: 1, @@ -272,7 +277,8 @@ class _OrdinalsFilterViewState extends ConsumerState { _selectedToDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedFromDate != null && + final flag = + _selectedFromDate != null && !_selectedToDate!.isAfter(_selectedFromDate!); if (flag) { _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( @@ -282,13 +288,15 @@ class _OrdinalsFilterViewState extends ConsumerState { setState(() { if (flag) { - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); } - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); }); } } @@ -296,15 +304,18 @@ class _OrdinalsFilterViewState extends ConsumerState { child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -319,18 +330,15 @@ class _OrdinalsFilterViewState extends ConsumerState { Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateToText, - ), + child: FittedBox(child: _dateToText), ), ], ), @@ -338,10 +346,7 @@ class _OrdinalsFilterViewState extends ConsumerState { ), ), ), - if (isDesktop) - const SizedBox( - width: 24, - ), + if (isDesktop) const SizedBox(width: 24), ], ); } @@ -353,10 +358,7 @@ class _OrdinalsFilterViewState extends ConsumerState { maxWidth: 576, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: _buildContent(context), ), ); @@ -384,22 +386,23 @@ class _OrdinalsFilterViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.size.standardPadding, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _buildContent(context), + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.size.standardPadding, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _buildContent(context)), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -424,9 +427,7 @@ class _OrdinalsFilterViewState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - SizedBox( - height: isDesktop ? 14 : 10, - ), + SizedBox(height: isDesktop ? 14 : 10), // if (!isDesktop) // Align( // alignment: Alignment.centerLeft, @@ -572,33 +573,29 @@ class _OrdinalsFilterViewState extends ConsumerState { child: FittedBox( child: Text( "Date", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), _buildDateRangePicker(), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Inscription", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -612,65 +609,68 @@ class _OrdinalsFilterViewState extends ConsumerState { controller: _inscriptionTextEditingController, focusNode: inscriptionTextFieldFocusNode, onChanged: (_) => setState(() {}), - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Enter inscription number...", keywordTextFieldFocusNode, context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _inscriptionTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _inscriptionTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _inscriptionTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _inscriptionTextEditingController.text = + ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Keyword", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -683,13 +683,16 @@ class _OrdinalsFilterViewState extends ConsumerState { key: const Key("OrdinalsViewKeywordFieldKey"), controller: _keywordTextEditingController, focusNode: keywordTextFieldFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type keyword...", @@ -697,39 +700,39 @@ class _OrdinalsFilterViewState extends ConsumerState { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _keywordTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _keywordTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _keywordTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _keywordTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( children: [ Expanded( @@ -741,9 +744,7 @@ class _OrdinalsFilterViewState extends ConsumerState { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); await Future.delayed( - const Duration( - milliseconds: 75, - ), + const Duration(milliseconds: 75), ); } } @@ -753,9 +754,7 @@ class _OrdinalsFilterViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -765,16 +764,10 @@ class _OrdinalsFilterViewState extends ConsumerState { label: "Save", ), ), - if (isDesktop) - const SizedBox( - width: 32, - ), + if (isDesktop) const SizedBox(width: 32), ], ), - if (!isDesktop) - const SizedBox( - height: 20, - ), + if (!isDesktop) const SizedBox(height: 20), ], ); } diff --git a/lib/pages/ordinals/ordinals_view.dart b/lib/pages/ordinals/ordinals_view.dart index 17aaffb86..ed47fcd5c 100644 --- a/lib/pages/ordinals/ordinals_view.dart +++ b/lib/pages/ordinals/ordinals_view.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'widgets/ordinals_list.dart'; + import '../../providers/global/wallets_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; @@ -20,12 +20,10 @@ import '../../utilities/text_styles.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import 'widgets/ordinals_list.dart'; class OrdinalsView extends ConsumerStatefulWidget { - const OrdinalsView({ - super.key, - required this.walletId, - }); + const OrdinalsView({super.key, required this.walletId}); static const routeName = "/ordinalsView"; @@ -59,73 +57,66 @@ class _OrdinalsViewState extends ConsumerState { @override Widget build(BuildContext context) { return Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: const AppBarBackButton(), - title: Text( - "Ordinals", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.arrowRotate, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: () async { - // show loading for a minimum of 2 seconds on refreshing - await showLoading( - whileFuture: Future.wait([ - Future.delayed(const Duration(seconds: 2)), - (ref.read(pWallets).getWallet(widget.walletId) - as OrdinalsInterface) - .refreshInscriptions(), - ]), - context: context, - message: "Refreshing...", - ); - }, + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: const AppBarBackButton(), + title: Text("Ordinals", style: STextStyles.navBarTitle(context)), + titleSpacing: 0, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.arrowRotate, + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () async { + // show loading for a minimum of 2 seconds on refreshing + await showLoading( + whileFuture: Future.wait([ + Future.delayed(const Duration(seconds: 2)), + (ref.read(pWallets).getWallet(widget.walletId) + as OrdinalsInterface) + .refreshInscriptions(), + ]), + context: context, + message: "Refreshing...", + ); + }, ), - // AspectRatio( - // aspectRatio: 1, - // child: AppBarIconButton( - // size: 36, - // icon: SvgPicture.asset( - // Assets.svg.filter, - // width: 20, - // height: 20, - // color: Theme.of(context) - // .extension()! - // .topNavIconPrimary, - // ), - // onPressed: () { - // Navigator.of(context).pushNamed( - // OrdinalsFilterView.routeName, - // ); - // }, - // ), - // ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - left: 16, - right: 16, - top: 8, ), + // AspectRatio( + // aspectRatio: 1, + // child: AppBarIconButton( + // size: 36, + // icon: SvgPicture.asset( + // Assets.svg.filter, + // width: 20, + // height: 20, + // color: Theme.of(context) + // .extension()! + // .topNavIconPrimary, + // ), + // onPressed: () { + // Navigator.of(context).pushNamed( + // OrdinalsFilterView.routeName, + // ); + // }, + // ), + // ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 16, right: 16, top: 8), child: Column( children: [ // ClipRRect( @@ -185,11 +176,7 @@ class _OrdinalsViewState extends ConsumerState { // const SizedBox( // height: 16, // ), - Expanded( - child: OrdinalsList( - walletId: widget.walletId, - ), - ), + Expanded(child: OrdinalsList(walletId: widget.walletId)), ], ), ), diff --git a/lib/pages/receive_view/addresses/edit_address_label_view.dart b/lib/pages/receive_view/addresses/edit_address_label_view.dart index 2e6052690..f0508f4a5 100644 --- a/lib/pages/receive_view/addresses/edit_address_label_view.dart +++ b/lib/pages/receive_view/addresses/edit_address_label_view.dart @@ -28,10 +28,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditAddressLabelView extends ConsumerStatefulWidget { - const EditAddressLabelView({ - super.key, - required this.addressLabelId, - }); + const EditAddressLabelView({super.key, required this.addressLabelId}); static const String routeName = "/editAddressLabel"; @@ -54,10 +51,11 @@ class _EditAddressLabelViewState extends ConsumerState { void initState() { isDesktop = Util.isDesktop; _labelFieldController = TextEditingController(); - addressLabel = MainDB.instance.isar.addressLabels - .where() - .idEqualTo(widget.addressLabelId) - .findFirstSync()!; + addressLabel = + MainDB.instance.isar.addressLabels + .where() + .idEqualTo(widget.addressLabelId) + .findFirstSync()!; _labelFieldController.text = addressLabel.value; super.initState(); } @@ -73,145 +71,163 @@ class _EditAddressLabelViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit label", + style: STextStyles.navBarTitle(context), + ), ), - title: Text( - "Edit label", - style: STextStyles.navBarTitle(context), + body: SafeArea( + child: ConditionalParent( + condition: !isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ); + }, + ), ), - ), - body: ConditionalParent( - condition: !isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (isDesktop) + Padding( + padding: const EdgeInsets.only(left: 32, bottom: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Edit label", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], ), ), - ); - }, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Edit label", - style: STextStyles.desktopH3(context), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _labelFieldController, + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), + focusNode: labelFieldFocusNode, + decoration: standardInputDecoration( + "Address label", + labelFieldFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _labelFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _labelFieldController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), - const DesktopDialogCloseButton(), - ], + ), ), ), - Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _labelFieldController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), - focusNode: labelFieldFocusNode, - decoration: standardInputDecoration( - "Address label", - labelFieldFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _labelFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _labelFieldController.text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, + // if (!isDesktop) + const Spacer(), + if (isDesktop) + Padding( + padding: const EdgeInsets.all(32), + child: PrimaryButton( + label: "Save", + onPressed: () async { + await MainDB.instance.updateAddressLabel( + addressLabel.copyWith( + label: _labelFieldController.text, + ), + ); + if (mounted) { + Navigator.of(context).pop(); + } + }, ), ), - ), - ), - // if (!isDesktop) - const Spacer(), - if (isDesktop) - Padding( - padding: const EdgeInsets.all(32), - child: PrimaryButton( - label: "Save", + if (!isDesktop) + TextButton( onPressed: () async { await MainDB.instance.updateAddressLabel( addressLabel.copyWith( @@ -222,29 +238,13 @@ class _EditAddressLabelViewState extends ConsumerState { Navigator.of(context).pop(); } }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text("Save", style: STextStyles.button(context)), ), - ), - if (!isDesktop) - TextButton( - onPressed: () async { - await MainDB.instance.updateAddressLabel( - addressLabel.copyWith( - label: _labelFieldController.text, - ), - ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), - ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/receive_view/addresses/wallet_addresses_view.dart b/lib/pages/receive_view/addresses/wallet_addresses_view.dart index 6c1441b43..8b87fd074 100644 --- a/lib/pages/receive_view/addresses/wallet_addresses_view.dart +++ b/lib/pages/receive_view/addresses/wallet_addresses_view.dart @@ -27,10 +27,7 @@ import 'address_card.dart'; import 'address_details_view.dart'; class WalletAddressesView extends ConsumerStatefulWidget { - const WalletAddressesView({ - super.key, - required this.walletId, - }); + const WalletAddressesView({super.key, required this.walletId}); static const String routeName = "/walletAddressesView"; @@ -85,23 +82,24 @@ class _WalletAddressesViewState extends ConsumerState { .findAll(); } - final labels = await MainDB.instance - .getAddressLabels(widget.walletId) - .filter() - .group( - (q) => q - .valueContains(term, caseSensitive: false) - .or() - .addressStringContains(term, caseSensitive: false) - .or() - .group( - (q) => q - .tagsIsNotNull() - .and() - .tagsElementContains(term, caseSensitive: false), - ), - ) - .findAll(); + final labels = + await MainDB.instance + .getAddressLabels(widget.walletId) + .filter() + .group( + (q) => q + .valueContains(term, caseSensitive: false) + .or() + .addressStringContains(term, caseSensitive: false) + .or() + .group( + (q) => q.tagsIsNotNull().and().tagsElementContains( + term, + caseSensitive: false, + ), + ), + ) + .findAll(); if (labels.isEmpty) { return []; @@ -165,139 +163,137 @@ class _WalletAddressesViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.backgroundAppBar, - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - titleSpacing: 0, - title: Text( - "Wallet addresses", - style: STextStyles.navBarTitle(context), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "Wallet addresses", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding(padding: const EdgeInsets.all(16), child: child), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, - ), - ), - ), - child: Column( - children: [ - // SizedBox( - // width: isDesktop ? 490 : null, - // child: ClipRRect( - // borderRadius: BorderRadius.circular( - // Constants.size.circularBorderRadius, - // ), - // child: TextField( - // autocorrect: !isDesktop, - // enableSuggestions: !isDesktop, - // controller: _searchController, - // focusNode: searchFieldFocusNode, - // onChanged: (value) { - // setState(() { - // _searchString = value; - // }); - // }, - // style: isDesktop - // ? STextStyles.desktopTextExtraSmall(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .textFieldActiveText, - // height: 1.8, - // ) - // : STextStyles.field(context), - // decoration: standardInputDecoration( - // "Search...", - // searchFieldFocusNode, - // context, - // desktopMed: isDesktop, - // ).copyWith( - // prefixIcon: Padding( - // padding: EdgeInsets.symmetric( - // horizontal: isDesktop ? 12 : 10, - // vertical: isDesktop ? 18 : 16, - // ), - // child: SvgPicture.asset( - // Assets.svg.search, - // width: isDesktop ? 20 : 16, - // height: isDesktop ? 20 : 16, - // ), - // ), - // suffixIcon: _searchController.text.isNotEmpty - // ? Padding( - // padding: const EdgeInsets.only(right: 0), - // child: UnconstrainedBox( - // child: Row( - // children: [ - // TextFieldIconButton( - // child: const XIcon(), - // onTap: () async { - // setState(() { - // _searchController.text = ""; - // _searchString = ""; - // }); - // }, - // ), - // ], - // ), - // ), - // ) - // : null, - // ), - // ), - // ), - // ), - // SizedBox( - // height: isDesktop ? 20 : 16, - // ), - Expanded( - child: FutureBuilder( - future: _search(_searchString), - builder: (context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.data != null) { - // listview - return ListView.separated( - itemCount: snapshot.data!.length, - separatorBuilder: (_, __) => Container( - height: 10, - ), - itemBuilder: (_, index) => AddressCard( - walletId: widget.walletId, - addressId: snapshot.data![index], - coin: coin, - onPressed: () { - Navigator.of(context).pushNamed( - AddressDetailsView.routeName, - arguments: Tuple2( - snapshot.data![index], - widget.walletId, + child: SafeArea( + child: Column( + children: [ + // SizedBox( + // width: isDesktop ? 490 : null, + // child: ClipRRect( + // borderRadius: BorderRadius.circular( + // Constants.size.circularBorderRadius, + // ), + // child: TextField( + // autocorrect: !isDesktop, + // enableSuggestions: !isDesktop, + // controller: _searchController, + // focusNode: searchFieldFocusNode, + // onChanged: (value) { + // setState(() { + // _searchString = value; + // }); + // }, + // style: isDesktop + // ? STextStyles.desktopTextExtraSmall(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .textFieldActiveText, + // height: 1.8, + // ) + // : STextStyles.field(context), + // decoration: standardInputDecoration( + // "Search...", + // searchFieldFocusNode, + // context, + // desktopMed: isDesktop, + // ).copyWith( + // prefixIcon: Padding( + // padding: EdgeInsets.symmetric( + // horizontal: isDesktop ? 12 : 10, + // vertical: isDesktop ? 18 : 16, + // ), + // child: SvgPicture.asset( + // Assets.svg.search, + // width: isDesktop ? 20 : 16, + // height: isDesktop ? 20 : 16, + // ), + // ), + // suffixIcon: _searchController.text.isNotEmpty + // ? Padding( + // padding: const EdgeInsets.only(right: 0), + // child: UnconstrainedBox( + // child: Row( + // children: [ + // TextFieldIconButton( + // child: const XIcon(), + // onTap: () async { + // setState(() { + // _searchController.text = ""; + // _searchString = ""; + // }); + // }, + // ), + // ], + // ), + // ), + // ) + // : null, + // ), + // ), + // ), + // ), + // SizedBox( + // height: isDesktop ? 20 : 16, + // ), + Expanded( + child: FutureBuilder( + future: _search(_searchString), + builder: (context, AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.data != null) { + // listview + return ListView.separated( + itemCount: snapshot.data!.length, + separatorBuilder: (_, __) => Container(height: 10), + itemBuilder: + (_, index) => AddressCard( + walletId: widget.walletId, + addressId: snapshot.data![index], + coin: coin, + onPressed: () { + Navigator.of(context).pushNamed( + AddressDetailsView.routeName, + arguments: Tuple2( + snapshot.data![index], + widget.walletId, + ), + ); + }, ), - ); - }, - ), - ); - } else { - return const Center( - child: LoadingIndicator( - height: 200, - width: 200, - ), - ); - } - }, + ); + } else { + return const Center( + child: LoadingIndicator(height: 200, width: 200), + ); + } + }, + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart index 7b02e525f..d485cfa14 100644 --- a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart +++ b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart @@ -80,8 +80,9 @@ class _GenerateUriQrCodeViewState extends State { final RenderRepaintBoundary boundary = _qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary; final ui.Image image = await boundary.toImage(); - final ByteData? byteData = - await image.toByteData(format: ui.ImageByteFormat.png); + final ByteData? byteData = await image.toByteData( + format: ui.ImageByteFormat.png, + ); final Uint8List pngBytes = byteData!.buffer.asUint8List(); if (shouldSaveInsteadOfShare) { @@ -131,10 +132,9 @@ class _GenerateUriQrCodeViewState extends State { final file = await File("${tempDir.path}/qrcode.png").create(); await file.writeAsBytes(pngBytes); - await Share.shareFiles( - ["${tempDir.path}/qrcode.png"], - text: "Receive URI QR Code", - ); + await Share.shareFiles([ + "${tempDir.path}/qrcode.png", + ], text: "Receive URI QR Code"); } } catch (e) { //todo: comeback to this @@ -216,25 +216,18 @@ class _GenerateUriQrCodeViewState extends State { style: STextStyles.pageTitleH2(context), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: RepaintBoundary( key: _qrKey, child: SizedBox( width: width + 20, height: width + 20, - child: QR( - data: uriString, - size: width, - ), + child: QR(data: uriString, size: width), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: SizedBox( width: width, @@ -244,9 +237,10 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.share, width: 14, height: 14, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), onPressed: () async { await _capturePng(false); @@ -299,62 +293,68 @@ class _GenerateUriQrCodeViewState extends State { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 70)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Generate QR code", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (buildContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 70), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Generate QR code", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (buildContext, 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: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Padding( - padding: isDesktop - ? const EdgeInsets.only( - top: 12, - left: 32, - right: 32, - bottom: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.only( + top: 12, + left: 32, + right: 32, + bottom: 32, + ) + : const EdgeInsets.all(0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, @@ -366,24 +366,23 @@ class _GenerateUriQrCodeViewState extends State { style: STextStyles.itemSubtitle(context), ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), Text( "Amount (Optional)", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -393,70 +392,77 @@ class _GenerateUriQrCodeViewState extends State { enableSuggestions: Util.isDesktop ? false : true, controller: amountController, focusNode: _amountFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, - height: 1.8, - ) - : STextStyles.field(context), - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions(decimal: true), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, + height: 1.8, + ) + : STextStyles.field(context), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions(decimal: true), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Amount", _amountFocusNode, context, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: amountController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - amountController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + amountController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + amountController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), Text( "Note (Optional)", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -466,68 +472,73 @@ class _GenerateUriQrCodeViewState extends State { enableSuggestions: Util.isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Note", _noteFocusNode, context, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - SizedBox( - height: isDesktop ? 20 : 8, - ), + SizedBox(height: isDesktop ? 20 : 8), PrimaryButton( label: "Generate QR code", - onPressed: isDesktop - ? () { - final uriString = _generateURI(); - if (uriString == null) { - return; + onPressed: + isDesktop + ? () { + final uriString = _generateURI(); + if (uriString == null) { + return; + } + + setState(() { + didGenerate = true; + _uriString = uriString; + }); } - - setState(() { - didGenerate = true; - _uriString = uriString; - }); - } - : onGeneratePressed, + : onGeneratePressed, buttonHeight: isDesktop ? ButtonHeight.l : null, ), if (isDesktop && didGenerate) @@ -538,13 +549,12 @@ class _GenerateUriQrCodeViewState extends State { Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), RoundedWhiteContainer( - borderColor: Theme.of(context) - .extension()! - .background, + borderColor: + Theme.of( + context, + ).extension()!.background, width: isDesktop ? 370 : null, child: Column( children: [ @@ -552,29 +562,23 @@ class _GenerateUriQrCodeViewState extends State { "New QR Code", style: STextStyles.desktopTextMedium(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Center( child: RepaintBoundary( key: _qrKey, child: SizedBox( width: 234, height: 234, - child: QR( - data: _uriString, - size: 220, - ), + child: QR(data: _uriString, size: 220), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( - mainAxisAlignment: isDesktop - ? MainAxisAlignment.center - : MainAxisAlignment.start, + mainAxisAlignment: + isDesktop + ? MainAxisAlignment.center + : MainAxisAlignment.start, children: [ if (!isDesktop) SecondaryButton( @@ -589,15 +593,13 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.share, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), ), - if (!isDesktop) - const SizedBox( - width: 16, - ), + if (!isDesktop) const SizedBox(width: 16), PrimaryButton( width: 170, buttonHeight: @@ -612,9 +614,10 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.arrowDown, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + color: + Theme.of(context) + .extension()! + .buttonTextPrimary, ), ), ], diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index 43a5c6c8d..9c8abcb6c 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -20,7 +20,6 @@ import 'package:isar/isar.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/keys/view_only_wallet_data.dart'; import '../../notifications/show_flush_bar.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../themes/stack_colors.dart'; @@ -94,10 +93,9 @@ class _ReceiveViewState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -112,8 +110,9 @@ class _ReceiveViewState extends ConsumerState { if (wallet is Bip39HDWallet && wallet is! BCashInterface) { DerivePathType? type; if (wallet.isViewOnly && wallet is ExtendedKeysInterface) { - final voData = await wallet.getViewOnlyWalletData() - as ExtendedKeysViewOnlyWalletData; + final voData = + await wallet.getViewOnlyWalletData() + as ExtendedKeysViewOnlyWalletData; for (final t in wallet.cryptoCurrency.supportedDerivationPathTypes) { final testPath = wallet.cryptoCurrency.constructDerivePath( derivePathType: t, @@ -151,8 +150,9 @@ class _ReceiveViewState extends ConsumerState { shouldPop = true; if (mounted) { - Navigator.of(context) - .popUntil(ModalRoute.withName(ReceiveView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(ReceiveView.routeName)); setState(() { _addressMap[_walletAddressTypes[_currentIndex]] = @@ -173,10 +173,9 @@ class _ReceiveViewState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -214,7 +213,8 @@ class _ReceiveViewState extends ConsumerState { if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { _showMultiType = false; } else { - _showMultiType = _supportsSpark || + _showMultiType = + _supportsSpark || (wallet is! BCashInterface && wallet is Bip39HDWallet && wallet.supportedAddressTypes.length > 1); @@ -227,9 +227,9 @@ class _ReceiveViewState extends ConsumerState { _walletAddressTypes.insert(0, AddressType.spark); } else { _walletAddressTypes.addAll( - (wallet as Bip39HDWallet) - .supportedAddressTypes - .where((e) => e != wallet.info.mainAddressType), + (wallet as Bip39HDWallet).supportedAddressTypes.where( + (e) => e != wallet.info.mainAddressType, + ), ); } } @@ -238,8 +238,9 @@ class _ReceiveViewState extends ConsumerState { _walletAddressTypes.removeWhere((e) => e == AddressType.p2pkh); } - _addressMap[_walletAddressTypes[_currentIndex]] = - ref.read(pWalletReceivingAddress(walletId)); + _addressMap[_walletAddressTypes[_currentIndex]] = ref.read( + pWalletReceivingAddress(walletId), + ); if (_showMultiType) { for (final type in _walletAddressTypes) { @@ -255,15 +256,15 @@ class _ReceiveViewState extends ConsumerState { .findFirst() .asStream() .listen((event) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - setState(() { - _addressMap[type] = - event?.value ?? _addressMap[type] ?? "[No address yet]"; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _addressMap[type] = + event?.value ?? _addressMap[type] ?? "[No address yet]"; + }); + } }); - } - }); - }); + }); } } @@ -291,8 +292,9 @@ class _ReceiveViewState extends ConsumerState { address = ref.watch(pWalletReceivingAddress(walletId)); } - final wallet = - ref.watch(pWallets.select((value) => value.getWallet(walletId))); + final wallet = ref.watch( + pWallets.select((value) => value.getWallet(walletId)), + ); final bool canGen; if (wallet is ViewOnlyOptionInterface && @@ -318,11 +320,7 @@ class _ReceiveViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -334,9 +332,10 @@ class _ReceiveViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -353,9 +352,10 @@ class _ReceiveViewState extends ConsumerState { right: 10, child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -407,114 +407,176 @@ class _ReceiveViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ConditionalParent( - condition: _showMultiType, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - "Address type", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ), - ), - const SizedBox( - height: 10, - ), - DropdownButtonHideUnderline( - child: DropdownButton2( - value: _currentIndex, - items: [ - for (int i = 0; - i < _walletAddressTypes.length; - i++) - DropdownMenuItem( - value: i, - child: Text( - _supportsSpark && - _walletAddressTypes[i] == - AddressType.p2pkh - ? "Transparent address" - : "${_walletAddressTypes[i].readableName} address", - style: STextStyles.w500_14(context), - ), - ), - ], - onChanged: (value) { - if (value != null && value != _currentIndex) { - setState(() { - _currentIndex = value; - }); - } - }, - isExpanded: true, - iconStyleData: IconStyleData( - icon: Padding( - padding: const EdgeInsets.only(right: 10), - child: SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ConditionalParent( + condition: _showMultiType, + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Address type", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, ), ), - ), - buttonStyleData: ButtonStyleData( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 10), + DropdownButtonHideUnderline( + child: DropdownButton2( + value: _currentIndex, + items: [ + for ( + int i = 0; + i < _walletAddressTypes.length; + i++ + ) + DropdownMenuItem( + value: i, + child: Text( + _supportsSpark && + _walletAddressTypes[i] == + AddressType.p2pkh + ? "Transparent address" + : "${_walletAddressTypes[i].readableName} address", + style: STextStyles.w500_14(context), + ), + ), + ], + onChanged: (value) { + if (value != null && + value != _currentIndex) { + setState(() { + _currentIndex = value; + }); + } + }, + isExpanded: true, + iconStyleData: IconStyleData( + icon: Padding( + padding: const EdgeInsets.only(right: 10), + child: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + ), + buttonStyleData: ButtonStyleData( + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + ), ), ), - ), - dropdownStyleData: DropdownStyleData( - offset: const Offset(0, -10), - elevation: 0, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + const SizedBox(height: 12), + child, + ], + ), + child: GestureDetector( + onTap: () { + HapticFeedback.lightImpact(); + clipboard.setData(ClipboardData(text: address)); + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + }, + child: RoundedWhiteContainer( + child: Column( + children: [ + Row( + children: [ + Text( + "Your $ticker address", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 10, + height: 10, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], + ), + ], ), - ), - menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, + const SizedBox(height: 4), + Row( + children: [ + Expanded( + child: Text( + address, + style: STextStyles.itemSubtitle12( + context, + ), + ), + ), + ], ), - ), + ], ), ), - const SizedBox( - height: 12, - ), - child, - ], + ), ), - child: GestureDetector( - onTap: () { + const SizedBox(height: 12), + PrimaryButton( + label: "Copy address", + onPressed: () { HapticFeedback.lightImpact(); - clipboard.setData( - ClipboardData( - text: address, - ), - ); + clipboard.setData(ClipboardData(text: address)); showFloatingFlushBar( type: FlushBarType.info, message: "Copied to clipboard", @@ -522,134 +584,62 @@ class _ReceiveViewState extends ConsumerState { context: context, ); }, - child: RoundedWhiteContainer( - child: Column( - children: [ - Row( - children: [ - Text( - "Your $ticker address", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: Text( - address, - style: STextStyles.itemSubtitle12(context), - ), - ), - ], - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 12, - ), - PrimaryButton( - label: "Copy address", - onPressed: () { - HapticFeedback.lightImpact(); - clipboard.setData( - ClipboardData( - text: address, - ), - ); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - }, - ), - if (canGen) - const SizedBox( - height: 12, - ), - if (canGen) - SecondaryButton( - label: "Generate new address", - onPressed: _supportsSpark && - _walletAddressTypes[_currentIndex] == - AddressType.spark - ? generateNewSparkAddress - : generateNewAddress, ), - const SizedBox( - height: 30, - ), - RoundedWhiteContainer( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Column( - children: [ - QR( - data: AddressUtils.buildUriString( - coin.uriScheme, - address, - {}, + if (canGen) const SizedBox(height: 12), + if (canGen) + SecondaryButton( + label: "Generate new address", + onPressed: + _supportsSpark && + _walletAddressTypes[_currentIndex] == + AddressType.spark + ? generateNewSparkAddress + : generateNewAddress, + ), + const SizedBox(height: 30), + RoundedWhiteContainer( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Column( + children: [ + QR( + data: AddressUtils.buildUriString( + coin.uriScheme, + address, + {}, + ), + size: MediaQuery.of(context).size.width / 2, ), - size: MediaQuery.of(context).size.width / 2, - ), - const SizedBox( - height: 20, - ), - CustomTextButton( - text: "Advanced options", - onTap: () async { - unawaited( - Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => GenerateUriQrCodeView( - coin: coin, - receivingAddress: address, - ), - settings: const RouteSettings( - name: GenerateUriQrCodeView.routeName, + const SizedBox(height: 20), + CustomTextButton( + text: "Advanced options", + onTap: () async { + unawaited( + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => GenerateUriQrCodeView( + coin: coin, + receivingAddress: address, + ), + settings: const RouteSettings( + name: GenerateUriQrCodeView.routeName, + ), ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 57a6549ca..ac6d9863c 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -411,29 +411,31 @@ class _ConfirmTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/send_view/frost_ms/frost_send_view.dart b/lib/pages/send_view/frost_ms/frost_send_view.dart index 3d90a896f..22c290036 100644 --- a/lib/pages/send_view/frost_ms/frost_send_view.dart +++ b/lib/pages/send_view/frost_ms/frost_send_view.dart @@ -51,11 +51,7 @@ import '../../coin_control/coin_control_view.dart'; import 'recipient.dart'; class FrostSendView extends ConsumerStatefulWidget { - const FrostSendView({ - super.key, - required this.walletId, - required this.coin, - }); + const FrostSendView({super.key, required this.walletId, required this.coin}); static const String routeName = "/frostSendView"; @@ -107,9 +103,7 @@ class _FrostSendViewState extends ConsumerState { try { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); TxData? txData; if (mounted) { @@ -143,9 +137,7 @@ class _FrostSendViewState extends ConsumerState { callerRouteName: FrostSendView.routeName, ); - await Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + await Navigator.of(context).pushNamed(FrostStepScaffold.routeName); } } catch (e) { if (mounted) { @@ -165,9 +157,10 @@ class _FrostSendViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -229,7 +222,8 @@ class _FrostSendViewState extends ConsumerState { debugPrint("BUILD: $runtimeType"); final wallet = ref.watch(pWallets).getWallet(walletId); - final showCoinControl = wallet is CoinControlInterface && + final showCoinControl = + wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, @@ -241,56 +235,59 @@ class _FrostSendViewState extends ConsumerState { return ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 50)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Send ${coin.ticker}", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: child, - ), - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 50), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, ), - ); - }, + title: Text( + "Send ${coin.ticker}", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, + ), + ), + ), + ); + }, + ), + ), + ), ), - ), - ), child: ConditionalParent( condition: Util.isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 14, - ), - child: child, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), + child: child, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -307,24 +304,19 @@ class _FrostSendViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 22, height: 22, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context) - .copyWith(fontSize: 14), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -333,15 +325,14 @@ class _FrostSendViewState extends ConsumerState { // ), Text( "Available balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), ], ), Util.isDesktop - ? const SizedBox( - height: 24, - ) + ? const SizedBox(height: 24) : const Spacer(), GestureDetector( onTap: () {}, @@ -351,15 +342,16 @@ class _FrostSendViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalance(walletId)) .spendable, ), - style: - STextStyles.titleBold12(context).copyWith( - fontSize: 10, - ), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), ], @@ -370,41 +362,40 @@ class _FrostSendViewState extends ConsumerState { ), ), ), - SizedBox( - height: recipientWidgetIndexes.length > 1 ? 8 : 16, - ), + SizedBox(height: recipientWidgetIndexes.length > 1 ? 8 : 16), Column( children: [ for (int i = 0; i < recipientWidgetIndexes.length; i++) ConditionalParent( condition: recipientWidgetIndexes.length > 1, - builder: (child) => Padding( - padding: const EdgeInsets.only(top: 8), - child: child, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.only(top: 8), + child: child, + ), child: Recipient( - key: Key( - "recipientKey_${recipientWidgetIndexes[i]}", - ), + key: Key("recipientKey_${recipientWidgetIndexes[i]}"), index: recipientWidgetIndexes[i], displayNumber: i + 1, coin: coin, onChanged: () { _validateRecipientFormStates(); }, - remove: i == 0 && recipientWidgetIndexes.length == 1 - ? null - : () { - ref - .read( - pRecipient(recipientWidgetIndexes[i]) - .notifier, - ) - .state = null; - recipientWidgetIndexes.removeAt(i); - setState(() {}); - _validateRecipientFormStates(); - }, + remove: + i == 0 && recipientWidgetIndexes.length == 1 + ? null + : () { + ref + .read( + pRecipient( + recipientWidgetIndexes[i], + ).notifier, + ) + .state = null; + recipientWidgetIndexes.removeAt(i); + setState(() {}); + _validateRecipientFormStates(); + }, addAnotherRecipientTapped: () { // used for tracking recipient forms _greatestWidgetIndex++; @@ -413,7 +404,9 @@ class _FrostSendViewState extends ConsumerState { _validateRecipientFormStates(); }, sendAllTapped: () { - return ref.read(pAmountFormatter(coin)).format( + return ref + .read(pAmountFormatter(coin)) + .format( ref.read(pWalletBalance(walletId)).spendable, withUnitName: false, ); @@ -422,10 +415,7 @@ class _FrostSendViewState extends ConsumerState { ), ], ), - if (recipientWidgetIndexes.length > 1) - const SizedBox( - height: 12, - ), + if (recipientWidgetIndexes.length > 1) const SizedBox(height: 12), if (recipientWidgetIndexes.length > 1) SecondaryButton( width: double.infinity, @@ -437,10 +427,7 @@ class _FrostSendViewState extends ConsumerState { setState(() {}); }, ), - if (showCoinControl) - const SizedBox( - height: 8, - ), + if (showCoinControl) const SizedBox(height: 8), if (showCoinControl) RoundedWhiteContainer( child: Row( @@ -449,15 +436,17 @@ class _FrostSendViewState extends ConsumerState { Text( "Coin control", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), CustomTextButton( - text: selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", onTap: () async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); @@ -492,17 +481,13 @@ class _FrostSendViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Text( "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -519,36 +504,32 @@ class _FrostSendViewState extends ConsumerState { _noteFocusNode, context, ).copyWith( - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, - ), + padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( coin: coin, showWU: true, @@ -557,22 +538,14 @@ class _FrostSendViewState extends ConsumerState { }, ), ), - Util.isDesktop - ? const SizedBox( - height: 12, - ) - : const Spacer(), - const SizedBox( - height: 12, - ), + Util.isDesktop ? const SizedBox(height: 12) : const Spacer(), + const SizedBox(height: 12), PrimaryButton( label: "Create multisig transaction", enabled: _buttonEnabled, onPressed: _createSignConfig, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 4047a2064..4ea893ea7 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1223,7 +1223,9 @@ class _SendViewState extends ConsumerState { _address = _address!.substring(0, _address!.indexOf("\n")); } - sendToController.text = AddressUtils().formatEpicCashAddress(_address!); + sendToController.text = AddressUtils().formatEpicCashAddress( + _address!, + ); } }); } @@ -1257,733 +1259,680 @@ class _SendViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - children: [ - SvgPicture.file( - File(ref.watch(coinIconProvider(coin))), - width: 22, - height: 22, - ), - const SizedBox(width: 6), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 14), - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - // const SizedBox( - // height: 2, - // ), - if (isFiro) - Text( - "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.label( - context, - ).copyWith(fontSize: 10), - ), - if (coin is! Firo) + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + SvgPicture.file( + File(ref.watch(coinIconProvider(coin))), + width: 22, + height: 22, + ), + const SizedBox(width: 6), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ Text( - "Available balance", - style: STextStyles.label( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( context, - ).copyWith(fontSize: 10), + ).copyWith(fontSize: 14), + overflow: TextOverflow.ellipsis, + maxLines: 1, ), - ], - ), - const Spacer(), - Builder( - builder: (context) { - final Amount amount; - if (isFiro) { - switch (ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state) { - case FiroType.public: - amount = - ref - .read( - pWalletBalance(walletId), - ) - .spendable; - break; - case FiroType.lelantus: - amount = - ref - .read( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; - case FiroType.spark: - amount = - ref - .read( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; - break; + // const SizedBox( + // height: 2, + // ), + if (isFiro) + Text( + "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + if (coin is! Firo) + Text( + "Available balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + ], + ), + const Spacer(), + Builder( + builder: (context) { + final Amount amount; + if (isFiro) { + switch (ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state) { + case FiroType.public: + amount = + ref + .read( + pWalletBalance( + walletId, + ), + ) + .spendable; + break; + case FiroType.lelantus: + amount = + ref + .read( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; + break; + case FiroType.spark: + amount = + ref + .read( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; + break; + } + } else { + amount = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; } - } else { - amount = - ref - .read(pWalletBalance(walletId)) - .spendable; - } - return GestureDetector( - onTap: () { - cryptoAmountController.text = ref - .read(pAmountFormatter(coin)) - .format( - amount, - withUnitName: false, - ); - }, - child: Container( - color: Colors.transparent, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - ref - .watch( - pAmountFormatter(coin), - ) - .format(amount), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 10), - textAlign: TextAlign.right, - ), - if (price != null) + return GestureDetector( + onTap: () { + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format( + amount, + withUnitName: false, + ); + }, + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ Text( - "${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle( - context, - ).copyWith(fontSize: 8), + ref + .watch( + pAmountFormatter(coin), + ) + .format(amount), + style: + STextStyles.titleBold12( + context, + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), - ], + if (price != null) + Text( + "${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, + ), + ], + ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - isPaynymSend - ? "Send to PayNym address" - : "Send to", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - // if (coin is Monero) - // CustomTextButton( - // text: "Use OpenAlias", - // onTap: () async { - // await showModalBottomSheet( - // context: context, - // builder: (context) => - // OpenAliasBottomSheet( - // onSelected: (address) { - // sendToController.text = address; - // }, - // ), - // ); - // }, - // ), - ], - ), - const SizedBox(height: 8), - if (isPaynymSend) - TextField( - key: const Key("sendViewPaynymAddressFieldKey"), - controller: sendToController, - enabled: false, - readOnly: true, - style: STextStyles.fieldLabel(context), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + isPaynymSend + ? "Send to PayNym address" + : "Send to", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + // if (coin is Monero) + // CustomTextButton( + // text: "Use OpenAlias", + // onTap: () async { + // await showModalBottomSheet( + // context: context, + // builder: (context) => + // OpenAliasBottomSheet( + // onSelected: (address) { + // sendToController.text = address; + // }, + // ), + // ); + // }, + // ), + ], ), - if (!isPaynymSend) - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("sendViewAddressFieldKey"), + const SizedBox(height: 8), + if (isPaynymSend) + TextField( + key: const Key("sendViewPaynymAddressFieldKey"), controller: sendToController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - // inputFormatters: [ - // FilteringTextInputFormatter.allow( - // RegExp("[a-zA-Z0-9]{34}")), - // ], - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, + enabled: false, + readOnly: true, + style: STextStyles.fieldLabel(context), + ), + if (!isPaynymSend) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) async { - final trimmed = newValue.trim(); - - if ((trimmed.length - (_address?.length ?? 0)) - .abs() > - 1) { - final parsed = AddressUtils.parsePaymentUri( - trimmed, - logging: Logging.instance, - ); - if (parsed != null) { - _applyUri(parsed); + child: TextField( + key: const Key("sendViewAddressFieldKey"), + controller: sendToController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + // inputFormatters: [ + // FilteringTextInputFormatter.allow( + // RegExp("[a-zA-Z0-9]{34}")), + // ], + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, + ), + onChanged: (newValue) async { + final trimmed = newValue.trim(); + + if ((trimmed.length - + (_address?.length ?? 0)) + .abs() > + 1) { + final parsed = + AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + await _checkSparkNameAndOrSetAddress( + newValue, + ); + } } else { await _checkSparkNameAndOrSetAddress( newValue, + setController: false, ); } - } else { - await _checkSparkNameAndOrSetAddress( - newValue, - setController: false, - ); - } - - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = newValue.isNotEmpty; - }); - }, - focusNode: _addressFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${coin.ticker} address", - _addressFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: - sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _addressToggleFlag - ? TextFieldIconButton( + _setValidAddressProviders(_address); + + setState(() { + _addressToggleFlag = newValue.isNotEmpty; + }); + }, + focusNode: _addressFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${coin.ticker} address", + _addressFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _addressToggleFlag + ? TextFieldIconButton( + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders( + _address, + ); + setState(() { + _addressToggleFlag = + false; + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: _pasteAddress, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( semanticsLabel: - "Clear Button. Clears The Address Field Input.", + "Address Book Button. Opens Address Book For Address Field.", key: const Key( - "sendViewClearAddressFieldButtonKey", + "sendViewAddressBookButtonKey", ), onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders( - _address, + Navigator.of( + context, + ).pushNamed( + AddressBookView.routeName, + arguments: widget.coin, ); - setState(() { - _addressToggleFlag = false; - }); }, - child: const XIcon(), - ) - : TextFieldIconButton( + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", + "Scan QR Button. Opens Camera For Scanning QR Code.", key: const Key( - "sendViewPasteAddressFieldButtonKey", + "sendViewScanQrButtonKey", ), - onTap: _pasteAddress, - child: - sendToController - .text - .isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - semanticsLabel: - "Address Book Button. Opens Address Book For Address Field.", - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: widget.coin, - ); - }, - child: const AddressBookIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key( - "sendViewScanQrButtonKey", + onTap: _scanQr, + child: const QrCodeIcon(), ), - onTap: _scanQr, - child: const QrCodeIcon(), - ), - ], + ], + ), ), ), ), ), ), - ), - const SizedBox(height: 10), - if (isStellar || - (ref.watch(pValidSparkSendToAddress) && - ref.watch( - publicPrivateBalanceStateProvider, - ) != - FiroType.lelantus)) - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("sendViewMemoFieldKey"), - maxLength: (coin is Firo) ? 31 : null, - controller: memoController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - focusNode: _memoFocus, - style: STextStyles.field(context), - onChanged: (_) { - setState(() {}); - }, - decoration: standardInputDecoration( - "Enter memo (optional)", - _memoFocus, - context, - ).copyWith( - counterText: '', - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: - memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - memoController.text.isNotEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Memo Field Input.", - key: const Key( - "sendViewClearMemoFieldButtonKey", - ), - onTap: () { - memoController.text = ""; - setState(() {}); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Memo Field Input.", - key: const Key( - "sendViewPasteMemoFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - final String content = - data.text!.trim(); - - memoController.text = - content.trim(); - + const SizedBox(height: 10), + if (isStellar || + (ref.watch(pValidSparkSendToAddress) && + ref.watch( + publicPrivateBalanceStateProvider, + ) != + FiroType.lelantus)) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("sendViewMemoFieldKey"), + maxLength: (coin is Firo) ? 31 : null, + controller: memoController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + focusNode: _memoFocus, + style: STextStyles.field(context), + onChanged: (_) { + setState(() {}); + }, + decoration: standardInputDecoration( + "Enter memo (optional)", + _memoFocus, + context, + ).copyWith( + counterText: '', + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + memoController.text.isNotEmpty + ? TextFieldIconButton( + semanticsLabel: + "Clear Button. Clears The Memo Field Input.", + key: const Key( + "sendViewClearMemoFieldButtonKey", + ), + onTap: () { + memoController.text = ""; setState(() {}); - } - }, - child: const ClipboardIcon(), - ), - ], + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Memo Field Input.", + key: const Key( + "sendViewPasteMemoFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data! + .text! + .isNotEmpty) { + final String content = + data.text!.trim(); + + memoController.text = + content.trim(); + + setState(() {}); + } + }, + child: const ClipboardIcon(), + ), + ], + ), ), ), ), ), ), - ), - Builder( - builder: (_) { - final String? error; - - if (_address == null || _address!.isEmpty) { - error = null; - } else if (isFiro) { - if (ref.watch( - publicPrivateBalanceStateProvider, - ) == - FiroType.lelantus) { - if (_data != null && - _data.contactLabel == _address) { - error = - SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: - coin.network == - CryptoCurrencyNetwork.test, - ) - ? "Unsupported" - : null; - } else if (ref.watch( - pValidSparkSendToAddress, - )) { - error = "Unsupported"; + Builder( + builder: (_) { + final String? error; + + if (_address == null || _address!.isEmpty) { + error = null; + } else if (isFiro) { + if (ref.watch( + publicPrivateBalanceStateProvider, + ) == + FiroType.lelantus) { + if (_data != null && + _data.contactLabel == _address) { + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: + coin.network == + CryptoCurrencyNetwork.test, + ) + ? "Unsupported" + : null; + } else if (ref.watch( + pValidSparkSendToAddress, + )) { + error = "Unsupported"; + } else { + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; + } } else { - error = - ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + if (_data != null && + _data.contactLabel == _address) { + error = null; + } else if (!ref.watch( + pValidSendToAddress, + ) && + !ref.watch(pValidSparkSendToAddress)) { + error = "Invalid address"; + } else { + error = null; + } } } else { if (_data != null && _data.contactLabel == _address) { error = null; - } else if (!ref.watch(pValidSendToAddress) && - !ref.watch(pValidSparkSendToAddress)) { + } else if (!ref.watch(pValidSendToAddress)) { error = "Invalid address"; } else { error = null; } } - } else { - if (_data != null && - _data.contactLabel == _address) { - error = null; - } else if (!ref.watch(pValidSendToAddress)) { - error = "Invalid address"; - } else { - error = null; - } - } - if (error == null || error.isEmpty) { - return Container(); - } else { - return Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), - child: Text( - error, - textAlign: TextAlign.left, - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textError, + if (error == null || error.isEmpty) { + return Container(); + } else { + return Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + top: 4.0, ), - ), - ), - ); - } - }, - ), - if (isFiro) const SizedBox(height: 12), - if (isFiro) - Text( - "Send from", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - if (isFiro) const SizedBox(height: 8), - if (isFiro) - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - readOnly: true, - textInputAction: TextInputAction.none, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - ), - child: RawMaterialButton( - splashColor: - Theme.of( + child: Text( + error, + textAlign: TextAlign.left, + style: STextStyles.label( context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: - (_) => FiroBalanceSelectionSheet( - walletId: walletId, - ), - ); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.itemSubtitle12( - context, - ), - ), - const SizedBox(width: 10), - Builder( - builder: (_) { - final Amount amount; - switch (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state) { - case FiroType.public: - amount = - ref - .watch( - pWalletBalance( - walletId, - ), - ) - .spendable; - break; - case FiroType.lelantus: - amount = - ref - .watch( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; - case FiroType.spark: - amount = - ref - .watch( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; - break; - } - - return Text( - ref - .watch( - pAmountFormatter(coin), - ) - .format(amount), - style: - STextStyles.itemSubtitle( - context, - ), - ); - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, + ).copyWith( color: Theme.of(context) .extension()! - .textSubtitle2, + .textError, ), - ], + ), ), - ), - ), - ], + ); + } + }, ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + if (isFiro) const SizedBox(height: 12), + if (isFiro) Text( - "Amount", + "Send from", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is! Ethereum && coin is! Tezos) - CustomTextButton( - text: _getSendAllTitle( - showCoinControl, - selectedUTXOs, + if (isFiro) const SizedBox(height: 8), + if (isFiro) + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + readOnly: true, + textInputAction: TextInputAction.none, ), - onTap: () => _sendAllTapped(showCoinControl), - ), - ], - ), - const SizedBox(height: 8), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textDark, - ), - key: const Key( - "amountInputFieldCryptoTextFieldKey", - ), - controller: cryptoAmountController, - focusNode: _cryptoFocus, - keyboardType: - Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - textAlign: TextAlign.right, - inputFormatters: [ - AmountInputFormatter( - decimals: coin.fractionDigits, - unit: ref.watch(pAmountUnit(coin)), - locale: locale, - ), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => FiroBalanceSelectionSheet( + walletId: walletId, + ), + ); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", + style: + STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + Builder( + builder: (_) { + final Amount amount; + switch (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state) { + case FiroType.public: + amount = + ref + .watch( + pWalletBalance( + walletId, + ), + ) + .spendable; + break; + case FiroType.lelantus: + amount = + ref + .watch( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; + break; + case FiroType.spark: + amount = + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; + break; + } - // regex to validate a crypto amount with 8 decimal places - // TextInputFormatter.withFunction((oldValue, - // newValue) => - // // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') - // // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$') - // getAmountRegex(locale, coin.fractionDigits) - // .hasMatch(newValue.text) - // ? newValue - // : oldValue), - ], - decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - top: 12, - right: 12, - ), - hintText: "0", - hintStyle: STextStyles.fieldLabel( - context, - ).copyWith(fontSize: 14), - prefixIcon: FittedBox( - fit: BoxFit.scaleDown, - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - ref - .watch(pAmountUnit(coin)) - .unitForCoin(coin), - style: STextStyles.smallMed14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, + return Text( + ref + .watch( + pAmountFormatter( + coin, + ), + ) + .format(amount), + style: + STextStyles.itemSubtitle( + context, + ), + ); + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension()! + .textSubtitle2, + ), + ], + ), ), ), - ), + ], ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + if (coin is! Ethereum && coin is! Tezos) + CustomTextButton( + text: _getSendAllTitle( + showCoinControl, + selectedUTXOs, + ), + onTap: + () => _sendAllTapped(showCoinControl), + ), + ], ), - ), - if (Prefs.instance.externalCalls) const SizedBox(height: 8), - if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1994,10 +1943,10 @@ class _SendViewState extends ConsumerState { ).extension()!.textDark, ), key: const Key( - "amountInputFieldFiatTextFieldKey", + "amountInputFieldCryptoTextFieldKey", ), - controller: baseAmountController, - focusNode: _baseFocus, + controller: cryptoAmountController, + focusNode: _cryptoFocus, keyboardType: Util.isDesktop ? null @@ -2008,19 +1957,21 @@ class _SendViewState extends ConsumerState { textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( - decimals: 2, + decimals: coin.fractionDigits, + unit: ref.watch(pAmountUnit(coin)), locale: locale, ), - // regex to validate a fiat amount with 2 decimal places + + // regex to validate a crypto amount with 8 decimal places // TextInputFormatter.withFunction((oldValue, // newValue) => - // // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') - // getAmountRegex(locale, 2) + // // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') + // // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$') + // getAmountRegex(locale, coin.fractionDigits) // .hasMatch(newValue.text) // ? newValue // : oldValue), ], - onChanged: _fiatFieldChanged, decoration: InputDecoration( contentPadding: const EdgeInsets.only( top: 12, @@ -2035,11 +1986,9 @@ class _SendViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.all(12), child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - ), + ref + .watch(pAmountUnit(coin)) + .unitForCoin(coin), style: STextStyles.smallMed14( context, ).copyWith( @@ -2053,86 +2002,214 @@ class _SendViewState extends ConsumerState { ), ), ), - if (showCoinControl) const SizedBox(height: 8), - if (showCoinControl) - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Coin control", - style: STextStyles.w500_14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, + if (Prefs.instance.externalCalls) + const SizedBox(height: 8), + if (Prefs.instance.externalCalls) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", + ), + controller: baseAmountController, + focusNode: _baseFocus, + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + AmountInputFormatter( + decimals: 2, + locale: locale, + ), + // regex to validate a fiat amount with 2 decimal places + // TextInputFormatter.withFunction((oldValue, + // newValue) => + // // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // getAmountRegex(locale, 2) + // .hasMatch(newValue.text) + // ? newValue + // : oldValue), + ], + onChanged: _fiatFieldChanged, + decoration: InputDecoration( + contentPadding: const EdgeInsets.only( + top: 12, + right: 12, + ), + hintText: "0", + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), + prefixIcon: FittedBox( + fit: BoxFit.scaleDown, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), + ), + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), ), ), - CustomTextButton( - text: - selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", - onTap: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); - } - - if (context.mounted) { - final spendable = - ref - .read(pWalletBalance(walletId)) - .spendable; - - Amount? amount; - if (ref.read(pSendAmount) != null) { - amount = ref.read(pSendAmount)!; + ), + ), + if (showCoinControl) const SizedBox(height: 8), + if (showCoinControl) + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Coin control", + style: STextStyles.w500_14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + CustomTextButton( + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", + onTap: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + } - if (spendable == amount) { - // this is now a send all - } else { - amount += _currentFee; + if (context.mounted) { + final spendable = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; + + Amount? amount; + if (ref.read(pSendAmount) != null) { + amount = ref.read(pSendAmount)!; + + if (spendable == amount) { + // this is now a send all + } else { + amount += _currentFee; + } } - } - final result = await Navigator.of( - context, - ).pushNamed( - CoinControlView.routeName, - arguments: Tuple4( - walletId, - CoinControlViewType.use, - amount, - selectedUTXOs, - ), - ); + final result = await Navigator.of( + context, + ).pushNamed( + CoinControlView.routeName, + arguments: Tuple4( + walletId, + CoinControlViewType.use, + amount, + selectedUTXOs, + ), + ); - if (result is Set) { - setState(() { - selectedUTXOs = result; - }); + if (result is Set) { + setState(() { + selectedUTXOs = result; + }); + } } - } - }, + }, + ), + ], + ), + ), + const SizedBox(height: 12), + if (coin is Epiccash) + Text( + "On chain Note (optional)", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + if (coin is Epiccash) const SizedBox(height: 8), + if (coin is Epiccash) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + maxLength: 256, + controller: onChainNoteController, + focusNode: _onChainNoteFocusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type something...", + _onChainNoteFocusNode, + context, + ).copyWith( + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController + .text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), - ], + ), ), - ), - const SizedBox(height: 12), - if (coin is Epiccash) + if (coin is Epiccash) const SizedBox(height: 12), Text( - "On chain Note (optional)", + (coin is Epiccash) + ? "Local Note (optional)" + : "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) const SizedBox(height: 8), - if (coin is Epiccash) + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -2141,18 +2218,17 @@ class _SendViewState extends ConsumerState { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - maxLength: 256, - controller: onChainNoteController, - focusNode: _onChainNoteFocusNode, + controller: noteController, + focusNode: _noteFocusNode, style: STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type something...", - _onChainNoteFocusNode, + _noteFocusNode, context, ).copyWith( suffixIcon: - onChainNoteController.text.isNotEmpty + noteController.text.isNotEmpty ? Padding( padding: const EdgeInsets.only( right: 0, @@ -2164,8 +2240,8 @@ class _SendViewState extends ConsumerState { child: const XIcon(), onTap: () async { setState(() { - onChainNoteController - .text = ""; + noteController.text = + ""; }); }, ), @@ -2177,272 +2253,230 @@ class _SendViewState extends ConsumerState { ), ), ), - if (coin is Epiccash) const SizedBox(height: 12), - Text( - (coin is Epiccash) - ? "Local Note (optional)" - : "Note (optional)", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: noteController, - focusNode: _noteFocusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Type something...", - _noteFocusNode, - context, - ).copyWith( - suffixIcon: - noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only( - right: 0, - ), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, + const SizedBox(height: 12), + if (hasFees) + Text( + "Transaction fee ${isEth + ? isCustomFee.value + ? "" + : "(max)" + : "(estimated)"}", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), - ), - const SizedBox(height: 12), - if (hasFees) - Text( - "Transaction fee ${isEth - ? isCustomFee.value - ? "" - : "(max)" - : "(estimated)"}", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - if (hasFees) const SizedBox(height: 8), - if (hasFees) - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: feeController, - readOnly: true, - textInputAction: TextInputAction.none, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, + if (hasFees) const SizedBox(height: 8), + if (hasFees) + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: feeController, + readOnly: true, + textInputAction: TextInputAction.none, ), - child: RawMaterialButton( - splashColor: - Theme.of( - context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - onPressed: - isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public - ? null - : _onFeeSelectPressed, - child: - (isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public) - ? Row( - children: [ - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: - stringsToLoopThrough, - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ) - : Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Row( - children: [ - Text( - ref + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: + isFiro && + ref .watch( - feeRateTypeMobileStateProvider + publicPrivateBalanceStateProvider .state, ) - .state - .prettyName, - style: - STextStyles.itemSubtitle12( - context, - ), - ), - const SizedBox(width: 10), - FutureBuilder( - future: - _calculateFeesFuture, - builder: ( - context, - snapshot, - ) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - isCustomFee.value - ? "" - : "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: - stringsToLoopThrough, - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - color: - Theme.of(context) - .extension< - StackColors - >()! - .textSubtitle2, - ), - ], - ), + .state != + FiroType.public + ? null + : _onFeeSelectPressed, + child: + (isFiro && + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) + ? Row( + children: [ + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + stringsToLoopThrough, + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ) + : Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeMobileStateProvider + .state, + ) + .state + .prettyName, + style: + STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot + .hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + isCustomFee.value + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + stringsToLoopThrough, + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textSubtitle2, + ), + ], + ), + ), ), + ], + ), + if (isCustomFee.value && !isEth) + Padding( + padding: const EdgeInsets.only( + bottom: 12, + top: 16, + ), + child: FeeSlider( + coin: coin, + onSatVByteChanged: (rate) { + customFeeRate = rate; + }, ), - ], - ), - if (isCustomFee.value && !isEth) - Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, ), - child: FeeSlider( - coin: coin, - onSatVByteChanged: (rate) { - customFeeRate = rate; - }, + if (isCustomFee.value && isEth) + const SizedBox(height: 12), + if (isCustomFee.value && isEth) + EthFeeForm( + minGasLimit: kEthereumMinGasLimit, + stateChanged: (fee) => ethFee = fee, ), - ), - if (isCustomFee.value && isEth) + const Spacer(), const SizedBox(height: 12), - if (isCustomFee.value && isEth) - EthFeeForm( - minGasLimit: kEthereumMinGasLimit, - stateChanged: (fee) => ethFee = fee, - ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: - ref.watch(pPreviewTxButtonEnabled(coin)) - ? _previewTransaction - : null, - style: - ref.watch(pPreviewTxButtonEnabled(coin)) - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - child: Text( - "Preview", - style: STextStyles.button(context), + TextButton( + onPressed: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? _previewTransaction + : null, + style: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + child: Text( + "Preview", + style: STextStyles.button(context), + ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 7eaaa43f4..8d9f41327 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -663,365 +663,299 @@ class _TokenSendViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - children: [ - EthTokenIcon( - contractAddress: tokenContract.address, - ), - const SizedBox(width: 6), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 14), - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - Text( - "Available balance", - style: STextStyles.label( - context, - ).copyWith(fontSize: 10), - ), - ], - ), - const Spacer(), - GestureDetector( - onTap: () { - cryptoAmountController.text = ref - .watch(pAmountFormatter(coin)) - .format( - ref - .read( - pTokenBalance(( - walletId: widget.walletId, - contractAddress: - tokenContract.address, - )), - ) - .spendable, - ethContract: tokenContract, - withUnitName: false, - indicatePrecisionLoss: true, - ); - }, - child: Container( - color: Colors.transparent, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - ref - .watch( - pTokenBalance(( - walletId: - widget.walletId, - contractAddress: - tokenContract - .address, - )), - ) - .spendable, - ethContract: tokenContract, - ), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 10), - textAlign: TextAlign.right, - ), - if (price != null) + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + EthTokenIcon( + contractAddress: tokenContract.address, + ), + const SizedBox(width: 6), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + Text( + "Available balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + ], + ), + const Spacer(), + GestureDetector( + onTap: () { + cryptoAmountController.text = ref + .watch(pAmountFormatter(coin)) + .format( + ref + .read( + pTokenBalance(( + walletId: widget.walletId, + contractAddress: + tokenContract.address, + )), + ) + .spendable, + ethContract: tokenContract, + withUnitName: false, + indicatePrecisionLoss: true, + ); + }, + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ Text( - "${(ref.watch(pTokenBalance((walletId: widget.walletId, contractAddress: tokenContract.address))).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch( + pTokenBalance(( + walletId: + widget.walletId, + contractAddress: + tokenContract + .address, + )), + ) + .spendable, + ethContract: tokenContract, + ), + style: STextStyles.titleBold12( context, - ).copyWith(fontSize: 8), + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), - ], + if (price != null) + Text( + "${(ref.watch(pTokenBalance((walletId: widget.walletId, contractAddress: tokenContract.address))).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, + ), + ], + ), ), ), - ), - ], + ], + ), ), ), - ), - const SizedBox(height: 16), - Text( - "Send to", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 16), + Text( + "Send to", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - child: TextField( - key: const Key("tokenSendViewAddressFieldKey"), - controller: sendToController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) { - _address = newValue.trim(); - _updatePreviewButtonState( - _address, - _amountToSend, - ); - - setState(() { - _addressToggleFlag = newValue.isNotEmpty; - }); - }, - focusNode: _addressFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${tokenContract.symbol} address", - _addressFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, + child: TextField( + key: const Key("tokenSendViewAddressFieldKey"), + controller: sendToController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, ), - suffixIcon: Padding( - padding: - sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _addressToggleFlag - ? TextFieldIconButton( + onChanged: (newValue) { + _address = newValue.trim(); + _updatePreviewButtonState( + _address, + _amountToSend, + ); + + setState(() { + _addressToggleFlag = newValue.isNotEmpty; + }); + }, + focusNode: _addressFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${tokenContract.symbol} address", + _addressFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _addressToggleFlag + ? TextFieldIconButton( + key: const Key( + "tokenSendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, + _amountToSend, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "tokenSendViewPasteAddressFieldButtonKey", + ), + onTap: + _onTokenSendViewPasteAddressFieldButtonPressed, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( key: const Key( - "tokenSendViewClearAddressFieldButtonKey", + "sendViewAddressBookButtonKey", ), onTap: () { - sendToController.text = ""; - _address = ""; - _updatePreviewButtonState( - _address, - _amountToSend, + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: widget.coin, ); - setState(() { - _addressToggleFlag = false; - }); }, - child: const XIcon(), - ) - : TextFieldIconButton( + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( key: const Key( - "tokenSendViewPasteAddressFieldButtonKey", + "sendViewScanQrButtonKey", ), onTap: - _onTokenSendViewPasteAddressFieldButtonPressed, - child: - sendToController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", + _onTokenSendViewScanQrButtonPressed, + child: const QrCodeIcon(), ), - onTap: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: widget.coin, - ); - }, - child: const AddressBookIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", - ), - onTap: - _onTokenSendViewScanQrButtonPressed, - child: const QrCodeIcon(), - ), - ], + ], + ), ), ), ), ), ), - ), - Builder( - builder: (_) { - final error = _updateInvalidAddressText( - _address ?? "", - ); - - if (error == null || error.isEmpty) { - return Container(); - } else { - return Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), - child: Text( - error, - textAlign: TextAlign.left, - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textError, + Builder( + builder: (_) { + final error = _updateInvalidAddressText( + _address ?? "", + ); + + if (error == null || error.isEmpty) { + return Container(); + } else { + return Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + top: 4.0, + ), + child: Text( + error, + textAlign: TextAlign.left, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, + ), ), ), - ), - ); - } - }, - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - // CustomTextButton( - // text: "Send all ${tokenContract.symbol}", - // onTap: () async { - // cryptoAmountController.text = ref - // .read(tokenServiceProvider)! - // .balance - // .getSpendable() - // .toStringAsFixed(tokenContract.decimals); - // - // _cryptoAmountChanged(); - // }, - // ), - ], - ), - const SizedBox(height: 8), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textDark, - ), - key: const Key( - "amountInputFieldCryptoTextFieldKey", + ); + } + }, ), - controller: cryptoAmountController, - focusNode: _cryptoFocus, - keyboardType: - Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), - textAlign: TextAlign.right, - inputFormatters: [ - AmountInputFormatter( - decimals: tokenContract.decimals, - unit: ref.watch(pAmountUnit(coin)), - locale: locale, - ), - // // regex to validate a crypto amount with 8 decimal places - // TextInputFormatter.withFunction((oldValue, - // newValue) => - // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') - // .hasMatch(newValue.text) - // ? newValue - // : oldValue), - ], - decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - top: 12, - right: 12, - ), - hintText: "0", - hintStyle: STextStyles.fieldLabel( - context, - ).copyWith(fontSize: 14), - prefixIcon: FittedBox( - fit: BoxFit.scaleDown, - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - ref - .watch(pAmountUnit(coin)) - .unitForContract(tokenContract), - style: STextStyles.smallMed14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, - ), - ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), + // CustomTextButton( + // text: "Send all ${tokenContract.symbol}", + // onTap: () async { + // cryptoAmountController.text = ref + // .read(tokenServiceProvider)! + // .balance + // .getSpendable() + // .toStringAsFixed(tokenContract.decimals); + // + // _cryptoAmountChanged(); + // }, + // ), + ], ), - ), - if (Prefs.instance.externalCalls) const SizedBox(height: 8), - if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1032,10 +966,10 @@ class _TokenSendViewState extends ConsumerState { ).extension()!.textDark, ), key: const Key( - "amountInputFieldFiatTextFieldKey", + "amountInputFieldCryptoTextFieldKey", ), - controller: baseAmountController, - focusNode: _baseFocus, + controller: cryptoAmountController, + focusNode: _cryptoFocus, keyboardType: Util.isDesktop ? null @@ -1046,18 +980,18 @@ class _TokenSendViewState extends ConsumerState { textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( - decimals: 2, + decimals: tokenContract.decimals, + unit: ref.watch(pAmountUnit(coin)), locale: locale, ), - // // regex to validate a fiat amount with 2 decimal places + // // regex to validate a crypto amount with 8 decimal places // TextInputFormatter.withFunction((oldValue, // newValue) => - // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') // .hasMatch(newValue.text) // ? newValue // : oldValue), ], - onChanged: _onFiatAmountFieldChanged, decoration: InputDecoration( contentPadding: const EdgeInsets.only( top: 12, @@ -1072,11 +1006,9 @@ class _TokenSendViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.all(12), child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - ), + ref + .watch(pAmountUnit(coin)) + .unitForContract(tokenContract), style: STextStyles.smallMed14( context, ).copyWith( @@ -1090,243 +1022,321 @@ class _TokenSendViewState extends ConsumerState { ), ), ), - const SizedBox(height: 12), - Text( - "Note (optional)", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: noteController, - focusNode: _noteFocusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Type something...", - _noteFocusNode, - context, - ).copyWith( - suffixIcon: - noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only( - right: 0, - ), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], - ), + if (Prefs.instance.externalCalls) + const SizedBox(height: 8), + if (Prefs.instance.externalCalls) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", + ), + controller: baseAmountController, + focusNode: _baseFocus, + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + AmountInputFormatter( + decimals: 2, + locale: locale, + ), + // // regex to validate a fiat amount with 2 decimal places + // TextInputFormatter.withFunction((oldValue, + // newValue) => + // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // .hasMatch(newValue.text) + // ? newValue + // : oldValue), + ], + onChanged: _onFiatAmountFieldChanged, + decoration: InputDecoration( + contentPadding: const EdgeInsets.only( + top: 12, + right: 12, + ), + hintText: "0", + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), + prefixIcon: FittedBox( + fit: BoxFit.scaleDown, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, ), - ) - : null, + ), + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), + ), + ), + ), ), + const SizedBox(height: 12), + Text( + "Note (optional)", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), - const SizedBox(height: 12), - Text( - "Transaction fee ${isCustomFee.value ? "" : "(max)"}", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - Stack( - children: [ - TextField( + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - controller: feeController, - readOnly: true, - textInputAction: TextInputAction.none, + controller: noteController, + focusNode: _noteFocusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type something...", + _noteFocusNode, + context, + ).copyWith( + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = + ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, + ), + const SizedBox(height: 12), + Text( + "Transaction fee ${isCustomFee.value ? "" : "(max)"}", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + const SizedBox(height: 8), + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: feeController, + readOnly: true, + textInputAction: TextInputAction.none, ), - child: RawMaterialButton( - splashColor: - Theme.of( - context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - builder: - (_) => TransactionFeeSelectionSheet( - walletId: walletId, - isToken: true, - amount: (Decimal.tryParse( - cryptoAmountController - .text, - ) ?? - Decimal.zero) - .toAmount( - fractionDigits: - tokenContract.decimals, - ), - updateChosen: (String fee) { - if (fee == "custom") { - if (!isCustomFee.value) { - setState(() { - isCustomFee.value = true; - }); + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => TransactionFeeSelectionSheet( + walletId: walletId, + isToken: true, + amount: (Decimal.tryParse( + cryptoAmountController + .text, + ) ?? + Decimal.zero) + .toAmount( + fractionDigits: + tokenContract.decimals, + ), + updateChosen: (String fee) { + if (fee == "custom") { + if (!isCustomFee.value) { + setState(() { + isCustomFee.value = true; + }); + } + return; } - return; - } - setState(() { - _calculateFeesFuture = Future( - () => fee, - ); - if (isCustomFee.value) { - isCustomFee.value = false; + setState(() { + _calculateFeesFuture = Future( + () => fee, + ); + if (isCustomFee.value) { + isCustomFee.value = false; + } + }); + }, + ), + ); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeMobileStateProvider + .state, + ) + .state + .prettyName, + style: STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: _calculateFeesFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + return Text( + isCustomFee.value + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); } - }); - }, - ), - ); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - ref - .watch( - feeRateTypeMobileStateProvider - .state, - ) - .state - .prettyName, - style: STextStyles.itemSubtitle12( - context, + }, ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + colorFilter: ColorFilter.mode( + Theme.of(context) + .extension()! + .textSubtitle2, + BlendMode.srcIn, ), - const SizedBox(width: 10), - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - return Text( - isCustomFee.value - ? "" - : "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - colorFilter: ColorFilter.mode( - Theme.of(context) - .extension()! - .textSubtitle2, - BlendMode.srcIn, ), - ), - ], + ], + ), ), ), - ), - ], - ), - if (isCustomFee.value) const SizedBox(height: 12), - if (isCustomFee.value) - EthFeeForm( - minGasLimit: kEthereumTokenMinGasLimit, - stateChanged: (value) => ethFee = value, + ], ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: - ref - .watch( - previewTokenTxButtonStateProvider - .state, - ) - .state - ? _previewTransaction - : null, - style: - ref - .watch( - previewTokenTxButtonStateProvider - .state, - ) - .state - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - child: Text( - "Preview", - style: STextStyles.button(context), + if (isCustomFee.value) const SizedBox(height: 12), + if (isCustomFee.value) + EthFeeForm( + minGasLimit: kEthereumTokenMinGasLimit, + stateChanged: (value) => ethFee = value, + ), + const Spacer(), + const SizedBox(height: 12), + TextButton( + onPressed: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? _previewTransaction + : null, + style: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + child: Text( + "Preview", + style: STextStyles.button(context), + ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart index b72c3222c..404490163 100644 --- a/lib/pages/settings_views/global_settings_view/about_view.dart +++ b/lib/pages/settings_views/global_settings_view/about_view.dart @@ -40,324 +40,280 @@ class AboutView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "About", - style: STextStyles.navBarTitle(context), - ), + title: Text("About", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FutureBuilder( - future: PackageInfo.fromPlatform(), - builder: - (context, AsyncSnapshot snapshot) { - String version = ""; - String signature = ""; - String appName = ""; - String build = ""; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + String version = ""; + String signature = ""; + String appName = ""; + String build = ""; - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - version = snapshot.data!.version; - build = snapshot.data!.buildNumber; - signature = snapshot.data!.buildSignature; - appName = snapshot.data!.appName; - } + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + version = snapshot.data!.version; + build = snapshot.data!.buildNumber; + signature = snapshot.data!.buildSignature; + appName = snapshot.data!.appName; + } - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - appName, - style: STextStyles.pageTitleH2(context), + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + appName, + style: STextStyles.pageTitleH2(context), + ), ), - ), - const SizedBox( - height: 24, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Version", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - version, - style: - STextStyles.itemSubtitle(context), - ), - ], + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Version", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + version, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Build number", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - build, - style: - STextStyles.itemSubtitle(context), - ), - ], + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build number", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + build, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build commit", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + GitStatus.appCommitHash, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build signature", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + signature, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + ), + ], + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + FutureBuilder( + future: GitStatus.getFiroCommitStatus(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + CommitStatus stateOfCommit = + CommitStatus.notLoaded; + + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + stateOfCommit = snapshot.data!; + } + return RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - "Build commit", + "Firo Build Commit", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( - GitStatus.appCommitHash, - style: - STextStyles.itemSubtitle(context), + GitStatus.firoCommit, + style: GitStatus.styleForStatus( + stateOfCommit, + context, + ), ), ], ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + FutureBuilder( + future: GitStatus.getEpicCommitStatus(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + CommitStatus stateOfCommit = + CommitStatus.notLoaded; + + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + stateOfCommit = snapshot.data!; + } + + return RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - "Build signature", + "Epic Cash Build Commit", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( - signature, - style: - STextStyles.itemSubtitle(context), + GitStatus.epicCashCommit, + style: GitStatus.styleForStatus( + stateOfCommit, + context, + ), ), ], ), - ), - ], - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) - FutureBuilder( - future: GitStatus.getFiroCommitStatus(), - builder: ( - context, - AsyncSnapshot snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - stateOfCommit = snapshot.data!; - } - return RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Firo Build Commit", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - GitStatus.firoCommit, - style: GitStatus.styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ), - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) - FutureBuilder( - future: GitStatus.getEpicCommitStatus(), - builder: ( - context, - AsyncSnapshot snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - stateOfCommit = snapshot.data!; - } - - return RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Epic Cash Build Commit", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - GitStatus.epicCashCommit, - style: GitStatus.styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ), - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - // if (AppConfig.coins.whereType().isNotEmpty) - // FutureBuilder( - // future: GitStatus.getMoneroCommitStatus(), - // builder: ( - // context, - // AsyncSnapshot snapshot, - // ) { - // CommitStatus stateOfCommit = - // CommitStatus.notLoaded; - // - // if (snapshot.connectionState == - // ConnectionState.done && - // snapshot.hasData) { - // stateOfCommit = snapshot.data!; - // } - // return RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: - // CrossAxisAlignment.stretch, - // children: [ - // Text( - // "Monero Build Commit", - // style: STextStyles.titleBold12(context), - // ), - // const SizedBox( - // height: 4, - // ), - // SelectableText( - // GitStatus.moneroCommit, - // style: GitStatus.styleForStatus( - // stateOfCommit, - // context, - // ), - // ), - // ], - // ), - // ); - // }, - // ), - // const SizedBox( - // height: 12, - // ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Website", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - CustomTextButton( - text: "https://stackwallet.com", - onTap: () { - launchUrl( - Uri.parse("https://stackwallet.com"), - mode: LaunchMode.externalApplication, - ); - }, - ), - ], - ), - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + // if (AppConfig.coins.whereType().isNotEmpty) + // FutureBuilder( + // future: GitStatus.getMoneroCommitStatus(), + // builder: ( + // context, + // AsyncSnapshot snapshot, + // ) { + // CommitStatus stateOfCommit = + // CommitStatus.notLoaded; + // + // if (snapshot.connectionState == + // ConnectionState.done && + // snapshot.hasData) { + // stateOfCommit = snapshot.data!; + // } + // return RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.stretch, + // children: [ + // Text( + // "Monero Build Commit", + // style: STextStyles.titleBold12(context), + // ), + // const SizedBox( + // height: 4, + // ), + // SelectableText( + // GitStatus.moneroCommit, + // style: GitStatus.styleForStatus( + // stateOfCommit, + // context, + // ), + // ), + // ], + // ), + // ); + // }, + // ), + // const SizedBox( + // height: 12, + // ), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Tezos functionality", + "Website", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), CustomTextButton( - text: "Powered by TzKT API", + text: "https://stackwallet.com", onTap: () { launchUrl( - Uri.parse("https://tzkt.io"), + Uri.parse("https://stackwallet.com"), mode: LaunchMode.externalApplication, ); }, @@ -365,55 +321,82 @@ class AboutView extends ConsumerWidget { ], ), ), - const SizedBox( - height: 12, - ), - const Spacer(), - RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: STextStyles.label(context), - children: [ - const TextSpan( - text: - "By using ${AppConfig.appName}, you agree to the ", - ), - TextSpan( - text: "Terms of service", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/terms-of-service.html", - ), - mode: LaunchMode.externalApplication, - ); - }, - ), - const TextSpan(text: " and "), - TextSpan( - text: "Privacy policy", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/privacy-policy.html", - ), - mode: LaunchMode.externalApplication, - ); - }, + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tezos functionality", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 4), + CustomTextButton( + text: "Powered by TzKT API", + onTap: () { + launchUrl( + Uri.parse("https://tzkt.io"), + mode: LaunchMode.externalApplication, + ); + }, + ), + ], ), - ], + ), + const SizedBox(height: 12), + const Spacer(), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: STextStyles.label(context), + children: [ + const TextSpan( + text: + "By using ${AppConfig.appName}, you agree to the ", + ), + TextSpan( + text: "Terms of service", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/terms-of-service.html", + ), + mode: + LaunchMode.externalApplication, + ); + }, + ), + const TextSpan(text: " and "), + TextSpan( + text: "Privacy policy", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/privacy-policy.html", + ), + mode: + LaunchMode.externalApplication, + ); + }, + ), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart index d86f17526..20f880dd7 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart @@ -28,9 +28,7 @@ import 'manage_coin_units/manage_coin_units_view.dart'; import 'manage_explorer_view.dart'; class AdvancedSettingsView extends StatelessWidget { - const AdvancedSettingsView({ - super.key, - }); + const AdvancedSettingsView({super.key}); static const String routeName = "/advancedSettings"; @@ -47,149 +45,93 @@ class AdvancedSettingsView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Advanced", - style: STextStyles.navBarTitle(context), - ), + title: Text("Advanced", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(LoggingSettingsView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Logging", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(LoggingSettingsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Logging", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Toggle testnet coins", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.showTestNetCoins, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .showTestNetCoins = newValue; - }, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Toggle testnet coins", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, ), - ), - ], - ), - ), - ); - }, - ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Enable coin control", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.enableCoinControl, + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.showTestNetCoins, + ), ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .showTestNetCoins = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .enableCoinControl = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, - ), - ), - // showExchange pref. - if (Constants.enableExchange) - const SizedBox( - height: 8, + ); + }, + ), ), - if (Constants.enableExchange) + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -208,7 +150,7 @@ class AdvancedSettingsView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Enable exchange features", + "Enable coin control", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), @@ -218,13 +160,13 @@ class AdvancedSettingsView extends StatelessWidget { child: DraggableSwitchButton( isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.enableExchange, + (value) => value.enableCoinControl, ), ), onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .enableExchange = newValue; + .enableCoinControl = newValue; }, ), ), @@ -235,138 +177,185 @@ class AdvancedSettingsView extends StatelessWidget { }, ), ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Consumer( - builder: (_, ref, __) { - final externalCalls = ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - ); - return RawMaterialButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: true, + // showExchange pref. + if (Constants.enableExchange) const SizedBox(height: 8), + if (Constants.enableExchange) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable exchange features", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableExchange, + ), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .enableExchange = newValue; + }, + ), + ), + ], + ), + ), ); }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + ), + ), + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Consumer( + builder: (_, ref, __) { + final externalCalls = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, ), - child: Row( - children: [ - RichText( - textAlign: TextAlign.left, - text: TextSpan( - children: [ - TextSpan( - text: "${AppConfig.prefix} Experience", - style: STextStyles.titleBold12(context), - ), - TextSpan( - text: externalCalls - ? "\nEasy crypto" - : "\nIncognito", - style: STextStyles.label(context) - .copyWith(fontSize: 15.0), - ), - ], + ); + return RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + Navigator.of(context).pushNamed( + StackPrivacyCalls.routeName, + arguments: true, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + RichText( + textAlign: TextAlign.left, + text: TextSpan( + children: [ + TextSpan( + text: "${AppConfig.prefix} Experience", + style: STextStyles.titleBold12(context), + ), + TextSpan( + text: + externalCalls + ? "\nEasy crypto" + : "\nIncognito", + style: STextStyles.label( + context, + ).copyWith(fontSize: 15.0), + ), + ], + ), ), - ), - ], + ], + ), ), - ), - ); - }, - ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + ); + }, ), - onPressed: () { - Navigator.of(context).pushNamed( - ChooseCoinView.routeName, - arguments: const Tuple3( - "Manage block explorers", - "block explorer", - ManageExplorerView.routeName, + ), + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, ), - child: Row( - children: [ - Text( - "Change block explorer", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, + onPressed: () { + Navigator.of(context).pushNamed( + ChooseCoinView.routeName, + arguments: const Tuple3( + "Manage block explorers", + "block explorer", + ManageExplorerView.routeName, ), - ], + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Change block explorer", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - ManageCoinUnitsView.routeName, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Units", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageCoinUnitsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Units", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart index 08d801cc4..661939aef 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart @@ -154,9 +154,11 @@ class _EditCoinUnitsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart index 28ebe18a9..af5838eff 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart @@ -99,7 +99,7 @@ class ManageCoinUnitsView extends ConsumerWidget { style: STextStyles.navBarTitle(context), ), ), - body: child, + body: SafeArea(child: child), ), ), child: ListView.separated( diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart index 1260aa70d..486da8184 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart @@ -21,10 +21,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/rounded_white_container.dart'; class ManageExplorerView extends ConsumerStatefulWidget { - const ManageExplorerView({ - super.key, - required this.coin, - }); + const ManageExplorerView({super.key, required this.coin}); static const String routeName = "/manageExplorer"; @@ -41,9 +38,10 @@ class _ManageExplorerViewState extends ConsumerState { void initState() { super.initState(); textEditingController = TextEditingController( - text: getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]") - .toString() - .replaceAll("%5BTXID%5D", "[TXID]"), + text: getBlockExplorerTransactionUrlFor( + coin: widget.coin, + txid: "[TXID]", + ).toString().replaceAll("%5BTXID%5D", "[TXID]"), ); } @@ -69,71 +67,66 @@ class _ManageExplorerViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Expanded( - child: Column( - children: [ - TextField( - controller: textEditingController, - decoration: const InputDecoration( - border: OutlineInputBorder(), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + Expanded( + child: Column( + children: [ + TextField( + controller: textEditingController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Center( - child: Text( - "Edit your block explorer above. Keep in mind that " - "every block explorer has a slightly different URL " - "scheme.\n\nPaste in your block explorer of choice," - " then edit in [TXID] where the transaction ID " - "should go, and ${AppConfig.appName} will auto fill the " - "transaction ID in that place of URL.", - style: STextStyles.itemSubtitle(context), + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Center( + child: Text( + "Edit your block explorer above. Keep in mind that " + "every block explorer has a slightly different URL " + "scheme.\n\nPaste in your block explorer of choice," + " then edit in [TXID] where the transaction ID " + "should go, and ${AppConfig.appName} will auto fill the " + "transaction ID in that place of URL.", + style: STextStyles.itemSubtitle(context), + ), ), ), - ), - ], - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: ConstrainedBox( - constraints: const BoxConstraints( - minWidth: 480, - minHeight: 70, + ], ), - child: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - textEditingController.text = - textEditingController.text.trim(); - await setBlockExplorerForCoin( - coin: widget.coin, - url: Uri.parse( - textEditingController.text, - ), - ); + ), + Align( + alignment: Alignment.bottomCenter, + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 480, + minHeight: 70, + ), + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + textEditingController.text = + textEditingController.text.trim(); + await setBlockExplorerForCoin( + coin: widget.coin, + url: Uri.parse(textEditingController.text), + ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - child: Text( - "Save", - style: STextStyles.button(context), + if (mounted) { + Navigator.of(context).pop(); + } + }, + child: Text("Save", style: STextStyles.button(context)), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart index fe17f8ffc..aa10724a7 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart @@ -39,125 +39,124 @@ class AppearanceSettingsView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Appearance", - style: STextStyles.navBarTitle(context), - ), + title: Text("Appearance", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Display favorite wallets", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => - value.showFavoriteWallets, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Display favorite wallets", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => + value.showFavoriteWallets, + ), ), + onValueChanged: (newValue) { + ref + .read( + prefsChangeNotifierProvider, + ) + .showFavoriteWallets = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read( - prefsChangeNotifierProvider, - ) - .showFavoriteWallets = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - children: [ - Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Choose Theme", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - const SizedBox( - height: 12, - ), - const Padding( - padding: EdgeInsets.all(4), - child: ThemeOptionsWidget(), - ), - ], - ), - ], - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Add more themes", - onPressed: () { - Navigator.of(context).pushNamed( - ManageThemesView.routeName, - ); - }, - ), - ], + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + children: [ + Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Choose Theme", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + const SizedBox(height: 12), + const Padding( + padding: EdgeInsets.all(4), + child: ThemeOptionsWidget(), + ), + ], + ), + ], + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Add more themes", + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageThemesView.routeName); + }, + ), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart index 4744d857f..40f654603 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart @@ -13,9 +13,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:tuple/tuple.dart'; + import '../../../../models/isar/stack_theme.dart'; -import 'sub_widgets/install_theme_from_file_dialog.dart'; -import 'sub_widgets/stack_theme_card.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/global/prefs_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -30,7 +30,8 @@ import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/loading_indicator.dart'; import '../../../../widgets/rounded_white_container.dart'; -import 'package:tuple/tuple.dart'; +import 'sub_widgets/install_theme_from_file_dialog.dart'; +import 'sub_widgets/stack_theme_card.dart'; class ManageThemesView extends ConsumerStatefulWidget { const ManageThemesView({super.key}); @@ -66,117 +67,117 @@ class _ManageThemesViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Add more themes", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only(right: 2), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - height: 20, - width: 20, - ), - onPressed: _onInstallPressed, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, ), - ), - ], - ), - body: _showThemes - ? Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), - child: IntrinsicHeight( - child: child, - ), + title: Text( + "Add more themes", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 2), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + height: 20, + width: 20, ), - ), - ), - Padding( - padding: const EdgeInsets.all(16), - child: SecondaryButton( - label: "Install theme file", onPressed: _onInstallPressed, ), ), - ], - ) - : SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Text( - "You are using Incognito Mode. Please press the" - " button below to load available themes from our server" - " or install a theme file manually from your device.", - style: STextStyles.smallMed12(context), + ), + ], + ), + body: SafeArea( + child: + _showThemes + ? Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), + child: IntrinsicHeight(child: child), + ), + ), ), - ), - const SizedBox( - height: 12, - ), - PrimaryButton( - label: "Load themes", - onPressed: () { - setState(() { - _showThemes = true; - future = ref.watch(pThemeService).fetchThemes; - }); - }, - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Install theme file", - onPressed: _onInstallPressed, - ), - const SizedBox( - height: 16, - ), - Expanded( - child: IncognitoInstalledThemes( - cardWidth: - (MediaQuery.of(context).size.width - 48) / 2, + Padding( + padding: const EdgeInsets.all(16), + child: SecondaryButton( + label: "Install theme file", + onPressed: _onInstallPressed, + ), + ), + ], + ) + : SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Text( + "You are using Incognito Mode. Please press the" + " button below to load available themes from our server" + " or install a theme file manually from your device.", + style: STextStyles.smallMed12(context), + ), + ), + const SizedBox(height: 12), + PrimaryButton( + label: "Load themes", + onPressed: () { + setState(() { + _showThemes = true; + future = + ref + .watch(pThemeService) + .fetchThemes; + }); + }, + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Install theme file", + onPressed: _onInstallPressed, + ), + const SizedBox(height: 16), + Expanded( + child: IncognitoInstalledThemes( + cardWidth: + (MediaQuery.of(context).size.width - + 48) / + 2, + ), + ), + const SizedBox(height: 16), + ], + ), ), ), - const SizedBox( - height: 16, - ), - ], - ), - ), - ), - ), - ), - ), + ), + ), + ), + ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -191,17 +192,17 @@ class _ManageThemesViewState extends ConsumerState { return Wrap( spacing: 16, runSpacing: 16, - children: snapshot.data! - .map( - (e) => SizedBox( - key: Key("ManageThemesView_card_${e.id}_key"), - width: (MediaQuery.of(context).size.width - 48) / 2, - child: StackThemeCard( - data: e, - ), - ), - ) - .toList(), + children: + snapshot.data! + .map( + (e) => SizedBox( + key: Key("ManageThemesView_card_${e.id}_key"), + width: + (MediaQuery.of(context).size.width - 48) / 2, + child: StackThemeCard(data: e), + ), + ) + .toList(), ); } else { return Center( @@ -219,10 +220,7 @@ class _ManageThemesViewState extends ConsumerState { } class IncognitoInstalledThemes extends ConsumerStatefulWidget { - const IncognitoInstalledThemes({ - super.key, - required this.cardWidth, - }); + const IncognitoInstalledThemes({super.key, required this.cardWidth}); final double cardWidth; @@ -238,28 +236,33 @@ class _IncognitoInstalledThemesState List> installedThemeIdNames = []; void _updateInstalledList() { - installedThemeIdNames = ref - .read(pThemeService) - .installedThemes - .where((e) => e.themeId != "light" && e.themeId != "dark") - .map((e) => Tuple3(e.themeId, e.name, e.version)) - .toList(); + installedThemeIdNames = + ref + .read(pThemeService) + .installedThemes + .where((e) => e.themeId != "light" && e.themeId != "dark") + .map((e) => Tuple3(e.themeId, e.name, e.version)) + .toList(); } @override void initState() { _updateInstalledList(); - _subscription = - ref.read(mainDBProvider).isar.stackThemes.watchLazy().listen((_) { - if (mounted) { - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _updateInstalledList(); - }); + _subscription = ref + .read(mainDBProvider) + .isar + .stackThemes + .watchLazy() + .listen((_) { + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + _updateInstalledList(); + }); + }); + } }); - } - }); super.initState(); } @@ -275,24 +278,25 @@ class _IncognitoInstalledThemesState return Wrap( spacing: 16, runSpacing: 16, - children: installedThemeIdNames - .map( - (e) => SizedBox( - key: Key("IncognitoInstalledThemes_card_${e.item1}_key"), - width: widget.cardWidth, - child: StackThemeCard( - data: StackThemeMetaData( - name: e.item2, - id: e.item1, - version: e.item3 ?? 1, - sha256: "", - size: "", - previewImageUrl: "", + children: + installedThemeIdNames + .map( + (e) => SizedBox( + key: Key("IncognitoInstalledThemes_card_${e.item1}_key"), + width: widget.cardWidth, + child: StackThemeCard( + data: StackThemeMetaData( + name: e.item2, + id: e.item1, + version: e.item3 ?? 1, + sha256: "", + size: "", + previewImageUrl: "", + ), + ), ), - ), - ), - ) - .toList(), + ) + .toList(), ); } } diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart index becef5fb6..d78c6cb3f 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart @@ -64,11 +64,12 @@ class _SystemBrightnessThemeSelectionViewState @override void initState() { - installedThemeIdNames = ref - .read(pThemeService) - .installedThemes - .map((e) => Tuple2(e.themeId, e.name)) - .toList(); + installedThemeIdNames = + ref + .read(pThemeService) + .installedThemes + .map((e) => Tuple2(e.themeId, e.name)) + .toList(); super.initState(); } @@ -89,52 +90,45 @@ class _SystemBrightnessThemeSelectionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 16, - ), - RoundedWhiteContainer( - child: Text( - "Select a light and dark theme that will be" - " activated automatically when your phone system" - " switches light and dark mode.", - style: STextStyles.smallMed12(context), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 16), + RoundedWhiteContainer( + child: Text( + "Select a light and dark theme that will be" + " activated automatically when your phone system" + " switches light and dark mode.", + style: STextStyles.smallMed12(context), + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Choose light mode theme", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 18, - ), - for (int i = 0; + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose light mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 18), + for ( + int i = 0; i < (2 * installedThemeIdNames.length) - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( + i++ + ) + (i % 2 == 1) + ? const SizedBox(height: 10) + : ThemeOption( label: installedThemeIdNames[i ~/ 2].item2, onPressed: () { @@ -170,36 +164,33 @@ class _SystemBrightnessThemeSelectionViewState installedThemeIdNames[i ~/ 2].item1, groupValue: ref.watch( prefsChangeNotifierProvider.select( - (value) => value - .systemBrightnessLightThemeId, + (value) => + value + .systemBrightnessLightThemeId, ), ), ), - ], + ], + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Choose dark mode theme", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 18, - ), - for (int i = 0; + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose dark mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 18), + for ( + int i = 0; i < (2 * installedThemeIdNames.length) - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( + i++ + ) + (i % 2 == 1) + ? const SizedBox(height: 10) + : ThemeOption( label: installedThemeIdNames[i ~/ 2].item2, onPressed: () { @@ -235,24 +226,24 @@ class _SystemBrightnessThemeSelectionViewState installedThemeIdNames[i ~/ 2].item1, groupValue: ref.watch( prefsChangeNotifierProvider.select( - (value) => value - .systemBrightnessDarkThemeId, + (value) => + value + .systemBrightnessDarkThemeId, ), ), ), - ], + ], + ), ), - ), - const SizedBox( - height: 16, - ), - ], + const SizedBox(height: 16), + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/currency_view.dart b/lib/pages/settings_views/global_settings_view/currency_view.dart index 2f85dc445..f49671b22 100644 --- a/lib/pages/settings_views/global_settings_view/currency_view.dart +++ b/lib/pages/settings_views/global_settings_view/currency_view.dart @@ -69,20 +69,14 @@ class _CurrencyViewState extends ConsumerState { BorderRadius? _borderRadius(int index) { if (index == 0 && currenciesWithoutSelected.length == 1) { - return BorderRadius.circular( - Constants.size.circularBorderRadius, - ); + return BorderRadius.circular(Constants.size.circularBorderRadius); } else if (index == 0) { return BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), + top: Radius.circular(Constants.size.circularBorderRadius), ); } else if (index == currenciesWithoutSelected.length - 1) { return BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottom: Radius.circular(Constants.size.circularBorderRadius), ); } return null; @@ -120,14 +114,16 @@ class _CurrencyViewState extends ConsumerState { final isDesktop = Util.isDesktop; if (!isDesktop) { - current = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + current = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); } - currenciesWithoutSelected = ref - .watch(baseCurrenciesProvider.select((value) => value.map)) - .keys - .toList(); + currenciesWithoutSelected = + ref + .watch(baseCurrenciesProvider.select((value) => value.map)) + .keys + .toList(); if (current.isNotEmpty) { currenciesWithoutSelected.remove(current); @@ -157,18 +153,13 @@ class _CurrencyViewState extends ConsumerState { } }, ), - title: Text( - "Currency", - style: STextStyles.navBarTitle(context), - ), + title: Text("Currency", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: child, ), - child: child, ), ), ); @@ -194,9 +185,7 @@ class _CurrencyViewState extends ConsumerState { child: child, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -206,9 +195,7 @@ class _CurrencyViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save changes", @@ -240,8 +227,9 @@ class _CurrencyViewState extends ConsumerState { headerSliverBuilder: (context, innerBoxIsScrolled) { return [ SliverOverlapAbsorber( - handle: - NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), sliver: SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(bottom: 16), @@ -274,26 +262,27 @@ class _CurrencyViewState extends ConsumerState { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - filter = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + filter = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -312,116 +301,110 @@ class _CurrencyViewState extends ConsumerState { ), ), SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, - borderRadius: _borderRadius(index), + delegate: SliverChildBuilderDelegate((context, index) { + return Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: _borderRadius(index), + ), + child: Padding( + padding: const EdgeInsets.all(4), + key: Key( + "currencySelect_${currenciesWithoutSelected[index]}", ), - child: Padding( - padding: const EdgeInsets.all(4), - key: Key( - "currencySelect_${currenciesWithoutSelected[index]}", - ), - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: currenciesWithoutSelected[index] == current - ? Theme.of(context) - .extension()! - .currencyListItemBG - : Theme.of(context) - .extension()! - .popupBG, - child: RawMaterialButton( - onPressed: () async { - onTap(index); - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + currenciesWithoutSelected[index] == current + ? Theme.of(context) + .extension()! + .currencyListItemBG + : Theme.of( + context, + ).extension()!.popupBG, + child: RawMaterialButton( + onPressed: () async { + onTap(index); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - value: true, - groupValue: currenciesWithoutSelected[ - index] == - current, - onChanged: (_) { - onTap(index); - }, - ), - ), - const SizedBox( - width: 12, + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: true, + groupValue: + currenciesWithoutSelected[index] == + current, + onChanged: (_) { + onTap(index); + }, ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - currenciesWithoutSelected[index], - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + currenciesWithoutSelected[index], + key: + (currenciesWithoutSelected[index] == + current) + ? const Key( "selectedCurrencySettingsCurrencyText", ) - : null, - style: STextStyles.largeMedium14( - context, - ), - ), - const SizedBox( - height: 2, + : null, + style: STextStyles.largeMedium14( + context, ), - Text( - ref.watch( - baseCurrenciesProvider.select( - (value) => value.map, - ), - )[currenciesWithoutSelected[ - index]] ?? - "", - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( + ), + const SizedBox(height: 2), + Text( + ref.watch( + baseCurrenciesProvider.select( + (value) => value.map, + ), + )[currenciesWithoutSelected[index]] ?? + "", + key: + (currenciesWithoutSelected[index] == + current) + ? const Key( "selectedCurrencySettingsCurrencyTextDescription", ) - : null, - style: STextStyles.itemSubtitle( - context, - ), + : null, + style: STextStyles.itemSubtitle( + context, ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), ), ), - ); - }, - childCount: currenciesWithoutSelected.length, - ), + ), + ); + }, childCount: currenciesWithoutSelected.length), ), ], ); diff --git a/lib/pages/settings_views/global_settings_view/global_settings_view.dart b/lib/pages/settings_views/global_settings_view/global_settings_view.dart index 082d03429..5dc6d4101 100644 --- a/lib/pages/settings_views/global_settings_view/global_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/global_settings_view.dart @@ -38,9 +38,7 @@ import 'syncing_preferences_views/syncing_preferences_view.dart'; import 'tor_settings/tor_settings_view.dart'; class GlobalSettingsView extends StatelessWidget { - const GlobalSettingsView({ - super.key, - }); + const GlobalSettingsView({super.key}); static const String routeName = "/globalSettings"; @@ -56,271 +54,248 @@ class GlobalSettingsView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("Settings", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (builderContext, 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.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(4), - child: Column( - children: [ - SettingsListButton( - iconAssetName: Assets.svg.addressBook, - iconSize: 16, - title: "Address book", - onPressed: () { - Navigator.of(context) - .pushNamed(AddressBookView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.downloadFolder, - iconSize: 14, - title: "${AppConfig.prefix} backup & restore", - onPressed: () { - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - routeOnSuccess: - StackBackupView.routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to access ${AppConfig.prefix} backup & restore settings", - biometricsAuthenticationTitle: - "${AppConfig.prefix} backup", - ), - settings: const RouteSettings( - name: "/swblockscreen", + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(4), + child: Column( + children: [ + SettingsListButton( + iconAssetName: Assets.svg.addressBook, + iconSize: 16, + title: "Address book", + onPressed: () { + Navigator.of( + context, + ).pushNamed(AddressBookView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.downloadFolder, + iconSize: 14, + title: + "${AppConfig.prefix} backup & restore", + onPressed: () { + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: + StackBackupView.routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to access ${AppConfig.prefix} backup & restore settings", + biometricsAuthenticationTitle: + "${AppConfig.prefix} backup", + ), + settings: const RouteSettings( + name: "/swblockscreen", + ), ), - ), - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.lock, - iconSize: 16, - title: "Security", - onPressed: () { - Navigator.of(context) - .pushNamed(SecurityView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.dollarSign, - iconSize: 18, - title: "Currency", - onPressed: () { - Navigator.of(context).pushNamed( - BaseCurrencySettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.language, - iconSize: 18, - title: "Language", - onPressed: () { - Navigator.of(context).pushNamed( - LanguageSettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.tor, - iconSize: 18, - title: "Tor Settings", - onPressed: () { - Navigator.of(context) - .pushNamed(TorSettingsView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.node, - iconSize: 16, - title: "Manage nodes", - onPressed: () { - Navigator.of(context) - .pushNamed(ManageNodesView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.arrowRotate, - iconSize: 18, - title: "Syncing preferences", - onPressed: () { - Navigator.of(context).pushNamed( - SyncingPreferencesView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.arrowUpRight, - iconSize: 16, - title: "Startup", - onPressed: () { - Navigator.of(context).pushNamed( - StartupPreferencesView.routeName, - ); - }, - ), - if (AppConfig.hasFeature( - AppFeature.themeSelection)) - const SizedBox( - height: 8, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.lock, + iconSize: 16, + title: "Security", + onPressed: () { + Navigator.of( + context, + ).pushNamed(SecurityView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.dollarSign, + iconSize: 18, + title: "Currency", + onPressed: () { + Navigator.of(context).pushNamed( + BaseCurrencySettingsView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.language, + iconSize: 18, + title: "Language", + onPressed: () { + Navigator.of(context).pushNamed( + LanguageSettingsView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.tor, + iconSize: 18, + title: "Tor Settings", + onPressed: () { + Navigator.of( + context, + ).pushNamed(TorSettingsView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.node, + iconSize: 16, + title: "Manage nodes", + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageNodesView.routeName); + }, ), - if (AppConfig.hasFeature( - AppFeature.themeSelection)) + const SizedBox(height: 8), SettingsListButton( - iconAssetName: Assets.svg.sun, + iconAssetName: Assets.svg.arrowRotate, iconSize: 18, - title: "Appearance", + title: "Syncing preferences", onPressed: () { Navigator.of(context).pushNamed( - AppearanceSettingsView.routeName, + SyncingPreferencesView.routeName, ); }, ), - if (Platform.isIOS) - const SizedBox( - height: 8, + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.arrowUpRight, + iconSize: 16, + title: "Startup", + onPressed: () { + Navigator.of(context).pushNamed( + StartupPreferencesView.routeName, + ); + }, + ), + if (AppConfig.hasFeature( + AppFeature.themeSelection, + )) + const SizedBox(height: 8), + if (AppConfig.hasFeature( + AppFeature.themeSelection, + )) + SettingsListButton( + iconAssetName: Assets.svg.sun, + iconSize: 18, + title: "Appearance", + onPressed: () { + Navigator.of(context).pushNamed( + AppearanceSettingsView.routeName, + ); + }, + ), + if (Platform.isIOS) const SizedBox(height: 8), + if (Platform.isIOS) + SettingsListButton( + iconAssetName: Assets.svg.circleAlert, + iconSize: 16, + title: "Delete account", + onPressed: () async { + await Navigator.of(context).pushNamed( + DeleteAccountView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.ellipsis, + iconSize: 18, + title: "About", + onPressed: () { + Navigator.of( + context, + ).pushNamed(AboutView.routeName); + }, ), - if (Platform.isIOS) + const SizedBox(height: 8), SettingsListButton( - iconAssetName: Assets.svg.circleAlert, + iconAssetName: Assets.svg.solidSliders, iconSize: 16, - title: "Delete account", - onPressed: () async { - await Navigator.of(context).pushNamed( - DeleteAccountView.routeName, + title: "Advanced", + onPressed: () { + Navigator.of(context).pushNamed( + AdvancedSettingsView.routeName, ); }, ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.ellipsis, - iconSize: 18, - title: "About", - onPressed: () { - Navigator.of(context) - .pushNamed(AboutView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.solidSliders, - iconSize: 16, - title: "Advanced", - onPressed: () { - Navigator.of(context).pushNamed( - AdvancedSettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.questionMessage, - iconSize: 16, - title: "Support", - onPressed: () { - Navigator.of(context) - .pushNamed(SupportView.routeName); - }, - ), - // TextButton( - // style: Theme.of(context) - // .textButtonTheme - // .style - // ?.copyWith( - // backgroundColor: - // MaterialStateProperty.all( - // Theme.of(context).extension()!.accentColorDark - // ), - // ), - // child: Text( - // "fire test notification", - // style: STextStyles.button(context), - // ), - // onPressed: () async { - // NotificationApi.showNotification2( - // title: "Test notification", - // body: "My doggy wallet", - // walletId: - // "3c5e2d70-fcc3-11ec-86a3-31a106a81c3b", - // iconAssetName: - // Assets.svg.iconFor(coin: Coin.dogecoin), - // date: DateTime.now(), - // ); - // }, - // ), - ], + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.questionMessage, + iconSize: 16, + title: "Support", + onPressed: () { + Navigator.of( + context, + ).pushNamed(SupportView.routeName); + }, + ), + // TextButton( + // style: Theme.of(context) + // .textButtonTheme + // .style + // ?.copyWith( + // backgroundColor: + // MaterialStateProperty.all( + // Theme.of(context).extension()!.accentColorDark + // ), + // ), + // child: Text( + // "fire test notification", + // style: STextStyles.button(context), + // ), + // onPressed: () async { + // NotificationApi.showNotification2( + // title: "Test notification", + // body: "My doggy wallet", + // walletId: + // "3c5e2d70-fcc3-11ec-86a3-31a106a81c3b", + // iconAssetName: + // Assets.svg.iconFor(coin: Coin.dogecoin), + // date: DateTime.now(), + // ); + // }, + // ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - ], + const SizedBox(height: 12), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/hidden_settings.dart b/lib/pages/settings_views/global_settings_view/hidden_settings.dart index 99fb927cb..52b78cbcf 100644 --- a/lib/pages/settings_views/global_settings_view/hidden_settings.dart +++ b/lib/pages/settings_views/global_settings_view/hidden_settings.dart @@ -41,338 +41,344 @@ class HiddenSettings extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: AppBarIconButton( size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: Navigator.of(context).pop, ), ), - title: Text( - "Dev options", - style: STextStyles.navBarTitle(context), - ), + title: Text("Dev options", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - ref - .read(prefsChangeNotifierProvider) - .advancedFiroFeatures = - !ref - .read(prefsChangeNotifierProvider) - .advancedFiroFeatures; - }, - child: RoundedWhiteContainer( - child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (s) => s.advancedFiroFeatures, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Consumer( + builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + ref + .read(prefsChangeNotifierProvider) + .advancedFiroFeatures = !ref + .read(prefsChangeNotifierProvider) + .advancedFiroFeatures; + }, + child: RoundedWhiteContainer( + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (s) => s.advancedFiroFeatures, + ), + ) + ? "Hide advanced Firo features" + : "Show advanced Firo features", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), - ) - ? "Hide advanced Firo features" - : "Show advanced Firo features", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, ), ), - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - final notifs = ref - .read(notificationsProvider) - .notifications; + ); + }, + ), + const SizedBox(height: 12), + 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, + 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()! + .accentColorDark, ), - ); - } - }, - child: RoundedWhiteContainer( - child: Text( - "Delete notifications", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - ref.read(prefsChangeNotifierProvider).logsPath = - null; - }, - child: RoundedWhiteContainer( - child: Text( - "Reset log location", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, ), ), - ), - ); - }, - ), - // const SizedBox( - // height: 12, - // ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // final trades = - // ref.read(tradesServiceProvider).trades; - // - // for (final trade in trades) { - // ref.read(tradesServiceProvider).delete( - // trade: trade, shouldNotifyListeners: false); - // } - // ref.read(tradesServiceProvider).delete( - // trade: trades[0], shouldNotifyListeners: true); - // - // // ref.read(notificationsProvider).DELETE_EVERYTHING(); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Delete trade history", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context).extension()!.accentColorDark - // ), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - // 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( - // color: Theme.of(context) - // .extension()! - // .accentColorDark, - // ), - // ), - // ), - // ); - // }, - // ), - const SizedBox( - height: 12, - ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // await showOneTimeTorHasBeenAddedDialogIfRequired( - // context, - // ); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Test tor stacy popup", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // final box = await Hive.openBox( - // DB.boxNameOneTimeDialogsShown); - // await box.clear(); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Reset tor stacy popup", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - Consumer( - builder: (_, ref, __) { - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.familiarity), - ) < - 6) { + ); + }, + ), + const SizedBox(height: 12), + Consumer( + builder: (_, ref, __) { return GestureDetector( onTap: () async { - final familiarity = ref + ref .read(prefsChangeNotifierProvider) - .familiarity; - if (familiarity < 6) { - ref - .read(prefsChangeNotifierProvider) - .familiarity = 6; - - Constants.exchangeForExperiencedUsers(6); - } + .logsPath = null; }, child: RoundedWhiteContainer( child: Text( - "Enable exchange", + "Reset log location", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), ); - } else { - return Container(); - } - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - await showDialog( - context: context, - builder: (_) => TorWarningDialog( - coin: Stellar(CryptoCurrencyNetwork.main), + }, + ), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // final trades = + // ref.read(tradesServiceProvider).trades; + // + // for (final trade in trades) { + // ref.read(tradesServiceProvider).delete( + // trade: trade, shouldNotifyListeners: false); + // } + // ref.read(tradesServiceProvider).delete( + // trade: trades[0], shouldNotifyListeners: true); + // + // // ref.read(notificationsProvider).DELETE_EVERYTHING(); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Delete trade history", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context).extension()!.accentColorDark + // ), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + // 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( + // color: Theme.of(context) + // .extension()! + // .accentColorDark, + // ), + // ), + // ), + // ); + // }, + // ), + const SizedBox(height: 12), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // await showOneTimeTorHasBeenAddedDialogIfRequired( + // context, + // ); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Test tor stacy popup", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // final box = await Hive.openBox( + // DB.boxNameOneTimeDialogsShown); + // await box.clear(); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Reset tor stacy popup", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + Consumer( + builder: (_, ref, __) { + if (ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.familiarity, + ), + ) < + 6) { + return GestureDetector( + onTap: () async { + final familiarity = + ref + .read(prefsChangeNotifierProvider) + .familiarity; + if (familiarity < 6) { + ref + .read(prefsChangeNotifierProvider) + .familiarity = 6; + + Constants.exchangeForExperiencedUsers(6); + } + }, + child: RoundedWhiteContainer( + child: Text( + "Enable exchange", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), ), ); - }, - child: RoundedWhiteContainer( - child: Text( - "Show Tor warning popup", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + } else { + return Container(); + } + }, + ), + const SizedBox(height: 12), + Consumer( + builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + await showDialog( + context: context, + builder: + (_) => TorWarningDialog( + coin: Stellar( + CryptoCurrencyNetwork.main, + ), + ), + ); + }, + child: RoundedWhiteContainer( + child: Text( + "Show Tor warning popup", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - ); - }, - ), - // const SizedBox( - // height: 12, - // ), - // Consumer( - // builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // await showLoading( - // whileFuture: FiroCache.init(), - // context: context, - // rootNavigator: true, - // message: "initializing firo cache", - // ); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "init firo_cache", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark, - // ), - // ), - // ), - // ); - // }, - // ), - ], + ); + }, + ), + // const SizedBox( + // height: 12, + // ), + // Consumer( + // builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // await showLoading( + // whileFuture: FiroCache.init(), + // context: context, + // rootNavigator: true, + // message: "initializing firo cache", + // ); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "init firo_cache", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark, + // ), + // ), + // ), + // ); + // }, + // ), + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/language_view.dart b/lib/pages/settings_views/global_settings_view/language_view.dart index 8f1ca3012..9490530d5 100644 --- a/lib/pages/settings_views/global_settings_view/language_view.dart +++ b/lib/pages/settings_views/global_settings_view/language_view.dart @@ -59,20 +59,14 @@ class _LanguageViewState extends ConsumerState { BorderRadius? _borderRadius(int index) { if (index == 0 && listWithoutSelected.length == 1) { - return BorderRadius.circular( - Constants.size.circularBorderRadius, - ); + return BorderRadius.circular(Constants.size.circularBorderRadius); } else if (index == 0) { return BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), + top: Radius.circular(Constants.size.circularBorderRadius), ); } else if (index == listWithoutSelected.length - 1) { return BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottom: Radius.circular(Constants.size.circularBorderRadius), ); } return null; @@ -103,8 +97,9 @@ class _LanguageViewState extends ConsumerState { @override Widget build(BuildContext context) { - current = ref - .watch(prefsChangeNotifierProvider.select((value) => value.language)); + current = ref.watch( + prefsChangeNotifierProvider.select((value) => value.language), + ); listWithoutSelected = languages; if (current.isNotEmpty) { @@ -127,101 +122,99 @@ class _LanguageViewState extends ConsumerState { } }, ), - title: Text( - "Language", - style: STextStyles.navBarTitle(context), - ), + title: Text("Language", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: - NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (newString) { - setState(() => filter = newString); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), + sliver: SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (newString) { + setState(() => filter = newString); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - filter = ""; - }); - }, + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + filter = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), ), ), ), - ), - ]; - }, - body: Builder( - builder: (context) { - return CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor( - context, + ]; + }, + body: Builder( + builder: (context) { + return CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), ), - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { + SliverList( + delegate: SliverChildBuilderDelegate((context, index) { return Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: _borderRadius(index), ), child: Padding( @@ -231,13 +224,14 @@ class _LanguageViewState extends ConsumerState { ), child: RoundedContainer( padding: const EdgeInsets.all(0), - color: index == 0 - ? Theme.of(context) - .extension()! - .currencyListItemBG - : Theme.of(context) - .extension()! - .popupBG, + color: + index == 0 + ? Theme.of(context) + .extension()! + .currencyListItemBG + : Theme.of( + context, + ).extension()!.popupBG, child: RawMaterialButton( onPressed: () async { onTap(index); @@ -257,9 +251,10 @@ class _LanguageViewState extends ConsumerState { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: true, groupValue: index == 0, onChanged: (_) { @@ -267,34 +262,32 @@ class _LanguageViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( listWithoutSelected[index], - key: (index == 0) - ? const Key( - "selectedLanguageSettingsLanguageText", - ) - : null, + key: + (index == 0) + ? const Key( + "selectedLanguageSettingsLanguageText", + ) + : null, style: STextStyles.largeMedium14( context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( listWithoutSelected[index], - key: (index == 0) - ? const Key( - "selectedLanguageSettingsLanguageTextDescription", - ) - : null, + key: + (index == 0) + ? const Key( + "selectedLanguageSettingsLanguageTextDescription", + ) + : null, style: STextStyles.itemSubtitle( context, ), @@ -308,13 +301,12 @@ class _LanguageViewState extends ConsumerState { ), ), ); - }, - childCount: listWithoutSelected.length, + }, childCount: listWithoutSelected.length), ), - ), - ], - ); - }, + ], + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 5703db754..61450faad 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -241,7 +241,7 @@ class _AddEditNodeViewState extends ConsumerState { final plainEnabled = formData.netOption == TorPlainNetworkOption.clear || formData.netOption == TorPlainNetworkOption.both; - + final forceNoTor = formData.forceNoTor ?? false; switch (viewType) { @@ -562,27 +562,29 @@ class _AddEditNodeViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - bottom: 12, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 8, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + bottom: 12, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 8, + ), + child: IntrinsicHeight(child: child), ), - child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart index a7756f662..8d8c1bc7b 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart @@ -27,9 +27,7 @@ import '../../../../widgets/rounded_white_container.dart'; import 'coin_nodes_view.dart'; class ManageNodesView extends ConsumerStatefulWidget { - const ManageNodesView({ - super.key, - }); + const ManageNodesView({super.key}); static const String routeName = "/manageNodes"; @@ -43,9 +41,7 @@ class _ManageNodesViewState extends ConsumerState { @override void initState() { _coins = _coins.toList(); - _coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + _coins.removeWhere((e) => e is Firo && e.network.isTestNet); super.initState(); } @@ -60,9 +56,10 @@ class _ManageNodesViewState extends ConsumerState { prefsChangeNotifierProvider.select((value) => value.showTestNetCoins), ); - final coins = showTestNet - ? _coins - : _coins.where((e) => !e.network.isTestNet).toList(); + final coins = + showTestNet + ? _coins + : _coins.where((e) => !e.network.isTestNet).toList(); return Background( child: Scaffold( @@ -73,29 +70,24 @@ class _ManageNodesViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Manage nodes", - style: STextStyles.navBarTitle(context), - ), + title: Text("Manage nodes", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ...coins.map( - (coin) { - final count = ref - .watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin)), - ) - .length; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 12, right: 12), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ...coins.map((coin) { + final count = + ref + .watch( + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodesFor(coin), + ), + ) + .length; return Padding( padding: const EdgeInsets.all(4), @@ -121,17 +113,11 @@ class _ManageNodesViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -151,9 +137,9 @@ class _ManageNodesViewState extends ConsumerState { ), ), ); - }, - ), - ], + }), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 572c7d7a2..414ba8097 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -64,8 +64,10 @@ class _NodeDetailsViewState extends ConsumerState { bool _desktopReadOnly = true; Future _notifyWalletsOfUpdatedNode() async { - final wallets = - ref.read(pWallets).wallets.where((e) => e.info.coin == widget.coin); + final wallets = ref + .read(pWallets) + .wallets + .where((e) => e.info.coin == widget.coin); final prefs = ref.read(prefsChangeNotifierProvider); switch (prefs.syncType) { @@ -110,139 +112,140 @@ class _NodeDetailsViewState extends ConsumerState { final isDesktop = Util.isDesktop; final node = ref.watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodeById(id: nodeId)), + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodeById(id: nodeId), + ), ); final nodesForCoin = ref.watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin)), + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodesFor(coin), + ), ); final canDelete = nodesForCoin.length > 1; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Node details", - style: STextStyles.navBarTitle(context), - ), - actions: [ - // if (!nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix)) - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Node details", + style: STextStyles.navBarTitle(context), ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("nodeDetailsEditNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: - Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.pencil, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + actions: [ + // if (!nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix)) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, ), - onPressed: () { - Navigator.of(context).pushNamed( - AddEditNodeView.routeName, - arguments: Tuple4( - AddEditNodeViewType.edit, - coin, - nodeId, - popRouteName, + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("nodeDetailsEditNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.pencil, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + AddEditNodeView.routeName, + arguments: Tuple4( + AddEditNodeViewType.edit, + coin, + nodeId, + popRouteName, + ), + ); + }, + ), + ), + ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 12, right: 12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 8, + ), + child: IntrinsicHeight(child: child), + ), ), ); }, ), ), ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight - 8), - child: IntrinsicHeight( - child: child, - ), - ), - ), - ); - }, ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( + builder: + (child) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - width: 8, - ), - const AppBarBackButton( - iconSize: 24, - size: 40, + Row( + children: [ + const SizedBox(width: 8), + const AppBarBackButton(iconSize: 24, size: 40), + Text( + "Node details", + style: STextStyles.desktopH3(context), + ), + ], ), - Text( - "Node details", - style: STextStyles.desktopH3(context), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: child, ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - top: 16, - bottom: 32, - ), - child: child, - ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -253,44 +256,35 @@ class _NodeDetailsViewState extends ConsumerState { coin: coin, ), if (!isDesktop) const Spacer(), - if (isDesktop) - const SizedBox( - height: 22, - ), + if (isDesktop) const SizedBox(height: 22), if (isDesktop && canDelete) SizedBox( height: 56, - child: _desktopReadOnly - ? null - : Row( - children: [ - Expanded( - child: DeleteButton( - label: "Delete node", - desktopMed: true, - onPressed: () async { - Navigator.of(context).pop(); + child: + _desktopReadOnly + ? null + : Row( + children: [ + Expanded( + child: DeleteButton( + label: "Delete node", + desktopMed: true, + onPressed: () async { + Navigator.of(context).pop(); - await ref - .read(nodeServiceChangeNotifierProvider) - .delete( - node!.id, - true, - ); - }, + await ref + .read(nodeServiceChangeNotifierProvider) + .delete(node!.id, true); + }, + ), ), - ), - const SizedBox( - width: 16, - ), - const Spacer(), - ], - ), + const SizedBox(width: 16), + const Spacer(), + ], + ), ), if (isDesktop && !_desktopReadOnly && canDelete) - const SizedBox( - height: 45, - ), + const SizedBox(height: 45), Row( children: [ Expanded( @@ -298,9 +292,10 @@ class _NodeDetailsViewState extends ConsumerState { label: "Test connection", buttonHeight: isDesktop ? ButtonHeight.l : null, onPressed: () async { - final node = ref - .read(nodeServiceChangeNotifierProvider) - .getNodeById(id: nodeId)!; + final node = + ref + .read(nodeServiceChangeNotifierProvider) + .getNodeById(id: nodeId)!; final TorPlainNetworkOption netOption; if (ref.read(nodeFormDataProvider).netOption != null) { @@ -312,16 +307,17 @@ class _NodeDetailsViewState extends ConsumerState { ); } - final nodeFormData = NodeFormData() - ..useSSL = node.useSSL - ..trusted = node.trusted - ..name = node.name - ..host = node.host - ..login = node.loginName - ..port = node.port - ..isFailover = node.isFailover - ..netOption = netOption - ..forceNoTor = node.forceNoTor; + final nodeFormData = + NodeFormData() + ..useSSL = node.useSSL + ..trusted = node.trusted + ..name = node.name + ..host = node.host + ..login = node.loginName + ..port = node.port + ..isFailover = node.isFailover + ..netOption = netOption + ..forceNoTor = node.forceNoTor; nodeFormData.password = await node.getPassword( ref.read(secureStoreProvider), ); @@ -359,16 +355,13 @@ class _NodeDetailsViewState extends ConsumerState { }, ), ), - if (isDesktop) - const SizedBox( - width: 16, - ), + if (isDesktop) const SizedBox(width: 16), if (isDesktop) Expanded( child: - // !nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix) - // ? - PrimaryButton( + // !nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix) + // ? + PrimaryButton( label: _desktopReadOnly ? "Edit" : "Save", buttonHeight: ButtonHeight.l, onPressed: () async { @@ -389,15 +382,16 @@ class _NodeDetailsViewState extends ConsumerState { ref.read(nodeFormDataProvider).isFailover, torEnabled: ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.tor || - ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.both, + TorPlainNetworkOption.tor || + ref.read(nodeFormDataProvider).netOption == + TorPlainNetworkOption.both, clearnetEnabled: ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.clear || - ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.both, - forceNoTor: ref.read(nodeFormDataProvider).forceNoTor, + TorPlainNetworkOption.clear || + ref.read(nodeFormDataProvider).netOption == + TorPlainNetworkOption.both, + forceNoTor: + ref.read(nodeFormDataProvider).forceNoTor, ); await ref @@ -410,16 +404,12 @@ class _NodeDetailsViewState extends ConsumerState { await _notifyWalletsOfUpdatedNode(); } }, - ) + ), // : Container() - , ), ], ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart index b5aac24a9..5412189ec 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart @@ -212,211 +212,118 @@ class _SecurityViewState extends ConsumerState { ), title: Text("Security", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: - (_) => const LockscreenView( - showBackButton: true, - routeOnSuccess: ChangePinView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to change PIN", - biometricsAuthenticationTitle: "Change PIN", - ), - settings: const RouteSettings( - name: "/changepinlockscreen", - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, ), - child: Row( - children: [ - Text( - "Change PIN", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - // () { - // final useBio = - // ref.read(prefsChangeNotifierProvider).useBiometrics; - // - // debugPrint("useBio: $useBio"); - // ref.read(prefsChangeNotifierProvider).useBiometrics = - // !useBio; - // - // debugPrint( - // "useBio set to: ${ref.read(prefsChangeNotifierProvider).useBiometrics}"); - // }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Enable biometric authentication", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.useBiometrics, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .useBiometrics = newValue; - }, + onPressed: () { + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: ChangePinView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to change PIN", + biometricsAuthenticationTitle: "Change PIN", ), - ), - ], - ), - ), - ); - }, - ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + settings: const RouteSettings( + name: "/changepinlockscreen", + ), ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Randomize PIN Pad", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.randomizePIN, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .randomizePIN = newValue; - }, - ), - ), - ], - ), + child: Row( + children: [ + Text( + "Change PIN", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], ), - ); - }, + ), + ), ), - ), - // The "autoPin" preference (whether to automatically accept a correct PIN). - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Auto-accept correct PIN", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.autoPin, + onPressed: null, + // () { + // final useBio = + // ref.read(prefsChangeNotifierProvider).useBiometrics; + // + // debugPrint("useBio: $useBio"); + // ref.read(prefsChangeNotifierProvider).useBiometrics = + // !useBio; + // + // debugPrint( + // "useBio set to: ${ref.read(prefsChangeNotifierProvider).useBiometrics}"); + // }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable biometric authentication", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.useBiometrics, + ), ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .useBiometrics = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .autoPin = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - if (!ref.watch(pDuress)) const SizedBox(height: 8), - if (!ref.watch(pDuress)) + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -435,20 +342,24 @@ class _SecurityViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Duress PIN", + "Randomize PIN Pad", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), SizedBox( height: 20, width: 40, - child: DraggableSwitch( - value: ref.watch( + child: DraggableSwitchButton( + isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, + (value) => value.randomizePIN, ), ), - onChanged: _duressToggled, + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .randomizePIN = newValue; + }, ), ), ], @@ -458,19 +369,8 @@ class _SecurityViewState extends ConsumerState { }, ), ), - if (!ref.watch(pDuress) && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, - ), - )) + // The "autoPin" preference (whether to automatically accept a correct PIN). const SizedBox(height: 8), - if (!ref.watch(pDuress) && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, - ), - )) RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -489,23 +389,23 @@ class _SecurityViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Biometrics opens duress", + "Auto-accept correct PIN", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), SizedBox( height: 20, width: 40, - child: DraggableSwitch( - value: ref.watch( + child: DraggableSwitchButton( + isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.biometricsDuress, + (value) => value.autoPin, ), ), - onChanged: (newValue) { + onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .biometricsDuress = newValue; + .autoPin = newValue; }, ), ), @@ -516,7 +416,111 @@ class _SecurityViewState extends ConsumerState { }, ), ), - ], + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Duress PIN", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + ), + onChanged: _duressToggled, + ), + ), + ], + ), + ), + ); + }, + ), + ), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + const SizedBox(height: 8), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Biometrics opens duress", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.biometricsDuress, + ), + ), + onChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .biometricsDuress = newValue; + }, + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart index f41891bb6..57785f5f4 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart @@ -95,9 +95,9 @@ class _AutoBackupViewState extends ConsumerState { title: "Enable Auto Backup", message: "To enable Auto Backup, you need to create a backup file.", leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getSecondaryEnabledButtonStyle(context), child: Text( "Back", style: STextStyles.button(context).copyWith( @@ -110,13 +110,10 @@ class _AutoBackupViewState extends ConsumerState { }, ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Continue", - style: STextStyles.button(context), - ), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + child: Text("Continue", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -126,9 +123,9 @@ class _AutoBackupViewState extends ConsumerState { ); if (mounted) { if (result is bool && result) { - Navigator.of(context) - .pushNamed(CreateAutoBackupView.routeName) - .then((_) { + Navigator.of(context).pushNamed(CreateAutoBackupView.routeName).then(( + _, + ) { // set toggle to correct state if (_toggle != ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled) { @@ -152,9 +149,9 @@ class _AutoBackupViewState extends ConsumerState { message: "You are turning off Auto Backup. You can turn it back on at any time. Your previous Auto Backup file will not be deleted. Remember to backup your wallets manually so you don't lose important information.", leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getSecondaryEnabledButtonStyle(context), child: Text( "Back", style: STextStyles.button(context).copyWith( @@ -167,13 +164,10 @@ class _AutoBackupViewState extends ConsumerState { }, ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Disable", - style: STextStyles.button(context), - ), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + child: Text("Disable", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -184,8 +178,9 @@ class _AutoBackupViewState extends ConsumerState { if (mounted) { if (result is bool && result) { ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled = false; - Navigator.of(context) - .popUntil(ModalRoute.withName(AutoBackupView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(AutoBackupView.routeName)); } else { toggleController.activate?.call(); } @@ -233,11 +228,11 @@ class _AutoBackupViewState extends ConsumerState { ); ref.listen( - prefsChangeNotifierProvider - .select((value) => value.backupFrequencyType), - (previous, BackupFrequencyType next) { - frequencyController.text = Format.prettyFrequencyType(next); - }); + prefsChangeNotifierProvider.select((value) => value.backupFrequencyType), + (previous, BackupFrequencyType next) { + frequencyController.text = Format.prettyFrequencyType(next); + }, + ); return Background( child: Scaffold( @@ -248,232 +243,220 @@ class _AutoBackupViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Auto Backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Auto Backup", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Auto Backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - key: const Key("autoBackupToggleButtonKey"), - isOn: _toggle, - controller: toggleController, - onValueChanged: (newValue) async { - _toggle = newValue; + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Auto Backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + key: const Key("autoBackupToggleButtonKey"), + isOn: _toggle, + controller: toggleController, + onValueChanged: (newValue) async { + _toggle = newValue; - if (_toggle) { - attemptEnable(); - } else { - attemptDisable(); - } - }, + if (_toggle) { + attemptEnable(); + } else { + attemptDisable(); + } + }, + ), ), - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - if (!isEnabledAutoBackup) - RoundedWhiteContainer( - child: RichText( - textAlign: TextAlign.left, - text: TextSpan( - style: STextStyles.label(context), - children: [ - const TextSpan( - text: - "Auto Backup is a custom ${AppConfig.appName} feature that offers a convenient backup of your data.\n\nTo ensure maximum security, we recommend using a unique password that you haven't used anywhere else on the internet before. Your password is not stored.\n\nFor more information, please see our website ", - ), - TextSpan( - text: "stackwallet.com.", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com"), - mode: LaunchMode.externalApplication, - ); - }, - ), - ], + ], + ), ), ), ), - if (isEnabledAutoBackup) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + const SizedBox(height: 8), + if (!isEnabledAutoBackup) + RoundedWhiteContainer( + child: RichText( + textAlign: TextAlign.left, + text: TextSpan( + style: STextStyles.label(context), children: [ - CustomTextButton( - text: "Back up now", - onTap: () { - ref.read(autoSWBServiceProvider).doBackup(); - }, + const TextSpan( + text: + "Auto Backup is a custom ${AppConfig.appName} feature that offers a convenient backup of your data.\n\nTo ensure maximum security, we recommend using a unique password that you haven't used anywhere else on the internet before. Your password is not stored.\n\nFor more information, please see our website ", ), - Text( - "Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}", - style: STextStyles.itemSubtitle(context), + TextSpan( + text: "stackwallet.com.", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse("https://stackwallet.com"), + mode: LaunchMode.externalApplication, + ); + }, ), ], ), ), - const SizedBox( - height: 32, - ), - Text( - "Auto Backup file", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + ), + if (isEnabledAutoBackup) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomTextButton( + text: "Back up now", + onTap: () { + ref.read(autoSWBServiceProvider).doBackup(); + }, + ), + Text( + "Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}", + style: STextStyles.itemSubtitle(context), + ), + ], + ), ), - child: TextField( - key: const Key("backupSavedToFileLocationTextFieldKey"), - focusNode: fileLocationFocusNode, - controller: fileLocationController, - enabled: false, - style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), + const SizedBox(height: 32), + Text( + "Auto Backup file", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - readOnly: true, - enableSuggestions: false, - autocorrect: false, - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: true, + child: TextField( + key: const Key( + "backupSavedToFileLocationTextFieldKey", + ), + focusNode: fileLocationFocusNode, + controller: fileLocationController, + enabled: false, + style: STextStyles.field(context).copyWith( + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.5), + ), + readOnly: true, + enableSuggestions: false, + autocorrect: false, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: true, + ), + decoration: standardInputDecoration( + "Saved to", + fileLocationFocusNode, + context, + ), ), - decoration: standardInputDecoration( - "Saved to", - fileLocationFocusNode, - context, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("backupPasswordFieldKey"), + focusNode: passwordFocusNode, + controller: passwordController, + enabled: false, + style: STextStyles.field(context).copyWith( + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.5), + ), + obscureText: true, + enableSuggestions: false, + autocorrect: false, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: true, + ), + decoration: standardInputDecoration( + "Passphrase", + passwordFocusNode, + context, + ), ), ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 12), + Text( + "Auto Backup frequency", + style: STextStyles.smallMed12(context), ), - child: TextField( - key: const Key("backupPasswordFieldKey"), - focusNode: passwordFocusNode, - controller: passwordController, + const SizedBox(height: 10), + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + key: const Key("backupFrequencyFieldKey"), + controller: frequencyController, enabled: false, style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.textDark.withOpacity(0.5), ), - obscureText: true, - enableSuggestions: false, - autocorrect: false, toolbarOptions: const ToolbarOptions( copy: true, cut: false, paste: false, selectAll: true, ), - decoration: standardInputDecoration( - "Passphrase", - passwordFocusNode, - context, - ), ), - ), - const SizedBox( - height: 12, - ), - Text( - "Auto Backup frequency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - key: const Key("backupFrequencyFieldKey"), - controller: frequencyController, - enabled: false, - style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), - ), - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: true, - ), - ), - const SizedBox( - height: 20, - ), - Center( - child: CustomTextButton( - text: "Edit Auto Backup", - onTap: () async { - Navigator.of(context) - .pushNamed(EditAutoBackupView.routeName); - }, + const SizedBox(height: 20), + Center( + child: CustomTextButton( + text: "Edit Auto Backup", + onTap: () async { + Navigator.of( + context, + ).pushNamed(EditAutoBackupView.routeName); + }, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart index c75ac4a83..5616ccd9d 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart @@ -41,9 +41,7 @@ import 'helpers/swb_file_system.dart'; import 'sub_views/backup_frequency_type_select_sheet.dart'; class CreateAutoBackupView extends ConsumerStatefulWidget { - const CreateAutoBackupView({ - super.key, - }); + const CreateAutoBackupView({super.key}); static const String routeName = "/createAutoBackup"; @@ -134,567 +132,587 @@ class _EnableAutoBackupViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - "Create your backup file", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - if (!Platform.isAndroid && !Platform.isIOS) - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); - } - - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); - } - } catch (e, s) { - Logging.instance - .e("$e\n$s", error: e, stackTrace: s); - } - }, - controller: fileLocationController, - style: STextStyles.field(context), - decoration: InputDecoration( - hintText: "Save to...", - hintStyle: STextStyles.fieldLabel(context), - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - SvgPicture.asset( - Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, - ), - const SizedBox( - width: 12, - ), - ], - ), - ), - ), - key: const Key( - "createBackupSaveToFileLocationTextFieldKey", - ), - readOnly: true, - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: false, - ), - onChanged: (newValue) {}, - ), - if (!Platform.isAndroid && !Platform.isIOS) - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Create your backup file", + style: STextStyles.smallMed12(context), ), - child: TextField( - key: const Key("createBackupPasswordFieldKey1"), - focusNode: passwordFocusNode, - controller: passwordController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Create passphrase", - passwordFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "createBackupPasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); + const SizedBox(height: 10), + if (!Platform.isAndroid && !Platform.isIOS) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem + .prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir( + context, + ); + } + + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e( + "$e\n$s", + error: e, + stackTrace: s, + ); + } }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + controller: fileLocationController, + style: STextStyles.field(context), + decoration: InputDecoration( + hintText: "Save to...", + hintStyle: STextStyles.fieldLabel(context), + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + SvgPicture.asset( + Assets.svg.folder, + color: + Theme.of(context) + .extension()! + .textDark3, width: 16, height: 16, ), - ), - const SizedBox( - width: 12, - ), - ], + const SizedBox(width: 12), + ], + ), ), ), + key: const Key( + "createBackupSaveToFileLocationTextFieldKey", + ), + readOnly: true, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: false, + ), + onChanged: (newValue) {}, + ), + if (!Platform.isAndroid && !Platform.isIOS) + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) { - if (newValue.isEmpty) { + child: TextField( + key: const Key("createBackupPasswordFieldKey1"), + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Create passphrase", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "createBackupPasswordFieldShowPasswordButtonKey", + ), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, + ), + ), + const SizedBox(width: 12), + ], + ), + ), + ), + onChanged: (newValue) { + if (newValue.isEmpty) { + setState(() { + passwordFeedback = ""; + }); + return; + } + final result = zxcvbn.evaluate(newValue); + String suggestionsAndTips = ""; + for (final sug + in result.feedback.suggestions!.toSet()) { + suggestionsAndTips += "$sug\n"; + } + suggestionsAndTips += result.feedback.warning!; + String feedback = + // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" + suggestionsAndTips; + + passwordStrength = result.score! / 4; + + // hack fix to format back string returned from zxcvbn + if (feedback.contains("phrasesNo need")) { + feedback = feedback.replaceFirst( + "phrasesNo need", + "phrases\nNo need", + ); + } + + if (feedback.endsWith("\n")) { + feedback = feedback.substring( + 0, + feedback.length - 2, + ); + } + setState(() { - passwordFeedback = ""; + passwordFeedback = feedback; }); - return; - } - final result = zxcvbn.evaluate(newValue); - String suggestionsAndTips = ""; - for (final sug - in result.feedback.suggestions!.toSet()) { - suggestionsAndTips += "$sug\n"; - } - suggestionsAndTips += result.feedback.warning!; - String feedback = - // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" - suggestionsAndTips; - - passwordStrength = result.score! / 4; - - // hack fix to format back string returned from zxcvbn - if (feedback.contains("phrasesNo need")) { - feedback = feedback.replaceFirst( - "phrasesNo need", - "phrases\nNo need", - ); - } - - if (feedback.endsWith("\n")) { - feedback = - feedback.substring(0, feedback.length - 2); - } - - setState(() { - passwordFeedback = feedback; - }); - }, - ), - ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: EdgeInsets.only( - left: 12, - right: 12, - top: passwordFeedback.isNotEmpty ? 4 : 0, + }, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), - child: ProgressBar( - key: const Key("createStackBackUpProgressBar"), - width: - MediaQuery.of(context).size.width - 32 - 24, - height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context) - .extension()! - .accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, - percent: passwordStrength < 0.25 - ? 0.03 - : passwordStrength, + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: EdgeInsets.only( + left: 12, + right: 12, + top: passwordFeedback.isNotEmpty ? 4 : 0, + ), + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("createBackupPasswordFieldKey2"), - focusNode: passwordRepeatFocusNode, - controller: passwordRepeatController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Confirm passphrase", - passwordRepeatFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "createBackupPasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: const EdgeInsets.only( + left: 12, + right: 12, + top: 10, + ), + child: ProgressBar( + key: const Key("createStackBackUpProgressBar"), + width: + MediaQuery.of(context).size.width - 32 - 24, + height: 5, + fillColor: + passwordStrength < 0.51 + ? Theme.of(context) .extension()! - .textDark3, - width: 16, - height: 16, - ), - ), - const SizedBox( - width: 12, - ), - ], - ), + .accentColorRed + : passwordStrength < 1 + ? Theme.of(context) + .extension()! + .accentColorYellow + : Theme.of(context) + .extension()! + .accentColorGreen, + backgroundColor: + Theme.of(context) + .extension()! + .buttonBackSecondary, + percent: + passwordStrength < 0.25 + ? 0.03 + : passwordStrength, ), ), - onChanged: (newValue) { - setState(() {}); - // TODO: ? check if passwords match? - }, - ), - ), - const SizedBox( - height: 32, - ), - Text( - "Auto Backup frequency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - readOnly: true, - textInputAction: TextInputAction.none, + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - Positioned.fill( - child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - const BackupFrequencyTypeSelectSheet(), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), + child: TextField( + key: const Key("createBackupPasswordFieldKey2"), + focusNode: passwordRepeatFocusNode, + controller: passwordRepeatController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Confirm passphrase", + passwordRepeatFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, children: [ - Text( - Format.prettyFrequencyType( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => - value.backupFrequencyType, - ), - ), + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "createBackupPasswordFieldShowPasswordButtonKey", ), - style: - STextStyles.itemSubtitle12(context), - ), - Padding( - padding: - const EdgeInsets.only(right: 4.0), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, child: SvgPicture.asset( - Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .textSubtitle2, - width: 12, - height: 6, + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, ), ), + const SizedBox(width: 12), ], ), ), ), + onChanged: (newValue) { + setState(() {}); + // TODO: ? check if passwords match? + }, ), - ], - ), - const Spacer(), - const SizedBox( - height: 10, - ), - TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: !shouldEnableCreate - ? null - : () async { - final String pathToSave = - fileLocationController.text; - final String passphrase = - passwordController.text; - final String repeatPassphrase = - passwordRepeatController.text; - - if (pathToSave.isEmpty) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Directory not chosen", - context: context, - ); - return; - } - if (!(await Directory(pathToSave).exists())) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Directory does not exist", - context: context, - ); - return; - } - if (passphrase.isEmpty) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "A passphrase is required", - context: context, - ); - return; - } - if (passphrase != repeatPassphrase) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Passphrase does not match", - context: context, - ); - return; - } - - showDialog( - context: context, - barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Encrypting initial backup", - message: "This shouldn't take long", + ), + const SizedBox(height: 32), + Text( + "Auto Backup frequency", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 10), + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + readOnly: true, + textInputAction: TextInputAction.none, + ), + Positioned.fill( + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - - // make sure the dialog is able to be displayed for at least some time - final fut = Future.delayed( - const Duration(milliseconds: 300), - ); - - String adkString; - int adkVersion; - try { - final adk = - await compute(generateAdk, passphrase); - adkString = - Format.uint8listToString(adk.item2); - adkVersion = adk.item1; - } on Exception catch (e, s) { - final String err = - getErrorMessageFromSWBException(e); - Logging.instance - .e("$err\n$s", error: e, stackTrace: s); - // pop encryption progress dialog - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.warning, - message: err, - context: context, - ); - return; - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - // pop encryption progress dialog - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.warning, - message: "$e", + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => + const BackupFrequencyTypeSelectSheet(), ); - return; - } - - await secureStore.write( - key: "auto_adk_string", - value: adkString, - ); - await secureStore.write( - key: "auto_adk_version_string", - value: adkVersion.toString(), - ); - - final DateTime now = DateTime.now(); - final String fileToSave = - createAutoBackupFilename(pathToSave, now); - - final backup = - await SWB.createStackWalletJSON( - secureStorage: secureStore, - ); - - final bool result = - await SWB.encryptStackWalletWithADK( - fileToSave, - adkString, - jsonEncode(backup), - adkVersion, - ); - - // this future should already be complete unless there was an error encrypting - await Future.wait([fut]); - - if (mounted) { - // pop encryption progress dialog - Navigator.of(context).pop(); - - if (result) { - ref - .read(prefsChangeNotifierProvider) - .autoBackupLocation = pathToSave; - ref - .read(prefsChangeNotifierProvider) - .lastAutoBackup = now; - - ref - .read(prefsChangeNotifierProvider) - .isAutoBackupEnabled = true; + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + Format.prettyFrequencyType( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => + value.backupFrequencyType, + ), + ), + ), + style: STextStyles.itemSubtitle12( + context, + ), + ), + Padding( + padding: const EdgeInsets.only( + right: 4.0, + ), + child: SvgPicture.asset( + Assets.svg.chevronDown, + color: + Theme.of(context) + .extension()! + .textSubtitle2, + width: 12, + height: 6, + ), + ), + ], + ), + ), + ), + ), + ], + ), + const Spacer(), + const SizedBox(height: 10), + TextButton( + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), + onPressed: + !shouldEnableCreate + ? null + : () async { + final String pathToSave = + fileLocationController.text; + final String passphrase = + passwordController.text; + final String repeatPassphrase = + passwordRepeatController.text; + + if (pathToSave.isEmpty) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Directory not chosen", + context: context, + ); + return; + } + if (!(await Directory( + pathToSave, + ).exists())) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Directory does not exist", + context: context, + ); + return; + } + if (passphrase.isEmpty) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "A passphrase is required", + context: context, + ); + return; + } + if (passphrase != repeatPassphrase) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Passphrase does not match", + context: context, + ); + return; + } - await showDialog( + showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: - "${AppConfig.prefix} Auto Backup enabled and saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: - "${AppConfig.prefix} Auto Backup enabled!", - ), + builder: + (_) => const StackDialog( + title: + "Encrypting initial backup", + message: + "This shouldn't take long", + ), ); - if (mounted) { - passwordController.text = ""; - passwordRepeatController.text = ""; - Navigator.of(context).popUntil( - ModalRoute.withName( - AutoBackupView.routeName, - ), + // make sure the dialog is able to be displayed for at least some time + final fut = Future.delayed( + const Duration(milliseconds: 300), + ); + + String adkString; + int adkVersion; + try { + final adk = await compute( + generateAdk, + passphrase, + ); + adkString = Format.uint8listToString( + adk.item2, + ); + adkVersion = adk.item1; + } on Exception catch (e, s) { + final String err = + getErrorMessageFromSWBException(e); + Logging.instance.e( + "$err\n$s", + error: e, + stackTrace: s, + ); + // pop encryption progress dialog + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.warning, + message: err, + context: context, ); + return; + } catch (e, s) { + Logging.instance.e( + "", + error: e, + stackTrace: s, + ); + // pop encryption progress dialog + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.warning, + message: "$e", + context: context, + ); + return; } - } else { - await showDialog( - context: context, - barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Failed to enable Auto Backup", - ), + + await secureStore.write( + key: "auto_adk_string", + value: adkString, + ); + await secureStore.write( + key: "auto_adk_version_string", + value: adkVersion.toString(), ); - } - } - }, - child: Text( - "Enable Auto Backup", - style: STextStyles.button(context), + + final DateTime now = DateTime.now(); + final String fileToSave = + createAutoBackupFilename( + pathToSave, + now, + ); + + final backup = await SWB + .createStackWalletJSON( + secureStorage: secureStore, + ); + + final bool result = await SWB + .encryptStackWalletWithADK( + fileToSave, + adkString, + jsonEncode(backup), + adkVersion, + ); + + // this future should already be complete unless there was an error encrypting + await Future.wait([fut]); + + if (mounted) { + // pop encryption progress dialog + Navigator.of(context).pop(); + + if (result) { + ref + .read(prefsChangeNotifierProvider) + .autoBackupLocation = pathToSave; + ref + .read(prefsChangeNotifierProvider) + .lastAutoBackup = now; + + ref + .read(prefsChangeNotifierProvider) + .isAutoBackupEnabled = true; + + await showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: + "${AppConfig.prefix} Auto Backup enabled and saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: + "${AppConfig.prefix} Auto Backup enabled!", + ), + ); + if (mounted) { + passwordController.text = ""; + passwordRepeatController.text = ""; + + Navigator.of(context).popUntil( + ModalRoute.withName( + AutoBackupView.routeName, + ), + ); + } + } else { + await showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => const StackOkDialog( + title: + "Failed to enable Auto Backup", + ), + ); + } + } + }, + child: Text( + "Enable Auto Backup", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart index 8b1c72ebd..3088b69ac 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart @@ -9,12 +9,13 @@ */ import 'package:flutter/material.dart'; -import 'create_backup_view.dart'; + import '../../../../themes/stack_colors.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/rounded_white_container.dart'; +import 'create_backup_view.dart'; class CreateBackupInfoView extends StatelessWidget { const CreateBackupInfoView({super.key}); @@ -36,63 +37,59 @@ class CreateBackupInfoView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Create backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Create backup", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - "Info", - style: STextStyles.pageTitleH2(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + "Info", + style: STextStyles.pageTitleH2(context), + ), ), - ), - const SizedBox( - height: 16, - ), - RoundedWhiteContainer( - child: Text( - // TODO: need info - "{lorem ipsum}", - style: STextStyles.baseXS(context), + const SizedBox(height: 16), + RoundedWhiteContainer( + child: Text( + // TODO: need info + "{lorem ipsum}", + style: STextStyles.baseXS(context), + ), ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.of(context) - .pushNamed(CreateBackupView.routeName); - }, - child: Text( - "Next", - style: STextStyles.button(context), + const SizedBox(height: 16), + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.of( + context, + ).pushNamed(CreateBackupView.routeName); + }, + child: Text( + "Next", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart index 944847a42..a04f0de24 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart @@ -138,21 +138,21 @@ class _RestoreFromFileViewState extends State { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -168,8 +168,9 @@ class _RestoreFromFileViewState extends State { padding: const EdgeInsets.only(bottom: 10), child: Text( "Choose file location", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -190,30 +191,31 @@ class _RestoreFromFileViewState extends State { child: TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); - } + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem.prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir(context); + } - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e( + "", + error: e, + stackTrace: s, + ); } - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - } - }, + }, controller: fileLocationController, style: STextStyles.field(context), decoration: InputDecoration( @@ -222,26 +224,24 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), ), key: const Key( - "createBackupSaveToFileLocationTextFieldKey"), + "createBackupSaveToFileLocationTextFieldKey", + ), readOnly: true, toolbarOptions: const ToolbarOptions( copy: true, @@ -257,16 +257,15 @@ class _RestoreFromFileViewState extends State { }, ), if (!Platform.isAndroid && !Platform.isIOS) - SizedBox( - height: !isDesktop ? 8 : 24, - ), + SizedBox(height: !isDesktop ? 8 : 24), if (isDesktop) Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Create a passphrase", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -295,9 +294,7 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -309,16 +306,15 @@ class _RestoreFromFileViewState extends State { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -369,46 +365,43 @@ class _RestoreFromFileViewState extends State { right: 12, top: passwordFeedback.isNotEmpty ? 4 : 0, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), if (passwordFocusNode.hasFocus || passwordRepeatFocusNode.hasFocus || passwordController.text.isNotEmpty) Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), + padding: const EdgeInsets.only(left: 12, right: 12, top: 10), child: ProgressBar( key: const Key("createStackBackUpProgressBar"), width: MediaQuery.of(context).size.width - 32 - 24, height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context) - .extension()! - .accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, + fillColor: + passwordStrength < 0.51 + ? Theme.of( + context, + ).extension()!.accentColorRed + : passwordStrength < 1 + ? Theme.of( + context, + ).extension()!.accentColorYellow + : Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.buttonBackSecondary, percent: passwordStrength < 0.25 ? 0.03 : passwordStrength, ), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -431,9 +424,7 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -445,16 +436,15 @@ class _RestoreFromFileViewState extends State { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -465,24 +455,24 @@ class _RestoreFromFileViewState extends State { }, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (!isDesktop) const Spacer(), !isDesktop ? Consumer( - builder: (context, ref, __) { - return TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: !shouldEnableCreate - ? null - : () async { + builder: (context, ref, __) { + return TextButton( + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), + onPressed: + !shouldEnableCreate + ? null + : () async { final String pathToSave = fileLocationController.text; final String passphrase = @@ -535,10 +525,11 @@ class _RestoreFromFileViewState extends State { showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Encrypting backup", - message: "This shouldn't take long", - ), + builder: + (_) => const StackDialog( + title: "Encrypting backup", + message: "This shouldn't take long", + ), ), ); // make sure the dialog is able to be displayed for at least 1 second @@ -554,12 +545,12 @@ class _RestoreFromFileViewState extends State { secureStorage: ref.read(secureStoreProvider), ); - final bool result = - await SWB.encryptStackWalletWithPassphrase( - fileToSave, - passphrase, - jsonEncode(backup), - ); + final bool result = await SWB + .encryptStackWalletWithPassphrase( + fileToSave, + passphrase, + jsonEncode(backup), + ); if (mounted) { // pop encryption progress dialog @@ -569,15 +560,17 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: "Backup saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: - "Backup creation succeeded", - ), + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: "Backup saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: + "Backup creation succeeded", + ), ); passwordController.text = ""; passwordRepeatController.text = ""; @@ -586,32 +579,34 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Backup creation failed", - ), + builder: + (_) => const StackOkDialog( + title: "Backup creation failed", + ), ); } } }, - child: Text( - "Create backup", - style: STextStyles.button(context), - ), - ); - }, - ) + child: Text( + "Create backup", + style: STextStyles.button(context), + ), + ); + }, + ) : Row( - children: [ - Consumer( - builder: (context, ref, __) { - return PrimaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Create backup", - enabled: shouldEnableCreate, - onPressed: !shouldEnableCreate - ? null - : () async { + children: [ + Consumer( + builder: (context, ref, __) { + return PrimaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Create backup", + enabled: shouldEnableCreate, + onPressed: + !shouldEnableCreate + ? null + : () async { final String pathToSave = fileLocationController.text; final String passphrase = @@ -629,8 +624,9 @@ class _RestoreFromFileViewState extends State { ); return; } - if (!(await Directory(pathToSave) - .exists())) { + if (!(await Directory( + pathToSave, + ).exists())) { unawaited( showFloatingFlushBar( type: FlushBarType.warning, @@ -684,18 +680,16 @@ class _RestoreFromFileViewState extends State { "Encrypting initial backup", style: STextStyles.desktopH3( - context, - ), - ), - const SizedBox( - height: 40, + context, + ), ), + const SizedBox(height: 40), Text( "This shouldn't take long", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ), @@ -726,18 +720,19 @@ class _RestoreFromFileViewState extends State { final String fileToSave = "$pathToSave/stackbackup_${now.year}_${now.month}_${now.day}_${now.hour}_${now.minute}_${now.second}.swb"; - final backup = - await SWB.createStackWalletJSON( - secureStorage: - ref.read(secureStoreProvider), - ); + final backup = await SWB + .createStackWalletJSON( + secureStorage: ref.read( + secureStoreProvider, + ), + ); final bool result = await SWB .encryptStackWalletWithPassphrase( - fileToSave, - passphrase, - jsonEncode(backup), - ); + fileToSave, + passphrase, + jsonEncode(backup), + ); await Future.wait([fut]); @@ -763,10 +758,10 @@ class _RestoreFromFileViewState extends State { child: Padding( padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), + left: 32, + right: 32, + bottom: 32, + ), child: Column( mainAxisSize: MainAxisSize.min, @@ -779,15 +774,17 @@ class _RestoreFromFileViewState extends State { ), Text( "${AppConfig.prefix} backup saved to: \n", - style: STextStyles - .desktopH3(context), + style: + STextStyles.desktopH3( + context, + ), ), Text( fileToSave, - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), const SizedBox( height: 40, @@ -796,8 +793,7 @@ class _RestoreFromFileViewState extends State { children: [ // const Spacer(), Expanded( - child: - PrimaryButton( + child: PrimaryButton( label: "Ok", buttonHeight: ButtonHeight @@ -835,27 +831,26 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Backup creation failed", - ), + builder: + (_) => const StackOkDialog( + title: "Backup creation failed", + ), ); } } }, - ); - }, - ), - const SizedBox( - width: 16, - ), - SecondaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Cancel", - onPressed: () {}, - ), - ], - ), + ); + }, + ), + const SizedBox(width: 16), + SecondaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Cancel", + onPressed: () {}, + ), + ], + ), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart index 53669d9f0..5ad7eab46 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart @@ -47,9 +47,7 @@ import 'helpers/swb_file_system.dart'; import 'sub_views/backup_frequency_type_select_sheet.dart'; class EditAutoBackupView extends ConsumerStatefulWidget { - const EditAutoBackupView({ - super.key, - }); + const EditAutoBackupView({super.key}); static const String routeName = "/editAutoBackup"; @@ -142,10 +140,11 @@ class _EditAutoBackupViewState extends ConsumerState { showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Updating Auto Backup", - message: "This shouldn't take long", - ), + builder: + (_) => const StackDialog( + title: "Updating Auto Backup", + message: "This shouldn't take long", + ), ), ); // make sure the dialog is able to be displayed for at least 1 second @@ -220,29 +219,33 @@ class _EditAutoBackupViewState extends ConsumerState { await showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: "${AppConfig.prefix} Auto Backup saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: "${AppConfig.prefix} Auto Backup saved"), + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: "${AppConfig.prefix} Auto Backup saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: "${AppConfig.prefix} Auto Backup saved", + ), ); if (mounted) { passwordController.text = ""; passwordRepeatController.text = ""; if (!Util.isDesktop) { - Navigator.of(context) - .popUntil(ModalRoute.withName(AutoBackupView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(AutoBackupView.routeName)); } } } else { await showDialog( context: context, barrierDismissible: false, - builder: (_) => - const StackOkDialog(title: "Failed to update Auto Backup"), + builder: + (_) => const StackOkDialog(title: "Failed to update Auto Backup"), ); } } @@ -299,49 +302,47 @@ class _EditAutoBackupViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Edit Auto Backup", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Edit Auto Backup", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ); + }, ), - ); - }, + ), + ), ), ), - ), - ), child: Column( crossAxisAlignment: isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.stretch, children: [ if (!isDesktop) - Text( - "Create your backup", - style: STextStyles.smallMed12(context), - ), + Text("Create your backup", style: STextStyles.smallMed12(context)), if (isDesktop) Text( "Choose file location", @@ -350,33 +351,32 @@ class _EditAutoBackupViewState extends ConsumerState { ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (!Platform.isAndroid && !Platform.isIOS) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem.prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir(context); + } + + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e("$e\n$s", error: e, stackTrace: s); } - - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); - } - } catch (e, s) { - Logging.instance.e("$e\n$s", error: e, stackTrace: s); - } - }, + }, controller: fileLocationController, style: STextStyles.field(context), decoration: InputDecoration( @@ -385,20 +385,17 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -413,10 +410,7 @@ class _EditAutoBackupViewState extends ConsumerState { ), onChanged: (newValue) {}, ), - if (isDesktop) - const SizedBox( - height: 24, - ), + if (isDesktop) const SizedBox(height: 24), if (isDesktop) Text( "Create a passphrase", @@ -426,9 +420,7 @@ class _EditAutoBackupViewState extends ConsumerState { textAlign: TextAlign.left, ), if (!Platform.isAndroid && !Platform.isIOS) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -450,9 +442,7 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -464,16 +454,15 @@ class _EditAutoBackupViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -524,46 +513,46 @@ class _EditAutoBackupViewState extends ConsumerState { right: 12, top: passwordFeedback.isNotEmpty ? 4 : 0, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), if (passwordFocusNode.hasFocus || passwordRepeatFocusNode.hasFocus || passwordController.text.isNotEmpty) Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), + padding: const EdgeInsets.only(left: 12, right: 12, top: 10), child: ProgressBar( key: const Key("createStackBackUpProgressBar"), - width: isDesktop - ? 492 - : MediaQuery.of(context).size.width - 32 - 24, + width: + isDesktop + ? 492 + : MediaQuery.of(context).size.width - 32 - 24, height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context).extension()!.accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, + fillColor: + passwordStrength < 0.51 + ? Theme.of( + context, + ).extension()!.accentColorRed + : passwordStrength < 1 + ? Theme.of( + context, + ).extension()!.accentColorYellow + : Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.buttonBackSecondary, percent: passwordStrength < 0.25 ? 0.03 : passwordStrength, ), ), - SizedBox( - height: isDesktop ? 16 : 10, - ), + SizedBox(height: isDesktop ? 16 : 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -585,9 +574,7 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -599,16 +586,15 @@ class _EditAutoBackupViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -619,52 +605,46 @@ class _EditAutoBackupViewState extends ConsumerState { }, ), ), - SizedBox( - height: isDesktop ? 24 : 32, - ), + SizedBox(height: isDesktop ? 24 : 32), Text( "Auto Backup frequency", - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), ), + const SizedBox(height: 10), if (isDesktop) DropdownButtonHideUnderline( child: DropdownButton2( isExpanded: true, value: _currentDropDownValue, items: [ - ..._dropDownItems.map( - (e) { - String message = ""; - switch (e) { - case BackupFrequencyType.everyTenMinutes: - message = "Every 10 minutes"; - break; - case BackupFrequencyType.everyAppStart: - message = "Every app startup"; - break; - case BackupFrequencyType.afterClosingAWallet: - message = "After closing a cryptocurrency wallet"; - break; - } - - return DropdownMenuItem( - value: e, - child: Text( - message, - style: - STextStyles.desktopTextExtraExtraSmall(context), - ), - ); - }, - ), + ..._dropDownItems.map((e) { + String message = ""; + switch (e) { + case BackupFrequencyType.everyTenMinutes: + message = "Every 10 minutes"; + break; + case BackupFrequencyType.everyAppStart: + message = "Every app startup"; + break; + case BackupFrequencyType.afterClosingAWallet: + message = "After closing a cryptocurrency wallet"; + break; + } + + return DropdownMenuItem( + value: e, + child: Text( + message, + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ); + }), ], onChanged: (value) { if (value is BackupFrequencyType) { @@ -694,19 +674,17 @@ class _EditAutoBackupViewState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), ), ), @@ -759,9 +737,10 @@ class _EditAutoBackupViewState extends ConsumerState { padding: const EdgeInsets.only(right: 4.0), child: SvgPicture.asset( Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, width: 12, height: 6, ), @@ -774,9 +753,7 @@ class _EditAutoBackupViewState extends ConsumerState { ], ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 24 : 10, - ), + SizedBox(height: isDesktop ? 24 : 10), if (isDesktop) Row( children: [ @@ -787,9 +764,7 @@ class _EditAutoBackupViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -802,18 +777,16 @@ class _EditAutoBackupViewState extends ConsumerState { ), if (!isDesktop) TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), onPressed: !shouldEnableCreate ? null : onSavePressed, - child: Text( - "Save", - style: STextStyles.button(context), - ), + child: Text("Save", style: STextStyles.button(context)), ), ], ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart index 9eff26a7e..5aded8ec6 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart @@ -30,10 +30,7 @@ import 'helpers/restore_create_backup.dart'; import 'sub_views/stack_restore_progress_view.dart'; class RestoreFromEncryptedStringView extends ConsumerStatefulWidget { - const RestoreFromEncryptedStringView({ - super.key, - required this.encrypted, - }); + const RestoreFromEncryptedStringView({super.key, required this.encrypted}); static const String routeName = "/restoreFromEncryptedString"; @@ -95,189 +92,197 @@ class _RestoreFromEncryptedStringViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("restoreFromFilePasswordFieldKey"), - focusNode: passwordFocusNode, - controller: passwordController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Enter password", - passwordFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "restoreFromFilePasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "restoreFromFilePasswordFieldKey", + ), + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Enter password", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "restoreFromFilePasswordFieldShowPasswordButtonKey", + ), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, + ), ), - ), - const SizedBox( - width: 12, - ), - ], + const SizedBox(width: 12), + ], + ), ), ), + onChanged: (newValue) { + setState(() {}); + }, ), - onChanged: (newValue) { - setState(() {}); - }, ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - TextButton( - style: passwordController.text.isEmpty - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: passwordController.text.isEmpty - ? null - : () async { - final String passphrase = - passwordController.text; + const SizedBox(height: 16), + const Spacer(), + TextButton( + style: + passwordController.text.isEmpty + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + onPressed: + passwordController.text.isEmpty + ? null + : () async { + final String passphrase = + passwordController.text; - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } - bool shouldPop = false; - showDialog( - barrierDismissible: false, - context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: - STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, - ), + bool shouldPop = false; + showDialog( + barrierDismissible: false, + context: context, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textWhite, + ), + ), + ), + ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator( + width: 100, + ), + ), + ], ), ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), - ), - ], - ), - ), - ); + ); - final String? jsonString = await compute( - SWB.decryptStackWalletStringWithPassphrase, - Tuple2(widget.encrypted, passphrase), - debugLabel: - "stack wallet decryption compute", - ); + final String? + jsonString = await compute( + SWB.decryptStackWalletStringWithPassphrase, + Tuple2(widget.encrypted, passphrase), + debugLabel: + "stack wallet decryption compute", + ); - if (mounted) { - // pop LoadingIndicator - shouldPop = true; - Navigator.of(context).pop(); + if (mounted) { + // pop LoadingIndicator + shouldPop = true; + Navigator.of(context).pop(); - passwordController.text = ""; + passwordController.text = ""; - if (jsonString == null) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: - "Failed to decrypt backup file", - context: context, - ); - return; - } + if (jsonString == null) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: + "Failed to decrypt backup file", + context: context, + ); + return; + } - Navigator.of(context).push( - RouteGenerator.getRoute( - builder: (_) => - StackRestoreProgressView( - jsonString: jsonString, - fromFile: true, - ), - ), - ); - } - }, - child: Text( - "Restore", - style: STextStyles.button(context), + Navigator.of(context).push( + RouteGenerator.getRoute( + builder: + (_) => + StackRestoreProgressView( + jsonString: jsonString, + fromFile: true, + ), + ), + ); + } + }, + child: Text( + "Restore", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart index 400e6e08d..d0ce73db1 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart @@ -110,21 +110,21 @@ class _RestoreFromFileViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -140,8 +140,9 @@ class _RestoreFromFileViewState extends ConsumerState { padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Choose file location", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -183,20 +184,17 @@ class _RestoreFromFileViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -211,16 +209,15 @@ class _RestoreFromFileViewState extends ConsumerState { ), onChanged: (newValue) {}, ), - SizedBox( - height: !isDesktop ? 8 : 24, - ), + SizedBox(height: !isDesktop ? 8 : 24), if (isDesktop) Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Enter passphrase", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -249,9 +246,7 @@ class _RestoreFromFileViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "restoreFromFilePasswordFieldShowPasswordButtonKey", @@ -263,16 +258,15 @@ class _RestoreFromFileViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -282,24 +276,24 @@ class _RestoreFromFileViewState extends ConsumerState { }, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (!isDesktop) const Spacer(), !isDesktop ? TextButton( - style: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? null - : () async { + style: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? null + : () async { final String fileToRestore = fileLocationController.text; final String passphrase = passwordController.text; @@ -325,41 +319,42 @@ class _RestoreFromFileViewState extends ConsumerState { showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator(width: 100), + ), + ], ), - ], - ), - ), + ), ), ); @@ -387,31 +382,31 @@ class _RestoreFromFileViewState extends ConsumerState { await Navigator.of(context).push( RouteGenerator.getRoute( - builder: (_) => StackRestoreProgressView( - jsonString: jsonString, - shouldPushToHome: true, - ), + builder: + (_) => StackRestoreProgressView( + jsonString: jsonString, + shouldPushToHome: true, + ), ), ); } }, - child: Text( - "Restore", - style: STextStyles.button(context), - ), - ) + child: Text("Restore", style: STextStyles.button(context)), + ) : Row( - children: [ - PrimaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Restore", - enabled: !(passwordController.text.isEmpty || - fileLocationController.text.isEmpty), - onPressed: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? null - : () async { + children: [ + PrimaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Restore", + enabled: + !(passwordController.text.isEmpty || + fileLocationController.text.isEmpty), + onPressed: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? null + : () async { final String fileToRestore = fileLocationController.text; final String passphrase = @@ -438,42 +433,45 @@ class _RestoreFromFileViewState extends ConsumerState { showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: + STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator( + width: 100, + ), + ), + ], ), - ], - ), - ), + ), ), ); @@ -530,16 +528,15 @@ class _RestoreFromFileViewState extends ConsumerState { children: [ Padding( padding: - const EdgeInsets - .all( - 32, - ), + const EdgeInsets.all( + 32, + ), child: Text( "Restore ${AppConfig.appName}", - style: STextStyles - .desktopH3( - context, - ), + style: + STextStyles.desktopH3( + context, + ), textAlign: TextAlign .center, @@ -550,15 +547,14 @@ class _RestoreFromFileViewState extends ConsumerState { ), Padding( padding: - const EdgeInsets - .symmetric( - horizontal: 32, - ), + const EdgeInsets.symmetric( + horizontal: 32, + ), child: StackRestoreProgressView( - jsonString: - jsonString, - ), + jsonString: + jsonString, + ), ), const SizedBox( height: 32, @@ -575,18 +571,16 @@ class _RestoreFromFileViewState extends ConsumerState { ); } }, - ), - const SizedBox( - width: 16, - ), - SecondaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Cancel", - onPressed: () {}, - ), - ], - ), + ), + const SizedBox(width: 16), + SecondaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Cancel", + onPressed: () {}, + ), + ], + ), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart index da5c0f411..1bb9d1995 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart @@ -24,9 +24,7 @@ import 'create_backup_view.dart'; import 'restore_from_file_view.dart'; class StackBackupView extends StatelessWidget { - const StackBackupView({ - super.key, - }); + const StackBackupView({super.key}); static const String routeName = "/stackBackup"; @@ -48,134 +46,129 @@ class StackBackupView extends StatelessWidget { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context).pushNamed(AutoBackupView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, - ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupAuto, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Auto Backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of(context).pushNamed(AutoBackupView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupAuto, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Auto Backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed(CreateBackupView.routeName); - // .pushNamed(CreateBackupInfoView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupAdd, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Create manual backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(CreateBackupView.routeName); + // .pushNamed(CreateBackupInfoView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupAdd, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Create manual backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(RestoreFromFileView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupRestore, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Restore backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(RestoreFromFileView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupRestore, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Restore backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart index dd1478b4a..dfd819506 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart @@ -8,16 +8,19 @@ * */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../../../notifications/show_flush_bar.dart'; -import '../../../../add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../utilities/assets.dart'; import '../../../../../utilities/clipboard_interface.dart'; import '../../../../../utilities/text_styles.dart'; import '../../../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../../add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart'; class RecoverPhraseView extends StatelessWidget { const RecoverPhraseView({ @@ -52,19 +55,18 @@ class RecoverPhraseView extends StatelessWidget { child: AppBarIconButton( color: Theme.of(context).extension()!.background, shadows: const [], - icon: SvgPicture.asset( - Assets.svg.copy, - width: 20, - height: 20, - ), + icon: SvgPicture.asset(Assets.svg.copy, width: 20, height: 20), onPressed: () async { - await clipboardInterface - .setData(ClipboardData(text: mnemonic.join(" "))); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, + await clipboardInterface.setData( + ClipboardData(text: mnemonic.join(" ")), + ); + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ), ); }, ), @@ -72,41 +74,32 @@ class RecoverPhraseView extends StatelessWidget { ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 4, - ), - Text( - walletName, - textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 4), + Text( + walletName, + textAlign: TextAlign.center, + style: STextStyles.label(context).copyWith(fontSize: 12), ), - ), - const SizedBox( - height: 4, - ), - Text( - "Recovery Phrase", - textAlign: TextAlign.center, - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 12, - ), - Expanded( - child: SingleChildScrollView( - child: MnemonicTable( - words: mnemonic, - isDesktop: false, + const SizedBox(height: 4), + Text( + "Recovery Phrase", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 12), + Expanded( + child: SingleChildScrollView( + child: MnemonicTable(words: mnemonic, isDesktop: false), ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart index 2c7ddd71e..7b71dc8c6 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart @@ -69,37 +69,34 @@ class _StackRestoreProgressViewState showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Cancelling restore. Please wait.", - style: STextStyles.pageTitleH2(context).copyWith( - color: - Theme.of(context).extension()!.textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Cancelling restore. Please wait.", + style: STextStyles.pageTitleH2(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, + const SizedBox(height: 64), + const Center(child: LoadingIndicator(width: 100)), + ], ), - const Center( - child: LoadingIndicator( - width: 100, - ), - ), - ], - ), - ), + ), ), ); @@ -111,12 +108,12 @@ class _StackRestoreProgressViewState if (mounted) { !isDesktop ? Navigator.of(context).popUntil( - ModalRoute.withName( - widget.fromFile - ? RestoreFromEncryptedStringView.routeName - : StackBackupView.routeName, - ), - ) + ModalRoute.withName( + widget.fromFile + ? RestoreFromEncryptedStringView.routeName + : StackBackupView.routeName, + ), + ) : Navigator.of(context).popUntil((_) => count++ >= 2); } } @@ -169,7 +166,7 @@ class _StackRestoreProgressViewState ref.read(secureStoreProvider), ); } catch (e, s) { - Logging.instance.w("$e\n$s", error: e, stackTrace: s,); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); } if (finished != null && finished && uiState.done) { @@ -224,7 +221,9 @@ class _StackRestoreProgressViewState } void _addWalletsToHomeView() { - ref.read(pWallets).loadAfterStackRestore( + ref + .read(pWallets) + .loadAfterStackRestore( ref.read(prefsChangeNotifierProvider), ref.read(stackRestoringUIStateProvider).wallets, Util.isDesktop, @@ -277,59 +276,95 @@ class _StackRestoreProgressViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), - child: child, ), ), ); }, child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.only( - left: 4, - top: 4, - right: 4, - bottom: 4, - ), + padding: const EdgeInsets.only(left: 4, top: 4, right: 4, bottom: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Settings", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 12, - ), + Text("Settings", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.preferences), + stackRestoringUIStateProvider.select( + (value) => value.preferences, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.gear, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Preferences", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.gear, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -340,84 +375,88 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Preferences", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.gear, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Preferences", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.addressBook), + stackRestoringUIStateProvider.select( + (value) => value.addressBook, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: AddressBookIcon( + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Address book", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: AddressBookIcon( width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -428,84 +467,90 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Address book", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: AddressBookIcon( - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Address book", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.nodes), + stackRestoringUIStateProvider.select( + (value) => value.nodes, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.node, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Nodes", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.node, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -516,85 +561,90 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Nodes", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.node, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Nodes", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.trades), + stackRestoringUIStateProvider.select( + (value) => value.trades, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.arrowsTwoWay, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Exchange history", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.arrowsTwoWay, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -605,123 +655,72 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Exchange history", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.arrowsTwoWay, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Exchange history", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 16, - ), - Text( - "Wallets", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 16), + Text("Wallets", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 8), ...ref .watch( - stackRestoringUIStateProvider - .select((value) => value.walletStateProviders), + stackRestoringUIStateProvider.select( + (value) => value.walletStateProviders, + ), ) .values .map( (provider) => Padding( padding: const EdgeInsets.symmetric(vertical: 4), - child: RestoringWalletCard( - provider: provider, - ), + child: RestoringWalletCard(provider: provider), ), ), - const SizedBox( - height: 30, - ), + const SizedBox(height: 30), SizedBox( width: MediaQuery.of(context).size.width - 32, - child: !isDesktop - ? TextButton( - onPressed: () async { - if (_success) { - if (widget.shouldPushToHome) { - Navigator.of(context).popUntil( - ModalRoute.withName( - HomeView.routeName, - ), - ); + child: + !isDesktop + ? TextButton( + onPressed: () async { + if (_success) { + if (widget.shouldPushToHome) { + Navigator.of(context).popUntil( + ModalRoute.withName(HomeView.routeName), + ); + } else { + Navigator.of(context).pop(); + } } else { - Navigator.of(context).pop(); - } - } else { - if (await _requestCancel()) { - await _cancel(); + if (await _requestCancel()) { + await _cancel(); + } } - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - _success ? "OK" : "Cancel restore process", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + _success ? "OK" : "Cancel restore process", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.buttonTextPrimary, + ), ), - ), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - _success - ? PrimaryButton( + ) + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _success + ? PrimaryButton( width: 248, buttonHeight: ButtonHeight.l, enabled: true, @@ -738,15 +737,18 @@ class _StackRestoreProgressViewState if (widget.shouldPushToHome) { unawaited( - Navigator.of(context) - .pushNamedAndRemoveUntil( + Navigator.of( + context, + ).pushNamedAndRemoveUntil( DesktopHomeView.routeName, (route) => false, ), ); } else { - Navigator.of(context, rootNavigator: true) - .popUntil( + Navigator.of( + context, + rootNavigator: true, + ).popUntil( ModalRoute.withName( DesktopHomeView.routeName, ), @@ -754,7 +756,7 @@ class _StackRestoreProgressViewState } }, ) - : SecondaryButton( + : SecondaryButton( width: 248, buttonHeight: ButtonHeight.l, enabled: true, @@ -765,8 +767,8 @@ class _StackRestoreProgressViewState } }, ), - ], - ), + ], + ), ), ], ), diff --git a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart index 3970ff9c8..2e902ede6 100644 --- a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart +++ b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart @@ -79,188 +79,193 @@ class _StartupPreferencesViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(4.0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - ref - .read(prefsChangeNotifierProvider) - .gotoWalletOnStartup = false; - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: false, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.gotoWalletOnStartup, + onPressed: () { + ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup = false; + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension< + StackColors + >()! + .radioButtonIconEnabled, + value: false, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .gotoWalletOnStartup, + ), ), + onChanged: (value) { + if (value is bool) { + ref + .read( + prefsChangeNotifierProvider, + ) + .gotoWalletOnStartup = value; + } + }, ), - onChanged: (value) { - if (value is bool) { - ref - .read( - prefsChangeNotifierProvider, - ) - .gotoWalletOnStartup = - value; - } - }, ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Home screen", - style: - STextStyles.titleBold12( - context, + const SizedBox(width: 12), + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Home screen", + style: + STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - Text( - "${AppConfig.appName} home screen", - style: - STextStyles.itemSubtitle( - context, + Text( + "${AppConfig.appName} home screen", + style: + STextStyles.itemSubtitle( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - Padding( - padding: const EdgeInsets.all(4), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + Padding( + padding: const EdgeInsets.all(4), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - ref - .read(prefsChangeNotifierProvider) - .gotoWalletOnStartup = true; - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: true, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.gotoWalletOnStartup, + onPressed: () { + ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup = true; + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension< + StackColors + >()! + .radioButtonIconEnabled, + value: true, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .gotoWalletOnStartup, + ), ), + onChanged: (value) { + if (value is bool) { + ref + .read( + prefsChangeNotifierProvider, + ) + .gotoWalletOnStartup = value; + } + }, ), - onChanged: (value) { - if (value is bool) { - ref - .read( - prefsChangeNotifierProvider, - ) - .gotoWalletOnStartup = - value; - } - }, ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Specific wallet", - style: - STextStyles.titleBold12( - context, + const SizedBox(width: 12), + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Specific wallet", + style: + STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - (safe && - ref.watch( - prefsChangeNotifierProvider - .select( - (value) => value - .startupWalletId, - ), - ) != - null) - ? Padding( + (safe && + ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .startupWalletId, + ), + ) != + null) + ? Padding( padding: - const EdgeInsets - .only(top: 12), + const EdgeInsets.only( + top: 12, + ), child: Row( children: [ SvgPicture.file( @@ -270,9 +275,10 @@ class _StartupPreferencesViewState ref.watch( pWalletCoin( ref.watch( - prefsChangeNotifierProvider - .select( - (value) => + prefsChangeNotifierProvider.select( + ( + value, + ) => value.startupWalletId!, ), ), @@ -291,115 +297,116 @@ class _StartupPreferencesViewState ref.watch( prefsChangeNotifierProvider .select( - (value) => - value - .startupWalletId!, - ), + ( + value, + ) => + value.startupWalletId!, + ), ), ), ), - style: STextStyles - .itemSubtitle( - context, - ), + style: + STextStyles.itemSubtitle( + context, + ), ), ], ), ) - : Text( + : Text( "Select a specific wallet to load into on startup", - style: STextStyles - .itemSubtitle( - context, - ), + style: + STextStyles.itemSubtitle( + context, + ), textAlign: TextAlign.left, ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - if (!ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.gotoWalletOnStartup, - ), - )) - const SizedBox( - height: 12, - ), - if (ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.gotoWalletOnStartup, - ), - )) - Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - right: 12, - bottom: 12, - ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const SizedBox( - width: 12 + 20, - height: 12, - ), - Flexible( - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize - .shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular( - Constants - .size.circularBorderRadius, + if (!ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.gotoWalletOnStartup, + ), + )) + const SizedBox(height: 12), + if (ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.gotoWalletOnStartup, + ), + )) + Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + right: 12, + bottom: 12, + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 12 + 20, + height: 12, + ), + Flexible( + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize + .shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - StartupWalletSelectionView - .routeName, - ); - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Select wallet...", - style: STextStyles.link2( - context, + onPressed: () { + Navigator.of(context).pushNamed( + StartupWalletSelectionView + .routeName, + ); + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Select wallet...", + style: STextStyles.link2( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart index 7c073c5ce..0caa4720d 100644 --- a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart +++ b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart @@ -13,6 +13,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../../providers/providers.dart'; import '../../../../themes/coin_icon_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -64,180 +65,179 @@ 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: ref - .watch( - pCoinColor( - ref.watch( - pWalletCoin( - wallet.walletId, + body: SafeArea( + child: 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, ), - ) - .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(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 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( + // height: 2, + // ), + // FutureBuilder( + // future: manager.totalBalance, + // builder: (builderContext, + // AsyncSnapshot 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()! - .radioButtonIconEnabled, - value: wallet.walletId, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.startupWalletId, + SizedBox( + height: 20, + width: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: wallet.walletId, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value.startupWalletId, + ), ), + onChanged: (value) { + if (value is String) { + ref + .read( + prefsChangeNotifierProvider, + ) + .startupWalletId = value; + } + }, ), - onChanged: (value) { - if (value is String) { - ref - .read( - prefsChangeNotifierProvider, - ) - .startupWalletId = value; - } - }, ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/support_view.dart b/lib/pages/settings_views/global_settings_view/support_view.dart index 8c348d99a..fcfc6ee18 100644 --- a/lib/pages/settings_views/global_settings_view/support_view.dart +++ b/lib/pages/settings_views/global_settings_view/support_view.dart @@ -10,6 +10,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:url_launcher/url_launcher.dart'; + import '../../../app_config.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; @@ -20,12 +22,9 @@ import '../../../widgets/background.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/rounded_white_container.dart'; -import 'package:url_launcher/url_launcher.dart'; class SupportView extends StatelessWidget { - const SupportView({ - super.key, - }); + const SupportView({super.key}); static const String routeName = "/support"; @@ -48,14 +47,10 @@ class SupportView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Support", - style: STextStyles.navBarTitle(context), - ), + title: Text("Support", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), ), ), ); @@ -69,13 +64,7 @@ class SupportView extends StatelessWidget { style: STextStyles.smallMed12(context), ), ), - isDesktop - ? const SizedBox( - height: 24, - ) - : const SizedBox( - height: 12, - ), + isDesktop ? const SizedBox(height: 24) : const SizedBox(height: 12), AboutItem( linkUrl: "https://t.me/stackwallet", label: "Telegram", @@ -83,9 +72,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.telegram, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://discord.com/invite/mRPZuXx3At", label: "Discord", @@ -93,9 +80,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.discord, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://www.reddit.com/r/stackwallet/", label: "Reddit", @@ -103,9 +88,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.reddit, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://twitter.com/stack_wallet", label: "Twitter", @@ -113,9 +96,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.twitter, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "mailto:support@stackwallet.com", label: "Email", @@ -160,21 +141,13 @@ class AboutItem extends StatelessWidget { ), ), onPressed: () { - launchUrl( - Uri.parse(linkUrl), - mode: LaunchMode.externalApplication, - ); + launchUrl(Uri.parse(linkUrl), mode: LaunchMode.externalApplication); }, child: Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 20, - vertical: 15, - ) - : const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, - ), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 20, vertical: 15) + : const EdgeInsets.symmetric(horizontal: 12, vertical: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -182,31 +155,30 @@ class AboutItem extends StatelessWidget { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10000), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - ), - child: Center( - child: child, - ), - ), + builder: + (child) => Container( + width: 40, + height: 40, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10000), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + ), + child: Center(child: child), + ), child: SvgPicture.asset( iconAsset, width: iconSize, height: iconSize, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( label, style: STextStyles.titleBold12(context), diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart index b036f89f8..7a0644f4d 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart @@ -46,26 +46,23 @@ class SyncingOptionsView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Syncing", - style: STextStyles.navBarTitle(context), - ), + title: Text("Syncing", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -114,13 +111,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.currentWalletOnly, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -131,9 +130,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -192,13 +189,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.allWalletsOnStartup, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -209,9 +208,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -272,13 +269,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.selectedWalletsAtStartup, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -289,9 +288,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -316,16 +313,16 @@ class SyncingOptionsView extends ConsumerWidget { ), ), if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ) != SyncingType.selectedWalletsAtStartup) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ) == SyncingType.selectedWalletsAtStartup) Container( @@ -339,10 +336,7 @@ class SyncingOptionsView extends ConsumerWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - width: 12 + 20, - height: 12, - ), + const SizedBox(width: 12 + 20, height: 12), Flexible( child: RawMaterialButton( // splashColor: Theme.of(context).extension()!.highlight, @@ -356,48 +350,50 @@ class SyncingOptionsView extends ConsumerWidget { onPressed: () { !isDesktop ? Navigator.of(context).pushNamed( - WalletSyncingOptionsView.routeName, - ) + WalletSyncingOptionsView.routeName, + ) : showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxWidth: 600, - maxHeight: 800, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Padding( - padding: - const EdgeInsets.all( - 32, - ), - child: Text( - "Select wallets to sync", - style: STextStyles - .desktopH3(context), - textAlign: - TextAlign.center, - ), + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 600, + maxHeight: 800, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.all( + 32, + ), + child: Text( + "Select wallets to sync", + style: + STextStyles.desktopH3( + context, + ), + textAlign: + TextAlign.center, ), - const DesktopDialogCloseButton(), - ], - ), - const Expanded( - child: - WalletSyncingOptionsView(), - ), - ], - ), - ); - }, - ); + ), + const DesktopDialogCloseButton(), + ], + ), + const Expanded( + child: + WalletSyncingOptionsView(), + ), + ], + ), + ); + }, + ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart index 988d951f1..7c29aa9b0 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart @@ -54,127 +54,136 @@ class SyncingPreferencesView extends ConsumerWidget { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( padding: const EdgeInsets.all(0), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + padding: const EdgeInsets.all(0), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(SyncingOptionsView.routeName); - }, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Syncing", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - Text( - _currentTypeDescription( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.syncType, + onPressed: () { + Navigator.of( + context, + ).pushNamed(SyncingOptionsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Syncing", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + Text( + _currentTypeDescription( + ref.watch( + prefsChangeNotifierProvider + .select( + (value) => value.syncType, + ), ), ), + style: STextStyles.itemSubtitle( + context, + ), + textAlign: TextAlign.left, ), - style: - STextStyles.itemSubtitle(context), - textAlign: TextAlign.left, - ), - ], - ), - const Spacer(), - ], + ], + ), + const Spacer(), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "AutoSync only on Wi-Fi", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.wifiOnly, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "AutoSync only on Wi-Fi", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => value.wifiOnly, + ), ), + onValueChanged: (newValue) { + ref + .read( + prefsChangeNotifierProvider, + ) + .wifiOnly = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read( - prefsChangeNotifierProvider, - ) - .wifiOnly = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart index f974226b6..c5916cf70 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart @@ -60,13 +60,11 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), ), ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), - child: child, ), ), ); @@ -92,23 +90,20 @@ class WalletSyncingOptionsView extends ConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( "Choose the wallets to sync automatically at startup", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( padding: const EdgeInsets.all(0), - borderColor: !isDesktop - ? Colors.transparent - : Theme.of(context) - .extension()! - .background, + borderColor: + !isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.background, child: Column( children: [ ...walletInfos.map( @@ -141,9 +136,7 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -153,11 +146,10 @@ class WalletSyncingOptionsView extends ConsumerWidget { Text( info.name, style: STextStyles.titleBold12( - context), - ), - const SizedBox( - height: 2, + context, + ), ), + const SizedBox(height: 2), Text( ref .watch( @@ -173,7 +165,8 @@ class WalletSyncingOptionsView extends ConsumerWidget { .total, ), style: STextStyles.itemSubtitle( - context), + context, + ), ), ], ), @@ -184,10 +177,10 @@ class WalletSyncingOptionsView extends ConsumerWidget { child: DraggableSwitchButton( isOn: ref .watch( - prefsChangeNotifierProvider - .select( - (value) => value - .walletIdsSyncOnStartup, + prefsChangeNotifierProvider.select( + (value) => + value + .walletIdsSyncOnStartup, ), ) .contains(info.walletId), @@ -195,11 +188,13 @@ class WalletSyncingOptionsView extends ConsumerWidget { // final syncType = ref // .read(prefsChangeNotifierProvider) // .syncType; - final ids = ref - .read( - prefsChangeNotifierProvider) - .walletIdsSyncOnStartup - .toList(); + final ids = + ref + .read( + prefsChangeNotifierProvider, + ) + .walletIdsSyncOnStartup + .toList(); if (value) { ids.add(info.walletId); } else { @@ -228,7 +223,8 @@ class WalletSyncingOptionsView extends ConsumerWidget { ref .read( - prefsChangeNotifierProvider) + prefsChangeNotifierProvider, + ) .walletIdsSyncOnStartup = ids; }, ), diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 245937fdf..24800936d 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -34,9 +34,7 @@ import '../../../../widgets/stack_dialog.dart'; import '../../../../widgets/tor_subscription.dart'; class TorSettingsView extends ConsumerStatefulWidget { - const TorSettingsView({ - super.key, - }); + const TorSettingsView({super.key}); static const String routeName = "/torSettings"; @@ -59,17 +57,12 @@ class _TorSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Tor settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("Tor settings", style: STextStyles.navBarTitle(context)), actions: [ AspectRatio( aspectRatio: 1, child: AppBarIconButton( - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - ), + icon: SvgPicture.asset(Assets.svg.circleQuestion), onPressed: () { showDialog( context: context, @@ -94,107 +87,107 @@ class _TorSettingsViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.all(10.0), - child: TorAnimatedButton(), - ), - ], - ), - const SizedBox( - height: 30, - ), - const TorButton(), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + child: TorAnimatedButton(), + ), + ], + ), + const SizedBox(height: 30), + const TorButton(), + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - "Tor killswitch", - style: STextStyles.titleBold12(context), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () { - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return StackDialog( - title: "What is Tor killswitch?", - message: - "A security feature that protects your information from accidental exposure by" - " disconnecting your device from the Tor network if the" - " connection is disrupted or compromised.", - rightButton: SecondaryButton( - label: "Close", - onPressed: - Navigator.of(context).pop, - ), - ); - }, - ); - }, - child: SvgPicture.asset( - Assets.svg.circleInfo, - height: 16, - width: 16, - color: Theme.of(context) - .extension()! - .infoItemLabel, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + "Tor killswitch", + style: STextStyles.titleBold12(context), ), + const SizedBox(width: 8), + GestureDetector( + onTap: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "What is Tor killswitch?", + message: + "A security feature that protects your information from accidental exposure by" + " disconnecting your device from the Tor network if the" + " connection is disrupted or compromised.", + rightButton: SecondaryButton( + label: "Close", + onPressed: + Navigator.of(context).pop, + ), + ); + }, + ); + }, + child: SvgPicture.asset( + Assets.svg.circleInfo, + height: 16, + width: 16, + color: + Theme.of(context) + .extension()! + .infoItemLabel, + ), + ), + ], + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.torKillSwitch, + ), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .torKillSwitch = newValue; + }, ), - ], - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.torKillSwitch), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .torKillSwitch = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - ], + ], + ), ), ), ), @@ -248,11 +241,7 @@ class _TorAnimatedButtonState extends ConsumerState } Future _playPlug() async { - await _play( - from: "0.0", - to: "connecting-start", - repeat: false, - ); + await _play(from: "0.0", to: "connecting-start", repeat: false); } Future _playConnecting({double? start}) async { @@ -272,11 +261,7 @@ class _TorAnimatedButtonState extends ConsumerState } Future _playConnected() async { - await _play( - from: "connected-start", - to: "connected-end", - repeat: true, - ); + await _play(from: "connected-start", to: "connected-end", repeat: true); } Future _playDisconnect() async { @@ -358,10 +343,7 @@ class _TorAnimatedButtonState extends ConsumerState }, child: ConditionalParent( condition: _status != TorConnectionStatus.connecting, - builder: (child) => GestureDetector( - onTap: onTap, - child: child, - ), + builder: (child) => GestureDetector(onTap: onTap, child: child), child: Column( children: [ SizedBox( @@ -401,10 +383,7 @@ class TorButton extends ConsumerStatefulWidget { class _TorButtonState extends ConsumerState { late TorConnectionStatus _status; - Color _color( - TorConnectionStatus status, - StackColors colors, - ) { + Color _color(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return colors.textSubtitle3; @@ -417,10 +396,7 @@ class _TorButtonState extends ConsumerState { } } - String _label( - TorConnectionStatus status, - StackColors colors, - ) { + String _label(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return "Disconnected"; @@ -487,16 +463,10 @@ class _TorButtonState extends ConsumerState { padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ - Text( - "Tor status", - style: STextStyles.titleBold12(context), - ), + Text("Tor status", style: STextStyles.titleBold12(context)), const Spacer(), Text( - _label( - _status, - Theme.of(context).extension()!, - ), + _label(_status, Theme.of(context).extension()!), style: STextStyles.itemSubtitle(context).copyWith( color: _color( _status, @@ -523,10 +493,7 @@ class UpperCaseTorText extends ConsumerStatefulWidget { class _UpperCaseTorTextState extends ConsumerState { late TorConnectionStatus _status; - Color _color( - TorConnectionStatus status, - StackColors colors, - ) { + Color _color(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return colors.textSubtitle3; @@ -539,9 +506,7 @@ class _UpperCaseTorTextState extends ConsumerState { } } - String _label( - TorConnectionStatus status, - ) { + String _label(TorConnectionStatus status) { switch (status) { case TorConnectionStatus.disconnected: return "CONNECT"; @@ -570,16 +535,9 @@ class _UpperCaseTorTextState extends ConsumerState { }); }, child: Text( - _label( - _status, - ), - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: _color( - _status, - Theme.of(context).extension()!, - ), + _label(_status), + style: STextStyles.pageTitleH2(context).copyWith( + color: _color(_status, Theme.of(context).extension()!), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart b/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart index 3404b395e..812639eb4 100644 --- a/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart @@ -34,10 +34,7 @@ import 'frost_participants_view.dart'; import 'initiate_resharing/initiate_resharing_view.dart'; class FrostMSWalletOptionsView extends ConsumerWidget { - const FrostMSWalletOptionsView({ - super.key, - required this.walletId, - }); + const FrostMSWalletOptionsView({super.key, required this.walletId}); static const String routeName = "/frostMSWalletOptionsView"; @@ -49,44 +46,39 @@ class FrostMSWalletOptionsView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return ConditionalParent( condition: Util.isDesktop, - builder: (child) => DesktopScaffold( - background: Theme.of(context).extension()!.background, - appBar: const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ), - body: SizedBox( - width: 480, - child: child, - ), - ), + builder: + (child) => DesktopScaffold( + background: Theme.of(context).extension()!.background, + appBar: const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ), + body: SizedBox(width: 480, child: child), + ), child: ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "FROST Multisig options", - style: STextStyles.navBarTitle(context), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "FROST Multisig options", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea(child: child), ), ), - body: child, - ), - ), child: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -105,9 +97,7 @@ class FrostMSWalletOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: EdgeInsets.zero, child: SettingsListButton( @@ -116,11 +106,12 @@ class FrostMSWalletOptionsView extends ConsumerWidget { iconAssetName: Assets.svg.swap2, onPressed: () { // TODO: optimize this by creating watcher providers (similar to normal WalletInfo) - final frostInfo = ref - .read(mainDBProvider) - .isar - .frostWalletInfo - .getByWalletIdSync(walletId)!; + final frostInfo = + ref + .read(mainDBProvider) + .isar + .frostWalletInfo + .getByWalletIdSync(walletId)!; ref.read(pFrostMyName.state).state = frostInfo.myName; @@ -131,9 +122,7 @@ class FrostMSWalletOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: EdgeInsets.zero, child: SettingsListButton( @@ -143,16 +132,18 @@ class FrostMSWalletOptionsView extends ConsumerWidget { iconSize: 16, onPressed: () { // TODO: optimize this by creating watcher providers (similar to normal WalletInfo) - final frostInfo = ref - .read(mainDBProvider) - .isar - .frostWalletInfo - .getByWalletIdSync(walletId)!; + final frostInfo = + ref + .read(mainDBProvider) + .isar + .frostWalletInfo + .getByWalletIdSync(walletId)!; ref.read(pFrostMyName.state).state = frostInfo.myName; - final wallet = ref.read(pWallets).getWallet(walletId) - as BitcoinFrostWallet; + final wallet = + ref.read(pWallets).getWallet(walletId) + as BitcoinFrostWallet; ref.read(pFrostScaffoldArgs.state).state = ( info: ( @@ -167,9 +158,9 @@ class FrostMSWalletOptionsView extends ConsumerWidget { callerRouteName: FrostMSWalletOptionsView.routeName, ); - Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + Navigator.of( + context, + ).pushNamed(FrostStepScaffold.routeName); }, ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart index 75b8ca87b..d94cca088 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart @@ -62,7 +62,8 @@ class WalletBackupView extends ConsumerWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; final KeyDataInterface? keyData; @override @@ -80,10 +81,7 @@ class WalletBackupView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Wallet backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Wallet backup", style: STextStyles.navBarTitle(context)), actions: [ if (keyData != null) Padding( @@ -93,7 +91,8 @@ class WalletBackupView extends ConsumerWidget { final XPrivData _ => "xpriv(s)", final CWKeyData _ => "keys", final ViewOnlyWalletData _ => "keys", - _ => throw UnimplementedError( + _ => + throw UnimplementedError( "Don't forget to add your KeyDataInterface here! ${keyData.runtimeType}", ), }, @@ -101,27 +100,24 @@ class WalletBackupView extends ConsumerWidget { Navigator.pushNamed( context, MobileKeyDataView.routeName, - arguments: ( - walletId: walletId, - keyData: keyData!, - ), + arguments: (walletId: walletId, keyData: keyData!), ); }, ), ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: frost - ? _FrostKeys( - frostWalletData: frostWalletData, - walletId: walletId, - ) - : _Mnemonic( - walletId: walletId, - mnemonic: mnemonic, - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + frost + ? _FrostKeys( + frostWalletData: frostWalletData, + walletId: walletId, + ) + : _Mnemonic(walletId: walletId, mnemonic: mnemonic), + ), ), ), ); @@ -148,21 +144,15 @@ class _Mnemonic extends ConsumerWidget { Text( ref.watch(pWalletName(walletId)), textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - const SizedBox( - height: 4, + style: STextStyles.label(context).copyWith(fontSize: 12), ), + const SizedBox(height: 4), Text( "Recovery Phrase", textAlign: TextAlign.center, style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, @@ -182,25 +172,19 @@ class _Mnemonic extends ConsumerWidget { ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: SingleChildScrollView( - child: MnemonicTable( - words: mnemonic, - isDesktop: false, - ), + child: MnemonicTable(words: mnemonic, isDesktop: false), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), SecondaryButton( label: "Copy", onPressed: () async { - await clipboardInterface - .setData(ClipboardData(text: mnemonic.join(" "))); + await clipboardInterface.setData( + ClipboardData(text: mnemonic.join(" ")), + ); if (context.mounted) { unawaited( showFloatingFlushBar( @@ -213,9 +197,7 @@ class _Mnemonic extends ConsumerWidget { } }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), PrimaryButton( label: "Show QR Code", onPressed: () { @@ -237,25 +219,18 @@ class _Mnemonic extends ConsumerWidget { style: STextStyles.pageTitleH2(context), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: RepaintBoundary( // key: _qrKey, child: SizedBox( width: width + 20, height: width + 20, - child: QR( - data: data, - size: width, - ), + child: QR(data: data, size: width), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: SizedBox( width: width, @@ -266,15 +241,14 @@ class _Mnemonic extends ConsumerWidget { }, style: Theme.of(context) .extension()! - .getSecondaryEnabledButtonStyle( - context, - ), + .getSecondaryEnabledButtonStyle(context), child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), @@ -293,11 +267,7 @@ class _Mnemonic extends ConsumerWidget { } class _FrostKeys extends StatelessWidget { - const _FrostKeys({ - super.key, - required this.walletId, - this.frostWalletData, - }); + const _FrostKeys({super.key, required this.walletId, this.frostWalletData}); final String walletId; final ({ @@ -305,7 +275,8 @@ class _FrostKeys extends StatelessWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; @override Widget build(BuildContext context) { @@ -314,9 +285,7 @@ class _FrostKeys extends StatelessWidget { builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), + constraints: BoxConstraints(minHeight: constraints.maxHeight - 24), child: IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -334,9 +303,7 @@ class _FrostKeys extends StatelessWidget { style: STextStyles.label(context), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), // DetailItem( // title: "My name", // detail: frostWalletData!.myName, @@ -354,32 +321,21 @@ class _FrostKeys extends StatelessWidget { DetailItem( title: "Multisig config", detail: frostWalletData!.config, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.config, - ) - : SimpleCopyButton( - data: frostWalletData!.config, - ), - ), - const SizedBox( - height: 16, + button: + Util.isDesktop + ? IconCopyButton(data: frostWalletData!.config) + : SimpleCopyButton(data: frostWalletData!.config), ), + const SizedBox(height: 16), DetailItem( title: "Keys", detail: frostWalletData!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.keys, - ) - : SimpleCopyButton( - data: frostWalletData!.keys, - ), + button: + Util.isDesktop + ? IconCopyButton(data: frostWalletData!.keys) + : SimpleCopyButton(data: frostWalletData!.keys), ), - if (prevGen) - const SizedBox( - height: 24, - ), + if (prevGen) const SizedBox(height: 24), if (prevGen) RoundedWhiteContainer( child: Text( @@ -387,37 +343,33 @@ class _FrostKeys extends StatelessWidget { style: STextStyles.label(context), ), ), - if (prevGen) - const SizedBox( - height: 12, - ), + if (prevGen) const SizedBox(height: 12), if (prevGen) DetailItem( title: "Previous multisig config", detail: frostWalletData!.prevGen!.config, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.prevGen!.config, - ) - : SimpleCopyButton( - data: frostWalletData!.prevGen!.config, - ), - ), - if (prevGen) - const SizedBox( - height: 16, + button: + Util.isDesktop + ? IconCopyButton( + data: frostWalletData!.prevGen!.config, + ) + : SimpleCopyButton( + data: frostWalletData!.prevGen!.config, + ), ), + if (prevGen) const SizedBox(height: 16), if (prevGen) DetailItem( title: "Previous keys", detail: frostWalletData!.prevGen!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.prevGen!.keys, - ) - : SimpleCopyButton( - data: frostWalletData!.prevGen!.keys, - ), + button: + Util.isDesktop + ? IconCopyButton( + data: frostWalletData!.prevGen!.keys, + ) + : SimpleCopyButton( + data: frostWalletData!.prevGen!.keys, + ), ), ], ), @@ -459,9 +411,7 @@ class MobileKeyDataView extends ConsumerWidget { final XPrivData _ => "xpriv(s)", final CWKeyData _ => "keys", final ViewOnlyWalletData _ => "keys", - _ => throw UnimplementedError( - "Don't forget to add your KeyDataInterface here!", - ), + _ => throw UnimplementedError("Don't forget to add your KeyDataInterface here!"), }}", style: STextStyles.navBarTitle(context), ), @@ -470,40 +420,40 @@ class MobileKeyDataView extends ConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: switch (keyData) { - final XPrivData e => WalletXPrivs( - walletId: walletId, - xprivData: e, - ), - final CWKeyData e => CNWalletKeys( - walletId: walletId, - cwKeyData: e, - ), - final ViewOnlyWalletData e => - ViewOnlyWalletDataWidget( - data: e, - ), - _ => throw UnimplementedError( - "Don't forget to add your KeyDataInterface here!", - ), - }, - ), - const SizedBox( - height: 16, + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: switch (keyData) { + final XPrivData e => WalletXPrivs( + walletId: walletId, + xprivData: e, + ), + final CWKeyData e => CNWalletKeys( + walletId: walletId, + cwKeyData: e, + ), + final ViewOnlyWalletData e => + ViewOnlyWalletDataWidget(data: e), + _ => + throw UnimplementedError( + "Don't forget to add your KeyDataInterface here!", + ), + }, + ), + const SizedBox(height: 16), + ], ), - ], + ), ), ), - ), - ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index 5b3a2eb07..506f1167c 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -142,9 +142,7 @@ class _WalletNetworkSettingsViewState try { final wallet = ref.read(pWallets).getWallet(widget.walletId); - await wallet.recover( - isRescan: true, - ); + await wallet.recover(isRescan: true); if (mounted) { // pop rescanning dialog @@ -155,29 +153,31 @@ class _WalletNetworkSettingsViewState context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => ConditionalParent( - condition: isDesktop, - builder: (child) => DesktopDialog( - maxHeight: 150, - maxWidth: 500, - child: child, - ), - child: StackDialog( - title: "Rescan completed", - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => ConditionalParent( + condition: isDesktop, + builder: + (child) => DesktopDialog( + maxHeight: 150, + maxWidth: 500, + child: child, + ), + child: StackDialog( + title: "Rescan completed", + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context, rootNavigator: isDesktop).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: isDesktop).pop(); - }, ), - ), - ), ); } } catch (e) { @@ -192,22 +192,23 @@ class _WalletNetworkSettingsViewState context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => StackDialog( + title: "Rescan failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context, rootNavigator: isDesktop).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: isDesktop).pop(); - }, - ), - ), ); } } @@ -246,26 +247,25 @@ class _WalletNetworkSettingsViewState eventBus = widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; - _syncStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _currentSyncStatus = event.newStatus; - }); - } - }, - ); + _syncStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentSyncStatus = event.newStatus; + }); + } + }); - _refreshSubscription = eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _percent = event.percent.clamp(0.0, 1.0); - }); - } - }, - ); + _refreshSubscription = eventBus.on().listen(( + event, + ) async { + if (event.walletId == widget.walletId) { + setState(() { + _percent = event.percent.clamp(0.0, 1.0); + }); + } + }); final coin = ref.read(pWalletCoin(widget.walletId)); @@ -322,9 +322,10 @@ class _WalletNetworkSettingsViewState Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; - final progressLength = isDesktop - ? 430.0 - : screenWidth - (_padding * 2) - (_boxPadding * 3) - _iconSize; + final progressLength = + isDesktop + ? 430.0 + : screenWidth - (_padding * 2) - (_boxPadding * 3) - _iconSize; final coin = ref.watch(pWalletCoin(widget.walletId)); @@ -364,10 +365,7 @@ class _WalletNetworkSettingsViewState Navigator.of(context).pop(); }, ), - title: Text( - "Network", - style: STextStyles.navBarTitle(context), - ), + title: Text("Network", style: STextStyles.navBarTitle(context)), actions: [ if (ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) Padding( @@ -384,14 +382,16 @@ class _WalletNetworkSettingsViewState ), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -408,9 +408,10 @@ class _WalletNetworkSettingsViewState right: 10, child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -461,18 +462,18 @@ class _WalletNetworkSettingsViewState ), ], ), - body: Padding( - padding: EdgeInsets.only( - top: 12, - left: _padding, - right: _padding, - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - child, - ], + body: SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: 12, + left: _padding, + right: _padding, + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [child], + ), ), ), ), @@ -488,9 +489,10 @@ class _WalletNetworkSettingsViewState Text( "Blockchain status", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( text: "Resync", @@ -500,17 +502,17 @@ class _WalletNetworkSettingsViewState ), ], ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), if (_currentSyncStatus == WalletSyncStatus.synced) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -528,15 +530,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radio, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .accentColorGreen, + color: + Theme.of( + context, + ).extension()!.accentColorGreen, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -551,18 +552,18 @@ class _WalletNetworkSettingsViewState ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: 1, ), ], @@ -572,12 +573,14 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.syncing) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -595,15 +598,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radioSyncing, height: 14, width: 14, - color: Theme.of(context) - .extension()! - .accentColorYellow, + color: + Theme.of( + context, + ).extension()!.accentColorYellow, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -624,11 +626,13 @@ class _WalletNetworkSettingsViewState children: [ Text( _percentString(_percent), - style: - STextStyles.syncPercent(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow, + style: STextStyles.syncPercent( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorYellow, ), ), if (coin is Monero || @@ -636,11 +640,13 @@ class _WalletNetworkSettingsViewState coin is Epiccash) Text( " (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})", - style: STextStyles.syncPercent(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow, + style: STextStyles.syncPercent( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorYellow, ), ), ], @@ -648,18 +654,18 @@ class _WalletNetworkSettingsViewState ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorYellow, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorYellow, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: _percent, ), ], @@ -669,12 +675,14 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.unableToSync) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -692,15 +700,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radioProblem, height: 14, width: 14, - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -711,34 +718,36 @@ class _WalletNetworkSettingsViewState Text( "Unable to synchronize", style: STextStyles.w600_12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), Text( "0%", style: STextStyles.syncPercent(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorRed, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorRed, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: 0, ), ], @@ -748,30 +757,29 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.unableToSync) Padding( - padding: const EdgeInsets.only( - top: 12, - ), + padding: const EdgeInsets.only(top: 12), child: RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, + color: + Theme.of( + context, + ).extension()!.warningBackground, child: Text( "Please check your internet connection and make sure your current node is not having issues.", style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of( + context, + ).extension()!.warningForeground, ), ), ), ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( @@ -780,9 +788,10 @@ class _WalletNetworkSettingsViewState Text( "Current height", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), Text( ref.watch(pWalletChainHeight(widget.walletId)).toString(), @@ -791,36 +800,37 @@ class _WalletNetworkSettingsViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Tor status", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( - text: ref.watch( - prefsChangeNotifierProvider.select((value) => value.useTor), - ) - ? "Disconnect" - : "Connect", + text: + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.useTor, + ), + ) + ? "Disconnect" + : "Connect", onTap: onTorTapped, ), ], ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( @@ -843,9 +853,10 @@ class _WalletNetworkSettingsViewState Assets.svg.tor, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .accentColorGreen, + color: + Theme.of( + context, + ).extension()!.accentColorGreen, ), ), ), @@ -856,10 +867,9 @@ class _WalletNetworkSettingsViewState width: _iconSize, height: _iconSize, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.08), + color: Theme.of( + context, + ).extension()!.textDark.withOpacity(0.08), borderRadius: BorderRadius.circular(_iconSize), ), child: Center( @@ -867,15 +877,14 @@ class _WalletNetworkSettingsViewState Assets.svg.tor, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), TorSubscription( onTorStatusChanged: (status) { setState(() { @@ -887,32 +896,37 @@ class _WalletNetworkSettingsViewState children: [ Text( "Tor status", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ), if (_torConnectionStatus == TorConnectionStatus.connected) Text( "Connected", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (_torConnectionStatus == TorConnectionStatus.connecting) Text( "Connecting...", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (_torConnectionStatus == TorConnectionStatus.disconnected) Text( "Disconnected", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ), @@ -920,18 +934,17 @@ class _WalletNetworkSettingsViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "${ref.watch(pWalletCoin(widget.walletId)).prettyName} nodes", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( text: "Add new node", @@ -949,22 +962,16 @@ class _WalletNetworkSettingsViewState ), ], ), - SizedBox( - height: isDesktop ? 12 : 8, - ), + SizedBox(height: isDesktop ? 12 : 8), NodesList( coin: ref.watch(pWalletCoin(widget.walletId)), popBackToRoute: WalletNetworkSettingsView.routeName, ), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) Padding( - padding: const EdgeInsets.only( - bottom: 12, - ), + padding: const EdgeInsets.only(bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -978,12 +985,14 @@ class _WalletNetworkSettingsViewState ), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Expandable( onExpandChanged: (state) { setState(() { @@ -999,24 +1008,24 @@ class _WalletNetworkSettingsViewState width: _iconSize, height: _iconSize, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular(_iconSize), ), child: Center( child: SvgPicture.asset( Assets.svg.networkWired, width: 24, - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -1026,9 +1035,10 @@ class _WalletNetworkSettingsViewState style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), Text( @@ -1047,9 +1057,10 @@ class _WalletNetworkSettingsViewState : Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ], ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index 68436c634..4d88a4d91 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -190,410 +190,420 @@ class _WalletSettingsViewState extends ConsumerState { ), title: Text("Settings", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (builderContext, 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.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(4), - child: Column( - children: [ - SettingsListButton( - iconAssetName: Assets.svg.addressBook, - iconSize: 16, - title: "Address book", - onPressed: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: coin, - ); - }, - ), - if (coin is FrostCurrency) + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(4), + child: Column( + children: [ + SettingsListButton( + iconAssetName: Assets.svg.addressBook, + iconSize: 16, + title: "Address book", + onPressed: () { + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: coin, + ); + }, + ), + if (coin is FrostCurrency) + const SizedBox(height: 8), + if (coin is FrostCurrency) + SettingsListButton( + iconAssetName: Assets.svg.addressBook2, + iconSize: 16, + title: "FROST Multisig settings", + onPressed: () { + Navigator.of(context).pushNamed( + FrostMSWalletOptionsView.routeName, + arguments: walletId, + ); + }, + ), const SizedBox(height: 8), - if (coin is FrostCurrency) SettingsListButton( - iconAssetName: Assets.svg.addressBook2, + iconAssetName: Assets.svg.node, iconSize: 16, - title: "FROST Multisig settings", + title: "Network", onPressed: () { Navigator.of(context).pushNamed( - FrostMSWalletOptionsView.routeName, - arguments: walletId, + WalletNetworkSettingsView.routeName, + arguments: Tuple3( + walletId, + _currentSyncStatus, + widget.initialNodeStatus, + ), ); }, ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.node, - iconSize: 16, - title: "Network", - onPressed: () { - Navigator.of(context).pushNamed( - WalletNetworkSettingsView.routeName, - arguments: Tuple3( - walletId, - _currentSyncStatus, - widget.initialNodeStatus, - ), - ); - }, - ), - if (canBackup) const SizedBox(height: 8), - if (canBackup) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.lock, - iconSize: 16, - title: "Wallet backup", - onPressed: () async { - // TODO: [prio=med] take wallets that don't have a mnemonic into account - - List? mnemonic; - ({ - String myName, - String config, - String keys, - ({String config, String keys})? - prevGen, - })? - frostWalletData; - if (wallet is BitcoinFrostWallet) { - final futures = [ - wallet.getSerializedKeys(), - wallet.getMultisigConfig(), - wallet.getSerializedKeysPrevGen(), - wallet.getMultisigConfigPrevGen(), - ]; - - final results = await Future.wait( - futures, - ); + if (canBackup) const SizedBox(height: 8), + if (canBackup) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.lock, + iconSize: 16, + title: "Wallet backup", + onPressed: () async { + // TODO: [prio=med] take wallets that don't have a mnemonic into account + + List? mnemonic; + ({ + String myName, + String config, + String keys, + ({String config, String keys})? + prevGen, + })? + frostWalletData; + if (wallet is BitcoinFrostWallet) { + final futures = [ + wallet.getSerializedKeys(), + wallet.getMultisigConfig(), + wallet + .getSerializedKeysPrevGen(), + wallet + .getMultisigConfigPrevGen(), + ]; - if (results.length == 4) { - frostWalletData = ( - myName: wallet.frostInfo.myName, - config: results[1]!, - keys: results[0]!, - prevGen: - results[2] == null || - results[3] == null - ? null - : ( - config: results[3]!, - keys: results[2]!, - ), + final results = await Future.wait( + futures, ); - } - } else { - if (wallet is MnemonicInterface) { - if (wallet - is ViewOnlyOptionInterface && - (wallet as ViewOnlyOptionInterface) - .isViewOnly) { - // TODO: is something needed here? - } else { - mnemonic = - await wallet - .getMnemonicAsWords(); + + if (results.length == 4) { + frostWalletData = ( + myName: + wallet.frostInfo.myName, + config: results[1]!, + keys: results[0]!, + prevGen: + results[2] == null || + results[3] == null + ? null + : ( + config: results[3]!, + keys: results[2]!, + ), + ); + } + } else { + if (wallet is MnemonicInterface) { + if (wallet + is ViewOnlyOptionInterface && + (wallet as ViewOnlyOptionInterface) + .isViewOnly) { + // TODO: is something needed here? + } else { + mnemonic = + await wallet + .getMnemonicAsWords(); + } } } - } - - KeyDataInterface? keyData; - if (wallet - is ViewOnlyOptionInterface && - wallet.isViewOnly) { - keyData = - await wallet - .getViewOnlyWalletData(); - } else if (wallet - is ExtendedKeysInterface) { - keyData = await wallet.getXPrivs(); - } else if (wallet - is LibMoneroWallet) { - keyData = await wallet.getKeys(); - } - - if (context.mounted) { - if (keyData != null && - wallet + + KeyDataInterface? keyData; + if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { - await Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: - ( - walletId: - walletId, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: - MobileKeyDataView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery data", - biometricsAuthenticationTitle: - "View recovery data", - ), - settings: const RouteSettings( - name: - "/viewRecoveryDataLockscreen", + keyData = + await wallet + .getViewOnlyWalletData(); + } else if (wallet + is ExtendedKeysInterface) { + keyData = + await wallet.getXPrivs(); + } else if (wallet + is LibMoneroWallet) { + keyData = await wallet.getKeys(); + } + + if (context.mounted) { + if (keyData != null && + wallet + is ViewOnlyOptionInterface && + wallet.isViewOnly) { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + ( + walletId: + walletId, + keyData: + keyData, + ), + showBackButton: true, + routeOnSuccess: + MobileKeyDataView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery data", + biometricsAuthenticationTitle: + "View recovery data", + ), + settings: const RouteSettings( + name: + "/viewRecoveryDataLockscreen", + ), ), - ), - ); - } else { - await Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: ( - walletId: walletId, - mnemonic: - mnemonic ?? [], - frostWalletData: - frostWalletData, - keyData: keyData, + ); + } else { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: ( + walletId: walletId, + mnemonic: + mnemonic ?? [], + frostWalletData: + frostWalletData, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + WalletBackupView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", ), - showBackButton: true, - routeOnSuccess: - WalletBackupView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: - "View recovery phrase", - ), - settings: const RouteSettings( - name: - "/viewRecoverPhraseLockscreen", + settings: const RouteSettings( + name: + "/viewRecoverPhraseLockscreen", + ), ), - ), - ); + ); + } } - } - }, + }, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.downloadFolder, + title: "Wallet settings", + iconSize: 16, + onPressed: () { + Navigator.of(context).pushNamed( + WalletSettingsWalletSettingsView + .routeName, + arguments: walletId, ); }, ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.downloadFolder, - title: "Wallet settings", - iconSize: 16, - onPressed: () { - Navigator.of(context).pushNamed( - WalletSettingsWalletSettingsView - .routeName, - arguments: walletId, - ); - }, - ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.arrowRotate, - title: "Syncing preferences", - onPressed: () { - Navigator.of(context).pushNamed( - SyncingPreferencesView.routeName, - ); - }, - ), - if (xPubEnabled) const SizedBox(height: 8), - if (xPubEnabled) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Wallet xPub", - onPressed: () async { - final xpubData = await showLoading( - delay: const Duration( - milliseconds: 800, - ), - whileFuture: - (ref - .read(pWallets) - .getWallet(walletId) - as ExtendedKeysInterface) - .getXPubs(), - context: context, - message: "Loading xpubs", - rootNavigator: Util.isDesktop, - ); - if (context.mounted) { - await Navigator.of( - context, - ).pushNamed( - XPubView.routeName, - arguments: ( - widget.walletId, - xpubData, - ), - ); - } - }, + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.arrowRotate, + title: "Syncing preferences", + onPressed: () { + Navigator.of(context).pushNamed( + SyncingPreferencesView.routeName, ); }, ), - if (coin is Firo) const SizedBox(height: 8), - if (coin is Firo) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Clear electrumx cache", - onPressed: () async { - String? result; - await showDialog( - useSafeArea: false, - barrierDismissible: true, - context: context, - builder: - (_) => StackOkDialog( - title: - "Are you sure you want to clear " - "${coin.prettyName} electrumx cache?", - onOkPressed: (value) { - result = value; - }, - leftButton: SecondaryButton( - label: "Cancel", - onPressed: () { - Navigator.of( - context, - ).pop(); - }, - ), + if (xPubEnabled) const SizedBox(height: 8), + if (xPubEnabled) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Wallet xPub", + onPressed: () async { + final xpubData = await showLoading( + delay: const Duration( + milliseconds: 800, + ), + whileFuture: + (ref + .read(pWallets) + .getWallet( + walletId, + ) + as ExtendedKeysInterface) + .getXPubs(), + context: context, + message: "Loading xpubs", + rootNavigator: Util.isDesktop, + ); + if (context.mounted) { + await Navigator.of( + context, + ).pushNamed( + XPubView.routeName, + arguments: ( + widget.walletId, + xpubData, ), - ); - - if (result == "OK" && - context.mounted) { - await showLoading( - whileFuture: Future.wait([ - Future.delayed( - const Duration( - milliseconds: 1500, + ); + } + }, + ); + }, + ), + if (coin is Firo) const SizedBox(height: 8), + if (coin is Firo) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Clear electrumx cache", + onPressed: () async { + String? result; + await showDialog( + useSafeArea: false, + barrierDismissible: true, + context: context, + builder: + (_) => StackOkDialog( + title: + "Are you sure you want to clear " + "${coin.prettyName} electrumx cache?", + onOkPressed: (value) { + result = value; + }, + leftButton: SecondaryButton( + label: "Cancel", + onPressed: () { + Navigator.of( + context, + ).pop(); + }, + ), ), - ), - DB.instance - .clearSharedTransactionCache( - currency: coin, + ); + + if (result == "OK" && + context.mounted) { + await showLoading( + whileFuture: Future.wait([ + Future.delayed( + const Duration( + milliseconds: 1500, ), - if (coin is Firo) - FiroCacheCoordinator.clearSharedCache( - coin.network, ), - ]), - context: context, - message: "Clearing cache...", + DB.instance + .clearSharedTransactionCache( + currency: coin, + ), + if (coin is Firo) + FiroCacheCoordinator.clearSharedCache( + coin.network, + ), + ]), + context: context, + message: "Clearing cache...", + ); + } + }, + ); + }, + ), + if (coin is NanoCurrency) + const SizedBox(height: 8), + if (coin is NanoCurrency) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Change representative", + onPressed: () { + Navigator.of(context).pushNamed( + ChangeRepresentativeView + .routeName, + arguments: widget.walletId, ); - } - }, - ); - }, - ), - if (coin is NanoCurrency) - const SizedBox(height: 8), - if (coin is NanoCurrency) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Change representative", - onPressed: () { - Navigator.of(context).pushNamed( - ChangeRepresentativeView.routeName, - arguments: widget.walletId, - ); - }, - ); - }, - ), - // const SizedBox( - // height: 8, - // ), - // SettingsListButton( - // iconAssetName: Assets.svg.ellipsis, - // title: "Debug Info", - // onPressed: () { - // Navigator.of(context) - // .pushNamed(DebugView.routeName); - // }, - // ), - ], + }, + ); + }, + ), + // const SizedBox( + // height: 8, + // ), + // SettingsListButton( + // iconAssetName: Assets.svg.ellipsis, + // title: "Debug Info", + // onPressed: () { + // Navigator.of(context) + // .pushNamed(DebugView.routeName); + // }, + // ), + ], + ), ), - ), - const SizedBox(height: 12), - const Spacer(), - Consumer( - builder: (_, ref, __) { - return TextButton( - onPressed: () { - // TODO: [prio=med] needs more thought if this is still required - // ref - // .read(pWallets) - // .getWallet(walletId) - // .isActiveWallet = false; - ref - .read(transactionFilterProvider.state) - .state = null; - - Navigator.of(context).popUntil( - ModalRoute.withName(HomeView.routeName), - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Log out", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(height: 12), + const Spacer(), + Consumer( + builder: (_, ref, __) { + return TextButton( + onPressed: () { + // TODO: [prio=med] needs more thought if this is still required + // ref + // .read(pWallets) + // .getWallet(walletId) + // .isActiveWallet = false; + ref + .read(transactionFilterProvider.state) + .state = null; + + Navigator.of(context).popUntil( + ModalRoute.withName(HomeView.routeName), + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Log out", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart index cfca56bf2..af3f9123e 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart @@ -128,8 +128,9 @@ class _ChangeRepresentativeViewState } Future _copy() async { - await _clipboardInterface - .setData(ClipboardData(text: representative ?? "")); + await _clipboardInterface.setData( + ClipboardData(text: representative ?? ""), + ); if (mounted) { unawaited( showFloatingFlushBar( @@ -146,107 +147,99 @@ class _ChangeRepresentativeViewState Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Wallet representative", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.all(10), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - color: Theme.of(context) - .extension()! - .background, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.copy, - width: 24, - height: 24, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Wallet representative", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.all(10), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + color: + Theme.of( + context, + ).extension()!.background, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.copy, + width: 24, + height: 24, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: () { + if (representative != null) { + _copy(); + } + }, ), - onPressed: () { - if (representative != null) { - _copy(); - } - }, ), ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: child, ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, ), - child: child, ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 600, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 600, + maxHeight: double.infinity, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Change representative", - style: STextStyles.desktopH2(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Change representative", + style: STextStyles.desktopH2(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, + ), + ], ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + AnimatedSize( + duration: const Duration(milliseconds: 150), + child: Padding( + padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), + child: child, + ), ), ], ), - AnimatedSize( - duration: const Duration( - milliseconds: 150, - ), - child: Padding( - padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), - child: child, - ), - ), - ], - ), - ), + ), child: Column( children: [ if (isDesktop) const SizedBox(height: 24), ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: FutureBuilder( future: loadRepresentative(), builder: (context, AsyncSnapshot snapshot) { @@ -261,63 +254,54 @@ class _ChangeRepresentativeViewState child = const SizedBox( key: Key("loadingRepresentative"), height: height, - child: Center( - child: LoadingIndicator( - width: 100, - ), - ), + child: Center(child: LoadingIndicator(width: 100)), ); } else { child = Column( children: [ ConditionalParent( condition: !isDesktop, - builder: (child) => RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - ], - ), - ), + builder: + (child) => RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [child], + ), + ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Current representative", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - const SizedBox( - height: 4, - ), - Row( + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - child, + Text( + "Current representative", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 4), + Row(children: [child]), ], ), - ], - ), child: SelectableText( representative!, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ) + : STextStyles.itemSubtitle12(context), ), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -326,15 +310,18 @@ class _ChangeRepresentativeViewState autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _textController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: _textFocusNode, decoration: standardInputDecoration( "Enter new representative", @@ -342,54 +329,50 @@ class _ChangeRepresentativeViewState context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _textController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _textController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _textController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _textController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), if (isDesktop) const SizedBox(height: 60), if (!isDesktop) const Spacer(), - PrimaryButton( - label: "Save", - onPressed: _save, - ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + PrimaryButton(label: "Save", onPressed: _save), + if (!isDesktop) const SizedBox(height: 16), ], ); } return AnimatedSwitcher( - duration: const Duration( - milliseconds: 200, - ), + duration: const Duration(milliseconds: 200), child: child, ); }, diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart index 16c48cbb6..03ba8cdf0 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart @@ -55,7 +55,8 @@ class DeleteWalletRecoveryPhraseView extends ConsumerStatefulWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; final ClipboardInterface clipboardInterface; @@ -79,45 +80,47 @@ class _DeleteWalletRecoveryPhraseViewState showDialog( barrierDismissible: true, context: context, - builder: (_) => StackDialog( - title: "Thanks! Your wallet will be deleted.", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context).extension()!.accentColorDark, + builder: + (_) => StackDialog( + title: "Thanks! Your wallet will be deleted.", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - await ref.read(pWallets).deleteWallet( - ref.read(pWalletInfo(widget.walletId)), - ref.read(secureStoreProvider), - ); + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + await ref + .read(pWallets) + .deleteWallet( + ref.read(pWalletInfo(widget.walletId)), + ref.read(secureStoreProvider), + ); - if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(HomeView.routeName), - ); - } - }, - child: Text( - "Ok", - style: STextStyles.button(context), + if (mounted) { + Navigator.of( + context, + ).popUntil(ModalRoute.withName(HomeView.routeName)); + } + }, + child: Text("Ok", style: STextStyles.button(context)), + ), ), - ), - ), ); } finally { _lock = false; @@ -159,13 +162,15 @@ class _DeleteWalletRecoveryPhraseViewState Assets.svg.copy, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { - await _clipboardInterface - .setData(ClipboardData(text: _mnemonic.join(" "))); + await _clipboardInterface.setData( + ClipboardData(text: _mnemonic.join(" ")), + ); if (context.mounted) { unawaited( showFloatingFlushBar( @@ -182,209 +187,218 @@ class _DeleteWalletRecoveryPhraseViewState ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: frost - ? LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Text( - "Please write down your backup data. Keep it safe and " - "never share it with anyone. " - "Your backup data is the only way you can access your " - "funds if you forget your PIN, lose your phone, etc." - "\n\n" - "${AppConfig.appName} does not keep nor is able to restore " - "your backup data. " - "Only you have access to your wallet.", - style: STextStyles.label(context), - ), - ), - const SizedBox( - height: 24, - ), - // DetailItem( - // title: "My name", - // detail: frostWalletData!.myName, - // button: Util.isDesktop - // ? IconCopyButton( - // data: frostWalletData!.myName, - // ) - // : SimpleCopyButton( - // data: frostWalletData!.myName, - // ), - // ), - // const SizedBox( - // height: 16, - // ), - DetailItem( - title: "Multisig config", - detail: widget.frostWalletData!.config, - button: Util.isDesktop - ? IconCopyButton( - data: widget.frostWalletData!.config, - ) - : SimpleCopyButton( - data: widget.frostWalletData!.config, - ), - ), - const SizedBox( - height: 16, - ), - DetailItem( - title: "Keys", - detail: widget.frostWalletData!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: widget.frostWalletData!.keys, - ) - : SimpleCopyButton( - data: widget.frostWalletData!.keys, - ), - ), - if (prevGen) - const SizedBox( - height: 24, - ), - if (prevGen) - RoundedWhiteContainer( - child: Text( - "Previous generation info", - style: STextStyles.label(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + frost + ? LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Text( + "Please write down your backup data. Keep it safe and " + "never share it with anyone. " + "Your backup data is the only way you can access your " + "funds if you forget your PIN, lose your phone, etc." + "\n\n" + "${AppConfig.appName} does not keep nor is able to restore " + "your backup data. " + "Only you have access to your wallet.", + style: STextStyles.label(context), + ), + ), + const SizedBox(height: 24), + // DetailItem( + // title: "My name", + // detail: frostWalletData!.myName, + // button: Util.isDesktop + // ? IconCopyButton( + // data: frostWalletData!.myName, + // ) + // : SimpleCopyButton( + // data: frostWalletData!.myName, + // ), + // ), + // const SizedBox( + // height: 16, + // ), + DetailItem( + title: "Multisig config", + detail: widget.frostWalletData!.config, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .config, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .config, + ), + ), + const SizedBox(height: 16), + DetailItem( + title: "Keys", + detail: widget.frostWalletData!.keys, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget.frostWalletData!.keys, + ) + : SimpleCopyButton( + data: + widget.frostWalletData!.keys, + ), ), - ), - if (prevGen) - const SizedBox( - height: 12, - ), - if (prevGen) - DetailItem( - title: "Previous multisig config", - detail: - widget.frostWalletData!.prevGen!.config, - button: Util.isDesktop - ? IconCopyButton( - data: widget - .frostWalletData!.prevGen!.config, - ) - : SimpleCopyButton( - data: widget - .frostWalletData!.prevGen!.config, - ), - ), - if (prevGen) - const SizedBox( - height: 16, - ), - if (prevGen) - DetailItem( - title: "Previous keys", - detail: widget.frostWalletData!.prevGen!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: widget - .frostWalletData!.prevGen!.keys, - ) - : SimpleCopyButton( - data: widget - .frostWalletData!.prevGen!.keys, - ), - ), + if (prevGen) const SizedBox(height: 24), + if (prevGen) + RoundedWhiteContainer( + child: Text( + "Previous generation info", + style: STextStyles.label(context), + ), + ), + if (prevGen) const SizedBox(height: 12), + if (prevGen) + DetailItem( + title: "Previous multisig config", + detail: + widget + .frostWalletData! + .prevGen! + .config, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .config, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .config, + ), + ), + if (prevGen) const SizedBox(height: 16), + if (prevGen) + DetailItem( + title: "Previous keys", + detail: + widget.frostWalletData!.prevGen!.keys, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .keys, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .keys, + ), + ), - const Spacer(), - const SizedBox( - height: 16, - ), - PrimaryButton( - label: "Continue", - onPressed: _continuePressed, + const Spacer(), + const SizedBox(height: 16), + PrimaryButton( + label: "Continue", + onPressed: _continuePressed, + ), + ], ), - ], + ), ), + ); + }, + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 4), + Text( + ref.watch(pWalletName(widget.walletId)), + textAlign: TextAlign.center, + style: STextStyles.label( + context, + ).copyWith(fontSize: 12), ), - ), - ); - }, - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 4, - ), - Text( - ref.watch(pWalletName(widget.walletId)), - textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - const SizedBox( - height: 4, - ), - Text( - "Recovery Phrase", - textAlign: TextAlign.center, - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 16, - ), - Container( - decoration: BoxDecoration( - color: - Theme.of(context).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 4), + Text( + "Recovery Phrase", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH1(context), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - "Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.", - style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(height: 16), + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.", + style: STextStyles.label(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), ), ), - ), - ), - const SizedBox( - height: 8, - ), - Expanded( - child: SingleChildScrollView( - child: MnemonicTable( - words: _mnemonic, - isDesktop: false, + const SizedBox(height: 8), + Expanded( + child: SingleChildScrollView( + child: MnemonicTable( + words: _mnemonic, + isDesktop: false, + ), + ), ), - ), - ), - const SizedBox( - height: 16, - ), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: _continuePressed, - child: Text( - "Continue", - style: STextStyles.button(context), - ), + const SizedBox(height: 16), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: _continuePressed, + child: Text( + "Continue", + style: STextStyles.button(context), + ), + ), + ], ), - ], - ), + ), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart index 39a723d66..d6bc5f2e2 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart @@ -26,10 +26,7 @@ import 'delete_view_only_wallet_keys_view.dart'; import 'delete_wallet_recovery_phrase_view.dart'; class DeleteWalletWarningView extends ConsumerWidget { - const DeleteWalletWarningView({ - super.key, - required this.walletId, - }); + const DeleteWalletWarningView({super.key, required this.walletId}); static const String routeName = "/deleteWalletWarning"; @@ -47,143 +44,132 @@ class DeleteWalletWarningView extends ConsumerWidget { }, ), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 32, - ), - Center( - child: Text( - "Attention!", - style: STextStyles.pageTitleH1(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 32), + Center( + child: Text( + "Attention!", + style: STextStyles.pageTitleH1(context), + ), ), - ), - const SizedBox( - height: 16, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, - child: Text( - "You are going to permanently delete your wallet.\n\n" - "If you delete your wallet, the only way you can have access" - " to your funds is by using your backup key.\n\n" - "${AppConfig.appName} does not keep nor is able to restore " - "your backup key or your wallet.\n\nPLEASE SAVE YOUR BACKUP KEY.", - style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + const SizedBox(height: 16), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.warningBackground, + child: Text( + "You are going to permanently delete your wallet.\n\n" + "If you delete your wallet, the only way you can have access" + " to your funds is by using your backup key.\n\n" + "${AppConfig.appName} does not keep nor is able to restore " + "your backup key or your wallet.\n\nPLEASE SAVE YOUR BACKUP KEY.", + style: STextStyles.baseXS(context).copyWith( + color: + Theme.of( + context, + ).extension()!.warningForeground, + ), ), ), - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), ), ), - ), - const SizedBox( - height: 12, - ), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - final wallet = ref.read(pWallets).getWallet(walletId); + const SizedBox(height: 12), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + final wallet = ref.read(pWallets).getWallet(walletId); - // TODO: [prio=med] take wallets that don't have a mnemonic into account + // TODO: [prio=med] take wallets that don't have a mnemonic into account - List? mnemonic; - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData; - ViewOnlyWalletData? viewOnlyData; + List? mnemonic; + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData; + ViewOnlyWalletData? viewOnlyData; - if (wallet is BitcoinFrostWallet) { - final futures = [ - wallet.getSerializedKeys(), - wallet.getMultisigConfig(), - wallet.getSerializedKeysPrevGen(), - wallet.getMultisigConfigPrevGen(), - ]; + if (wallet is BitcoinFrostWallet) { + final futures = [ + wallet.getSerializedKeys(), + wallet.getMultisigConfig(), + wallet.getSerializedKeysPrevGen(), + wallet.getMultisigConfigPrevGen(), + ]; - final results = await Future.wait(futures); + final results = await Future.wait(futures); - if (results.length == 4) { - frostWalletData = ( - myName: wallet.frostInfo.myName, - config: results[1]!, - keys: results[0]!, - prevGen: results[2] == null || results[3] == null - ? null - : ( - config: results[3]!, - keys: results[2]!, - ), - ); - } - } else { - if (wallet is ViewOnlyOptionInterface && - wallet.isViewOnly) { - viewOnlyData = await wallet.getViewOnlyWalletData(); - } else if (wallet is MnemonicInterface) { - mnemonic = await wallet.getMnemonicAsWords(); - } - } - if (context.mounted) { - if (viewOnlyData != null) { - await Navigator.of(context).pushNamed( - DeleteViewOnlyWalletKeysView.routeName, - arguments: ( - walletId: walletId, - data: viewOnlyData, - ), - ); + if (results.length == 4) { + frostWalletData = ( + myName: wallet.frostInfo.myName, + config: results[1]!, + keys: results[0]!, + prevGen: + results[2] == null || results[3] == null + ? null + : (config: results[3]!, keys: results[2]!), + ); + } } else { - await Navigator.of(context).pushNamed( - DeleteWalletRecoveryPhraseView.routeName, - arguments: ( - walletId: walletId, - mnemonicWords: mnemonic ?? [], - frostWalletData: frostWalletData, - ), - ); + if (wallet is ViewOnlyOptionInterface && + wallet.isViewOnly) { + viewOnlyData = await wallet.getViewOnlyWalletData(); + } else if (wallet is MnemonicInterface) { + mnemonic = await wallet.getMnemonicAsWords(); + } + } + if (context.mounted) { + if (viewOnlyData != null) { + await Navigator.of(context).pushNamed( + DeleteViewOnlyWalletKeysView.routeName, + arguments: (walletId: walletId, data: viewOnlyData), + ); + } else { + await Navigator.of(context).pushNamed( + DeleteWalletRecoveryPhraseView.routeName, + arguments: ( + walletId: walletId, + mnemonicWords: mnemonic ?? [], + frostWalletData: frostWalletData, + ), + ); + } } - } - }, - child: Text( - "View Backup Key", - style: STextStyles.button(context), + }, + child: Text( + "View Backup Key", + style: STextStyles.button(context), + ), ), - ), - const SizedBox( - height: 16, - ), - ], + const SizedBox(height: 16), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart index 61d497452..f1d0aa5f9 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart @@ -22,10 +22,7 @@ import '../../../../widgets/stack_text_field.dart'; import '../../../../widgets/textfield_icon_button.dart'; class EditRefreshHeightView extends ConsumerStatefulWidget { - const EditRefreshHeightView({ - super.key, - required this.walletId, - }); + const EditRefreshHeightView({super.key, required this.walletId}); static const String routeName = "/editRefreshHeightView"; @@ -92,8 +89,10 @@ class _EditRefreshHeightViewState extends ConsumerState { void initState() { super.initState(); _wallet = ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet; - _controller = TextEditingController() - ..text = _wallet.libMoneroWallet!.getRefreshFromBlockHeight().toString(); + _controller = + TextEditingController() + ..text = + _wallet.libMoneroWallet!.getRefreshFromBlockHeight().toString(); } @override @@ -119,10 +118,8 @@ class _EditRefreshHeightViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.end, children: [ DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, ), ], ), @@ -130,9 +127,7 @@ class _EditRefreshHeightViewState extends ConsumerState { padding: const EdgeInsets.symmetric(horizontal: 32), child: child, ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ); @@ -155,9 +150,8 @@ class _EditRefreshHeightViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), ), ), ); @@ -173,11 +167,12 @@ class _EditRefreshHeightViewState extends ConsumerState { key: const Key("restoreHeightFieldKey"), controller: _controller, focusNode: _focusNode, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), + style: + Util.isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2) + : STextStyles.field(context), enableSuggestions: false, autocorrect: false, autofocus: true, @@ -188,48 +183,39 @@ class _EditRefreshHeightViewState extends ConsumerState { _focusNode, context, ).copyWith( - suffixIcon: _controller.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: ConditionalParent( - condition: Util.isDesktop, - builder: (child) => SizedBox( - height: 70, - child: child, - ), - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _controller.text = ""; - }); - }, - ), - ], + suffixIcon: + _controller.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: ConditionalParent( + condition: Util.isDesktop, + builder: + (child) => + SizedBox(height: 70, child: child), + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _controller.text = ""; + }); + }, + ), + ], + ), ), ), - ), - ) - : Util.isDesktop - ? const SizedBox( - height: 70, - ) + ) + : Util.isDesktop + ? const SizedBox(height: 70) : null, ), ), ), - Util.isDesktop - ? const SizedBox( - height: 32, - ) - : const Spacer(), - PrimaryButton( - label: "Save", - onPressed: _save, - ), + Util.isDesktop ? const SizedBox(height: 32) : const Spacer(), + PrimaryButton(label: "Save", onPressed: _save), ], ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart index da8c328bf..accd91416 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart @@ -31,10 +31,7 @@ import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/stack_dialog.dart'; class LelantusSettingsView extends ConsumerStatefulWidget { - const LelantusSettingsView({ - super.key, - required this.walletId, - }); + const LelantusSettingsView({super.key, required this.walletId}); static const String routeName = "/lelantusSettings"; @@ -54,12 +51,12 @@ class _LelantusSettingsViewState extends ConsumerState { try { // Toggle enableLelantusScanning in wallet info. - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.enableLelantusScanning: newValue, - }, - isar: ref.read(mainDBProvider).isar, - ); + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.enableLelantusScanning: newValue}, + isar: ref.read(mainDBProvider).isar, + ); if (newValue) { await _doRescanMaybe(); } @@ -75,7 +72,8 @@ class _LelantusSettingsViewState extends ConsumerState { builder: (context) { return StackDialog( title: "Rescan may be required", - message: "A blockchain rescan may be required to fully recover all " + message: + "A blockchain rescan may be required to fully recover all " "lelantus history. This may take a while.", leftButton: SecondaryButton( label: "Rescan now", @@ -98,12 +96,14 @@ class _LelantusSettingsViewState extends ConsumerState { Exception? e; if (mounted) { await showLoading( - whileFuture: ref.read(pWallets).getWallet(widget.walletId).recover( - isRescan: true, - ), + whileFuture: ref + .read(pWallets) + .getWallet(widget.walletId) + .recover(isRescan: true), context: context, message: "Rescanning blockchain", - subMessage: "This may take a while." + subMessage: + "This may take a while." "\nPlease do not exit this screen.", rootNavigator: Util.isDesktop, onException: (ex) => e = ex, @@ -121,22 +121,26 @@ class _LelantusSettingsViewState extends ConsumerState { context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => StackDialog( + title: "Rescan failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of( + context, + rootNavigator: Util.isDesktop, + ).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: Util.isDesktop).pop(); - }, - ), - ), ); } } finally { @@ -161,44 +165,47 @@ class _LelantusSettingsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId) - .select((value) => value.otherData), - )[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false, - onValueChanged: _switchToggled, - ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.smallMed12(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableLelantusScanning] + as bool? ?? + false, + onValueChanged: _switchToggled, ), - // Text( - // detail, - // style: STextStyles.desktopTextExtraExtraSmall(context), - // ), - ], - ), - ], - ), - ], + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Lelantus transactions", + style: STextStyles.smallMed12(context), + ), + // Text( + // detail, + // style: STextStyles.desktopTextExtraExtraSmall(context), + // ), + ], + ), + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart index 088b33379..aefbe6e79 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart @@ -11,10 +11,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; class RbfSettingsView extends ConsumerStatefulWidget { - const RbfSettingsView({ - super.key, - required this.walletId, - }); + const RbfSettingsView({super.key, required this.walletId}); static const String routeName = "/rbfSettings"; @@ -34,12 +31,12 @@ class _RbfSettingsViewState extends ConsumerState { try { // Toggle enableOptInRbf in wallet info. - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.enableOptInRbf: newValue, - }, - isar: ref.read(mainDBProvider).isar, - ); + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.enableOptInRbf: newValue}, + isar: ref.read(mainDBProvider).isar, + ); } finally { // ensure _switchRbfToggledLock is set to false no matter what _switchRbfToggledLock = false; @@ -57,46 +54,46 @@ class _RbfSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "RBF settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("RBF settings", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId) - .select((value) => value.otherData), - )[WalletInfoKeys.enableOptInRbf] as bool? ?? - false, - onValueChanged: _switchRbfToggled, - ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Enable opt-in RBF", - style: STextStyles.w600_20(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableOptInRbf] + as bool? ?? + false, + onValueChanged: _switchRbfToggled, ), - ], - ), - ], - ), - ], + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Enable opt-in RBF", + style: STextStyles.w600_20(context), + ), + ], + ), + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart index 319cc067f..04991bbb3 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart @@ -12,6 +12,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../../../notifications/show_flush_bar.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -26,10 +27,7 @@ import '../../../../widgets/stack_text_field.dart'; import '../../../../widgets/textfield_icon_button.dart'; class RenameWalletView extends ConsumerStatefulWidget { - const RenameWalletView({ - super.key, - required this.walletId, - }); + const RenameWalletView({super.key, required this.walletId}); static const String routeName = "/renameWallet"; @@ -73,105 +71,104 @@ class _RenameWalletViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Rename wallet", - style: STextStyles.navBarTitle(context), - ), + title: Text("Rename wallet", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _controller, - focusNode: _focusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Wallet name", - _focusNode, - context, - ).copyWith( - suffixIcon: _controller.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _controller.text = ""; - }); - }, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _controller, + focusNode: _focusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Wallet name", + _focusNode, + context, + ).copyWith( + suffixIcon: + _controller.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _controller.text = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - final newName = _controller.text; + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + final newName = _controller.text; - String? errMessage; - try { - await ref.read(pWalletInfo(walletId)).updateName( - newName: newName, - isar: ref.read(mainDBProvider).isar, - ); - } catch (e) { - if (e - .toString() - .contains("Empty wallet name not allowed!")) { - errMessage = "Empty wallet name not allowed."; - } else { - errMessage = e.toString(); + String? errMessage; + try { + await ref + .read(pWalletInfo(walletId)) + .updateName( + newName: newName, + isar: ref.read(mainDBProvider).isar, + ); + } catch (e) { + if (e.toString().contains( + "Empty wallet name not allowed!", + )) { + errMessage = "Empty wallet name not allowed."; + } else { + errMessage = e.toString(); + } } - } - if (mounted) { - if (errMessage == null) { - Navigator.of(context).pop(); - unawaited( - showFloatingFlushBar( - type: FlushBarType.success, - message: "Wallet renamed", - context: context, - ), - ); - } else { - unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Wallet named \"$newName\" already exists", - context: context, - ), - ); + if (mounted) { + if (errMessage == null) { + Navigator.of(context).pop(); + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Wallet renamed", + context: context, + ), + ); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Wallet named \"$newName\" already exists", + context: context, + ), + ); + } } - } - }, - child: Text( - "Save", - style: STextStyles.button(context), + }, + child: Text("Save", style: STextStyles.button(context)), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart index 934736311..99bd2f94c 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart @@ -10,10 +10,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/detail_item.dart'; class SparkInfoView extends ConsumerWidget { - const SparkInfoView({ - super.key, - required this.walletId, - }); + const SparkInfoView({super.key, required this.walletId}); static const String routeName = "/sparkInfo"; @@ -30,33 +27,32 @@ class SparkInfoView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Spark Info", - style: STextStyles.navBarTitle(context), - ), + title: Text("Spark Info", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FutureBuilder( - future: FiroCacheCoordinator.getSparkCacheSize( - ref.watch(pWalletCoin(walletId)).network, - ), - builder: (_, snapshot) { - String detail = "Loading..."; - if (snapshot.connectionState == ConnectionState.done) { - detail = snapshot.data ?? detail; - } + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FutureBuilder( + future: FiroCacheCoordinator.getSparkCacheSize( + ref.watch(pWalletCoin(walletId)).network, + ), + builder: (_, snapshot) { + String detail = "Loading..."; + if (snapshot.connectionState == ConnectionState.done) { + detail = snapshot.data ?? detail; + } - return DetailItem( - title: "Spark electrumx cache size", - detail: detail, - ); - }, - ), - ], + return DetailItem( + title: "Spark electrumx cache size", + detail: detail, + ); + }, + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index 3917f743e..dc446fef6 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -180,49 +180,17 @@ class _WalletSettingsWalletSettingsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.only(top: 12, left: 16, right: 16), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - RenameWalletView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, - ), - child: Row( - children: [ - Text( - "Rename wallet", - style: STextStyles.titleBold12(context), - ), - ], - ), - ), - ), - ), - if (wallet is RbfInterface) const SizedBox(height: 8), - if (wallet is RbfInterface) + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -231,7 +199,7 @@ class _WalletSettingsWalletSettingsViewState materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () { Navigator.of(context).pushNamed( - RbfSettingsView.routeName, + RenameWalletView.routeName, arguments: widget.walletId, ); }, @@ -243,7 +211,7 @@ class _WalletSettingsWalletSettingsViewState child: Row( children: [ Text( - "RBF settings", + "Rename wallet", style: STextStyles.titleBold12(context), ), ], @@ -251,186 +219,318 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) - const SizedBox(height: 8), - if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (wallet is RbfInterface) const SizedBox(height: 8), + if (wallet is RbfInterface) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + RbfSettingsView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "RBF settings", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), - onPressed: _switchReuseAddressToggled, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + ), + if (wallet is MultiAddressInterface && + !isViewOnlyNoAddressGen) + const SizedBox(height: 8), + if (wallet is MultiAddressInterface && + !isViewOnlyNoAddressGen) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Reuse receiving address", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: IgnorePointer( - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData, - ), - )[WalletInfoKeys.reuseAddress] - as bool? ?? - false, - controller: _switchController, + onPressed: _switchReuseAddressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Reuse receiving address", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select( + (value) => value.otherData, + ), + )[WalletInfoKeys.reuseAddress] + as bool? ?? + false, + controller: _switchController, + ), ), ), - ), - ], + ], + ), ), ), ), - ), - if (!ref.watch(pDuress)) const SizedBox(height: 8), - if (!ref.watch(pDuress)) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: _switchDuressToggled, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Show in duress", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: IgnorePointer( - child: DraggableSwitch( - value: - ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData, - ), - )[WalletInfoKeys - .duressMarkedVisibleWalletKey] - as bool? ?? - false, - onChanged: (_) => (), + onPressed: _switchDuressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Show in duress", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitch( + value: + ref.watch( + pWalletInfo( + widget.walletId, + ).select( + (value) => value.otherData, + ), + )[WalletInfoKeys + .duressMarkedVisibleWalletKey] + as bool? ?? + false, + onChanged: (_) => (), + ), ), ), - ), - ], + ], + ), ), ), ), - ), - if (wallet is LelantusInterface && !wallet.isViewOnly) - const SizedBox(height: 8), - if (wallet is LelantusInterface && !wallet.isViewOnly) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - LelantusSettingsView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + if (wallet is LelantusInterface && !wallet.isViewOnly) + const SizedBox(height: 8), + if (wallet is LelantusInterface && !wallet.isViewOnly) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Lelantus settings", - style: STextStyles.titleBold12(context), - ), - ], + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + LelantusSettingsView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Lelantus settings", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), ), - ), - if (wallet is SparkInterface && !wallet.isViewOnly) - const SizedBox(height: 8), - if (wallet is SparkInterface && !wallet.isViewOnly) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (wallet is SparkInterface && !wallet.isViewOnly) + const SizedBox(height: 8), + if (wallet is SparkInterface && !wallet.isViewOnly) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + SparkInfoView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Spark info", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - SparkInfoView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + ), + if (wallet is LibMoneroWallet) const SizedBox(height: 8), + if (wallet is LibMoneroWallet) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Spark info", - style: STextStyles.titleBold12(context), - ), - ], + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + EditRefreshHeightView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Restore height", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), ), - ), - if (wallet is LibMoneroWallet) const SizedBox(height: 8), - if (wallet is LibMoneroWallet) + const SizedBox(height: 8), RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: const EdgeInsets.all(0), onPressed: () { - Navigator.of(context).pushNamed( - EditRefreshHeightView.routeName, - arguments: widget.walletId, + showDialog( + barrierDismissible: true, + context: context, + builder: + (_) => StackDialog( + title: + "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen", + ), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), + ), ); }, child: Padding( @@ -441,7 +541,7 @@ class _WalletSettingsWalletSettingsViewState child: Row( children: [ Text( - "Restore height", + "Delete wallet", style: STextStyles.titleBold12(context), ), ], @@ -449,100 +549,8 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - const SizedBox(height: 8), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: const EdgeInsets.all(0), - onPressed: () { - showDialog( - barrierDismissible: true, - context: context, - builder: - (_) => StackDialog( - title: - "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: - widget.walletId, - showBackButton: true, - routeOnSuccess: - DeleteWalletWarningView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: - "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen", - ), - ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), - ), - ), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, - ), - child: Row( - children: [ - Text( - "Delete wallet", - style: STextStyles.titleBold12(context), - ), - ], - ), - ), - ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart index 2eddd3078..35a46d6b4 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart @@ -87,115 +87,106 @@ class XPubViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Wallet xpub(s)", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: Column( - children: [ - Expanded( - child: child, - ), - const SizedBox( - height: 16, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Wallet xpub(s)", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: LayoutBuilder( + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + children: [ + Expanded(child: child), + const SizedBox(height: 16), + ], + ), + ), + ), ), - ], - ), ), ), ), ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 600, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 600, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "${ref.watch(pWalletName(widget.walletId))} xpub(s)", - style: STextStyles.desktopH2(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "${ref.watch(pWalletName(widget.walletId))} xpub(s)", + style: STextStyles.desktopH2(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, + ), + ], ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + Flexible( + child: Padding( + padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), + child: SingleChildScrollView(child: child), + ), ), ], ), - Flexible( - child: Padding( - padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), - child: SingleChildScrollView( - child: child, - ), - ), - ), - ], - ), - ), + ), child: Column( mainAxisSize: Util.isDesktop ? MainAxisSize.min : MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), DetailItem( title: "Master fingerprint", detail: widget.xpubData.fingerprint, horizontal: true, - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, - ), - SizedBox( - height: Util.isDesktop ? 12 : 16, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, ), + SizedBox(height: Util.isDesktop ? 12 : 16), DetailItemBase( horizontal: true, - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, title: Text( "Derivation", style: STextStyles.itemSubtitle(context), @@ -226,9 +217,10 @@ class XPubViewState extends ConsumerState { isExpanded: true, buttonStyleData: ButtonStyleData( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -241,9 +233,10 @@ class XPubViewState extends ConsumerState { Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), ), @@ -251,9 +244,10 @@ class XPubViewState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -269,46 +263,34 @@ class XPubViewState extends ConsumerState { ), ), ), - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), QR( data: _current(_currentDropDownValue), - size: Util.isDesktop - ? 256 - : MediaQuery.of(context).size.width / 1.5, - ), - SizedBox( - height: Util.isDesktop ? 12 : 16, + size: + Util.isDesktop + ? 256 + : MediaQuery.of(context).size.width / 1.5, ), + SizedBox(height: Util.isDesktop ? 12 : 16), RoundedWhiteContainer( - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, child: SelectableText( _current(_currentDropDownValue), style: STextStyles.w500_14(context), ), ), - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), if (!Util.isDesktop) const Spacer(), Row( children: [ if (Util.isDesktop) const Spacer(), - if (Util.isDesktop) - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Copy", - onPressed: _copy, - ), - ), + if (Util.isDesktop) const SizedBox(width: 16), + Expanded(child: PrimaryButton(label: "Copy", onPressed: _copy)), ], ), ], diff --git a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart index 011532708..c98409dfd 100644 --- a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart +++ b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart @@ -269,29 +269,31 @@ class _ConfirmSparkNameTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, 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: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, 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: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/special/firo_rescan_recovery_error_dialog.dart b/lib/pages/special/firo_rescan_recovery_error_dialog.dart index fa59d841a..b703d69c2 100644 --- a/lib/pages/special/firo_rescan_recovery_error_dialog.dart +++ b/lib/pages/special/firo_rescan_recovery_error_dialog.dart @@ -28,17 +28,10 @@ import '../pinpad_views/lock_screen_view.dart'; import '../settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart'; import '../settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart'; -enum FiroRescanRecoveryErrorViewOption { - retry, - showMnemonic, - deleteWallet; -} +enum FiroRescanRecoveryErrorViewOption { retry, showMnemonic, deleteWallet } class FiroRescanRecoveryErrorView extends ConsumerStatefulWidget { - const FiroRescanRecoveryErrorView({ - super.key, - required this.walletId, - }); + const FiroRescanRecoveryErrorView({super.key, required this.walletId}); static const String routeName = "/firoRescanRecoveryErrorView"; @@ -71,20 +64,21 @@ class _FiroRescanRecoveryErrorViewState final result = await showDialog( context: context, barrierDismissible: false, - builder: (context) => Navigator( - initialRoute: DesktopDeleteWalletDialog.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - RouteGenerator.generateRoute( - RouteSettings( - name: DesktopDeleteWalletDialog.routeName, - arguments: widget.walletId, - ), - ), - ]; - }, - ), + builder: + (context) => Navigator( + initialRoute: DesktopDeleteWalletDialog.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + RouteGenerator.generateRoute( + RouteSettings( + name: DesktopDeleteWalletDialog.routeName, + arguments: widget.walletId, + ), + ), + ]; + }, + ), ); if (result == true) { @@ -119,82 +113,97 @@ class _FiroRescanRecoveryErrorViewState child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( - semanticsLabel: "Delete wallet button. " + semanticsLabel: + "Delete wallet button. " "Start process of deleting current wallet.", key: const Key("walletViewRadioButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.trash, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { - final walletName = - ref.read(pWalletName(widget.walletId)); + final walletName = ref.read( + pWalletName(widget.walletId), + ); await showDialog( barrierDismissible: true, context: context, - builder: (_) => StackDialog( - title: "Do you want to delete $walletName?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) + builder: + (_) => StackDialog( + title: "Do you want to delete $walletName?", + leftButton: TextButton( + style: Theme.of(context) .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: - widget.walletId, - showBackButton: true, - routeOnSuccess: - DeleteWalletWarningView.routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: - "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen", + .getSecondaryEnabledButtonStyle( + context, + ), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle( + context, + ), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen", + ), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), ), - ), - ), ); }, ), @@ -202,9 +211,11 @@ class _FiroRescanRecoveryErrorViewState ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), ), ), ); @@ -217,25 +228,23 @@ class _FiroRescanRecoveryErrorViewState "Failed to rescan Firo wallet", style: STextStyles.pageTitleH2(context), ), - Util.isDesktop - ? const SizedBox( - height: 60, - ) - : const Spacer(), + Util.isDesktop ? const SizedBox(height: 60) : const Spacer(), BranchedParent( condition: Util.isDesktop, - conditionBranchBuilder: (children) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: children, - ), - otherBranchBuilder: (children) => Row( - children: [ - Expanded(child: children[0]), - children[1], - Expanded(child: children[2]), - ], - ), + conditionBranchBuilder: + (children) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: children, + ), + otherBranchBuilder: + (children) => Row( + children: [ + Expanded(child: children[0]), + children[1], + Expanded(child: children[2]), + ], + ), children: [ SecondaryButton( label: "Show mnemonic", @@ -245,24 +254,26 @@ class _FiroRescanRecoveryErrorViewState await showDialog( context: context, barrierDismissible: false, - builder: (context) => Navigator( - initialRoute: UnlockWalletKeysDesktop.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - RouteGenerator.generateRoute( - RouteSettings( - name: UnlockWalletKeysDesktop.routeName, - arguments: widget.walletId, - ), - ), - ]; - }, - ), + builder: + (context) => Navigator( + initialRoute: UnlockWalletKeysDesktop.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + RouteGenerator.generateRoute( + RouteSettings( + name: UnlockWalletKeysDesktop.routeName, + arguments: widget.walletId, + ), + ), + ]; + }, + ), ); } else { - final wallet = - ref.read(pWallets).getWallet(widget.walletId); + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); // TODO: [prio=low] take wallets that don't have a mnemonic into account if (wallet is MnemonicInterface) { final mnemonic = await wallet.getMnemonicAsWords(); @@ -280,20 +291,22 @@ class _FiroRescanRecoveryErrorViewState RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: ( - walletId: widget.walletId, - mnemonic: mnemonic, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: WalletBackupView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: - "View recovery phrase", - ), + builder: + (_) => LockscreenView( + routeOnSuccessArguments: ( + walletId: widget.walletId, + mnemonic: mnemonic, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + WalletBackupView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", + ), settings: const RouteSettings( name: "/viewRecoverPhraseLockscreen", ), @@ -304,17 +317,12 @@ class _FiroRescanRecoveryErrorViewState } }, ), - const SizedBox( - width: 16, - height: 16, - ), + const SizedBox(width: 16, height: 16), PrimaryButton( label: "Retry", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: () { - Navigator.of(context).pop( - true, - ); + Navigator.of(context).pop(true); }, ), ], diff --git a/lib/pages/token_view/my_tokens_view.dart b/lib/pages/token_view/my_tokens_view.dart index eef37ced9..10e84751b 100644 --- a/lib/pages/token_view/my_tokens_view.dart +++ b/lib/pages/token_view/my_tokens_view.dart @@ -13,8 +13,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import '../add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; -import 'sub_widgets/my_tokens_list.dart'; + import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; @@ -27,12 +26,11 @@ import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/icon_widgets/x_icon.dart'; import '../../widgets/stack_text_field.dart'; import '../../widgets/textfield_icon_button.dart'; +import '../add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; +import 'sub_widgets/my_tokens_list.dart'; class MyTokensView extends ConsumerStatefulWidget { - const MyTokensView({ - super.key, - required this.walletId, - }); + const MyTokensView({super.key, required this.walletId}); static const String routeName = "/myTokens"; final String walletId; @@ -68,78 +66,80 @@ class _MyTokensViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "${ref.watch( - pWalletName(widget.walletId), - )} Tokens", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "${ref.watch(pWalletName(widget.walletId))} Tokens", + style: STextStyles.navBarTitle(context), ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("addTokenAppBarIconButtonKey"), - size: 36, - shadows: const [], - color: - Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - width: 20, - height: 20, + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 20, ), - onPressed: () async { - final result = await Navigator.of(context).pushNamed( - EditWalletTokensView.routeName, - arguments: widget.walletId, - ); + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("addTokenAppBarIconButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + width: 20, + height: 20, + ), + onPressed: () async { + final result = await Navigator.of(context).pushNamed( + EditWalletTokensView.routeName, + arguments: widget.walletId, + ); - if (mounted && result == 42) { - setState(() {}); - } - }, + if (mounted && result == 42) { + setState(() {}); + } + }, + ), + ), ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, ), - child: child, ), - ), - ), child: Column( children: [ Padding( @@ -148,14 +148,10 @@ class _MyTokensViewState extends ConsumerState { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -170,15 +166,18 @@ class _MyTokensViewState extends ConsumerState { _searchString = value; }); }, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Search...", searchFieldFocusNode, @@ -196,26 +195,27 @@ class _MyTokensViewState extends ConsumerState { height: isDesktop ? 20 : 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -224,9 +224,7 @@ class _MyTokensViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: MyTokensList( walletId: widget.walletId, diff --git a/lib/pages/token_view/token_view.dart b/lib/pages/token_view/token_view.dart index b6acc49c5..6063bd49f 100644 --- a/lib/pages/token_view/token_view.dart +++ b/lib/pages/token_view/token_view.dart @@ -53,9 +53,10 @@ class _TokenViewState extends ConsumerState { @override void initState() { - initialSyncStatus = ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced; + initialSyncStatus = + ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced; super.initState(); } @@ -108,14 +109,13 @@ class _TokenViewState extends ConsumerState { ), size: 24, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Flexible( child: Text( ref.watch( - pCurrentTokenWallet - .select((value) => value!.tokenContract.name), + pCurrentTokenWallet.select( + (value) => value!.tokenContract.name, + ), ), style: STextStyles.navBarTitle(context), overflow: TextOverflow.ellipsis, @@ -135,9 +135,10 @@ class _TokenViewState extends ConsumerState { child: AppBarIconButton( icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () { // todo: context menu @@ -146,7 +147,8 @@ class _TokenViewState extends ConsumerState { arguments: Tuple2( ref.watch( pCurrentTokenWallet.select( - (value) => value!.tokenContract.address), + (value) => value!.tokenContract.address, + ), ), widget.walletId, ), @@ -157,93 +159,90 @@ class _TokenViewState extends ConsumerState { ), ], ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Column( - children: [ - const SizedBox( - height: 10, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TokenSummary( - walletId: widget.walletId, - initialSyncStatus: initialSyncStatus, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Column( + children: [ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: TokenSummary( + walletId: widget.walletId, + initialSyncStatus: initialSyncStatus, + ), ), - ), - const SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transactions", - style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transactions", + style: STextStyles.itemSubtitle(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), ), - ), - CustomTextButton( - text: "See all", - onTap: () { - Navigator.of(context).pushNamed( - AllTransactionsV2View.routeName, - arguments: ( - walletId: widget.walletId, - contractAddress: ref.watch( - pCurrentTokenWallet.select( - (value) => value!.tokenContract.address, + CustomTextButton( + text: "See all", + onTap: () { + Navigator.of(context).pushNamed( + AllTransactionsV2View.routeName, + arguments: ( + walletId: widget.walletId, + contractAddress: ref.watch( + pCurrentTokenWallet.select( + (value) => value!.tokenContract.address, + ), ), ), - ), - ); - }, - ), - ], - ), - ), - const SizedBox( - height: 12, - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: ClipRRect( - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), - bottom: Radius.circular( - // TokenView.navBarHeight / 2.0, - Constants.size.circularBorderRadius, + ); + }, ), - ), - child: Container( - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular( + ], + ), + ), + const SizedBox(height: 12), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ClipRRect( + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + bottom: Radius.circular( + // TokenView.navBarHeight / 2.0, Constants.size.circularBorderRadius, ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TokenTransactionsList( - walletId: widget.walletId, - ), + child: Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: TokenTransactionsList( + walletId: widget.walletId, + ), + ), + ], + ), ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/wallet_view/transaction_views/edit_note_view.dart b/lib/pages/wallet_view/transaction_views/edit_note_view.dart index 4d0c584eb..bcb6202ec 100644 --- a/lib/pages/wallet_view/transaction_views/edit_note_view.dart +++ b/lib/pages/wallet_view/transaction_views/edit_note_view.dart @@ -12,7 +12,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../models/isar/models/transaction_note.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/constants.dart'; @@ -28,11 +27,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditNoteView extends ConsumerStatefulWidget { - const EditNoteView({ - super.key, - required this.txid, - required this.walletId, - }); + const EditNoteView({super.key, required this.txid, required this.walletId}); static const String routeName = "/editNote"; @@ -57,9 +52,7 @@ class _EditNoteViewState extends ConsumerState { _noteController = TextEditingController(); _note = ref.read( - pTransactionNote( - (txid: widget.txid, walletId: widget.walletId), - ), + pTransactionNote((txid: widget.txid, walletId: widget.walletId)), ); _noteController.text = _note?.value ?? ""; super.initState(); @@ -76,63 +69,56 @@ class _EditNoteViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit note", - style: STextStyles.navBarTitle(context), + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit note", + style: STextStyles.navBarTitle(context), + ), ), - ), body: MobileEditNoteScaffold( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), + padding: const EdgeInsets.only(left: 32, bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Edit note", - style: STextStyles.desktopH3(context), - ), + Text("Edit note", style: STextStyles.desktopH3(context)), const DesktopDialogCloseButton(), ], ), ), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -141,14 +127,18 @@ class _EditNoteViewState extends ConsumerState { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _noteController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: noteFieldFocusNode, decoration: standardInputDecoration( "Note", @@ -156,33 +146,35 @@ class _EditNoteViewState extends ConsumerState { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _noteController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -195,7 +187,9 @@ class _EditNoteViewState extends ConsumerState { child: PrimaryButton( label: "Save", onPressed: () async { - await ref.read(mainDBProvider).putTransactionNote( + await ref + .read(mainDBProvider) + .putTransactionNote( _note?.copyWith(value: _noteController.text) ?? TransactionNote( walletId: widget.walletId, @@ -213,7 +207,9 @@ class _EditNoteViewState extends ConsumerState { if (!isDesktop) TextButton( onPressed: () async { - await ref.read(mainDBProvider).putTransactionNote( + await ref + .read(mainDBProvider) + .putTransactionNote( _note?.copyWith(value: _noteController.text) ?? TransactionNote( walletId: widget.walletId, @@ -228,10 +224,7 @@ class _EditNoteViewState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), - ), + child: Text("Save", style: STextStyles.button(context)), ), ], ), @@ -242,10 +235,7 @@ class _EditNoteViewState extends ConsumerState { } class MobileEditNoteScaffold extends StatelessWidget { - const MobileEditNoteScaffold({ - super.key, - required this.child, - }); + const MobileEditNoteScaffold({super.key, required this.child}); final Widget child; @@ -254,24 +244,24 @@ class MobileEditNoteScaffold extends StatelessWidget { if (Util.isDesktop) { return child; } else { - return Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + return SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), - ), - ); - }, + ); + }, + ), ), ); } diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index edd0bff14..7dc810ac8 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -22,7 +22,6 @@ import 'package:url_launcher/url_launcher.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../notifications/show_flush_bar.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/address_book_service_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; @@ -419,405 +418,167 @@ class _TransactionDetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: - isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), - child: Column( - children: [ - if (isDesktop) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction details", - style: STextStyles.desktopH3(context), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: - isDesktop - ? const EdgeInsets.only(right: 32, bottom: 32) - : const EdgeInsets.all(0), - child: ConditionalParent( - condition: isDesktop, - builder: (child) { - return RoundedWhiteContainer( - borderColor: - isDesktop - ? Theme.of( - context, - ).extension()!.backgroundAppBar - : null, - padding: const EdgeInsets.all(0), - child: child, - ); - }, - child: SingleChildScrollView( - primary: isDesktop ? false : null, - child: Padding( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), - child: Container( - decoration: + body: ConditionalParent( + condition: !isDesktop, + builder: (child) => SafeArea(child: child), + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), + child: Column( + children: [ + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction details", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return RoundedWhiteContainer( + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, + padding: const EdgeInsets.all(0), + child: child, + ); + }, + child: SingleChildScrollView( + primary: isDesktop ? false : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: isDesktop - ? BoxDecoration( - color: - Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants - .size - .circularBorderRadius, - ), - ), - ) - : null, - child: Padding( - padding: + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), + child: Container( + decoration: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - if (isDesktop) - Row( - children: [ - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - const SizedBox(width: 16), - SelectableText( - _transaction.isCancelled - ? coin is Ethereum - ? "Failed" - : "Cancelled" - : whatIsIt( - _transaction, - currentHeight, - ), - style: - STextStyles.desktopTextMedium( - context, - ), + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ], - ), - Column( - crossAxisAlignment: - isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - SelectableText( - "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.titleBold12( + ) + : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + if (isDesktop) + Row( + children: [ + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + const SizedBox(width: 16), + SelectableText( + _transaction.isCancelled + ? coin is Ethereum + ? "Failed" + : "Cancelled" + : whatIsIt( + _transaction, + currentHeight, + ), + style: + STextStyles.desktopTextMedium( context, ), + ), + ], ), - const SizedBox(height: 2), - if (price != null) + Column( + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ SelectableText( - "$amountPrefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - ], - ), - if (!isDesktop) - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - ], - ), - ), - ), - ), - - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.isCancelled - ? coin is Ethereum - ? "Failed" - : "Cancelled" - : whatIsIt(_transaction, currentHeight), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - _transaction.type == - TransactionType - .outgoing - ? Theme.of(context) - .extension< - StackColors - >()! - .accentColorOrange - : Theme.of(context) - .extension< - StackColors - >()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], - ), - ), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: kDebugMode, - builder: (child) { - return Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - child, - CustomTextButton( - text: "Info", - onTap: () { - if (isDesktop) { - showDialog( - context: context, - builder: - ( - _, - ) => DesktopDialog( - maxHeight: - double - .infinity, - child: AddressDetailsView( - addressId: - _transaction - .address - .value! - .id, - walletId: - widget - .walletId, - ), - ), - ); - } else { - Navigator.of( - context, - ).pushNamed( - AddressDetailsView - .routeName, - arguments: Tuple2( - _transaction - .address - .value! - .id, - widget.walletId, - ), - ); - } - }, - ), - ], - ); - }, - child: Text( - _transaction.type == - TransactionType.outgoing - ? "Sent to" - : "Receiving address", + "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.titleBold12( context, ), ), - ), - const SizedBox(height: 8), - _transaction.type == - TransactionType.incoming - ? FutureBuilder( - future: fetchContactNameFor( - _transaction - .address - .value! - .value, - ), - builder: ( - builderContext, - AsyncSnapshot - snapshot, - ) { - String addressOrContactName = - _transaction - .address - .value! - .value; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - addressOrContactName = - snapshot.data!; - } - return SelectableText( - addressOrContactName, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ); - }, - ) - : SelectableText( - _transaction - .address - .value! - .value, + const SizedBox(height: 2), + if (price != null) + SelectableText( + "$amountPrefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), + ], + ), + if (!isDesktop) + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + ], ), - if (isDesktop) - IconCopyButton( - data: _transaction.address.value!.value, - ), - ], + ), ), ), - if (coin is Epiccash) + isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is Epiccash) RoundedWhiteContainer( padding: isDesktop @@ -826,219 +587,397 @@ class _TransactionDetailsViewState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "On chain note", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - SelectableText( - _transaction.otherData ?? "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + Text( + "Status", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.isCancelled + ? coin is Ethereum + ? "Failed" + : "Cancelled" + : whatIsIt( + _transaction, + currentHeight, ), - ], - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - IconCopyButton( - data: _transaction.otherData ?? "", - ), + // ), + // ), ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - (coin is Epiccash) - ? "Local Note" - : "Note ", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - isDesktop - ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: kDebugMode, + builder: (child) { + return Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + child, + CustomTextButton( + text: "Info", + onTap: () { + if (isDesktop) { + showDialog( + context: context, + builder: + ( + _, + ) => DesktopDialog( + maxHeight: + double + .infinity, + child: AddressDetailsView( + addressId: + _transaction + .address + .value! + .id, + walletId: + widget + .walletId, + ), + ), + ); + } else { + Navigator.of( + context, + ).pushNamed( + AddressDetailsView + .routeName, + arguments: Tuple2( + _transaction + .address + .value! + .id, + widget.walletId, + ), + ); + } + }, ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .infoItemIcons, - ), - const SizedBox(width: 4), - Text( - "Edit", - style: STextStyles.link2( - context, + ], + ); + }, + child: Text( + _transaction.type == + TransactionType.outgoing + ? "Sent to" + : "Receiving address", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ), + const SizedBox(height: 8), + _transaction.type == + TransactionType.incoming + ? FutureBuilder( + future: fetchContactNameFor( + _transaction + .address + .value! + .value, ), + builder: ( + builderContext, + AsyncSnapshot + snapshot, + ) { + String + addressOrContactName = + _transaction + .address + .value! + .value; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + addressOrContactName = + snapshot.data!; + } + return SelectableText( + addressOrContactName, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ); + }, + ) + : SelectableText( + _transaction + .address + .value! + .value, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ], - ), - ), + ], + ), + ), + if (isDesktop) + IconCopyButton( + data: + _transaction.address.value!.value, + ), ], ), - const SizedBox(height: 8), - SelectableText( - ref - .watch( - pTransactionNote(( - txid: _transaction.txid, - walletId: walletId, - )), - ) - ?.value ?? - "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( + ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Date", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "On chain note", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + const SizedBox(height: 8), + SelectableText( + _transaction.otherData ?? "", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), ), - if (isDesktop) const SizedBox(height: 2), if (isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), + IconCopyButton( + data: _transaction.otherData ?? "", + ), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + (coin is Epiccash) + ? "Local Note" + : "Note ", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( + ) + : STextStyles.itemSubtitle( + context, + ), + ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, color: Theme.of(context) .extension< StackColors >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + .infoItemIcons, ), - ), - ], - ), - if (!isDesktop) + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 8), SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), + ref + .watch( + pTransactionNote(( + txid: _transaction.txid, + walletId: walletId, + )), + ) + ?.value ?? + "", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1055,96 +994,44 @@ class _TransactionDetailsViewState context, ), ), - if (isDesktop) - IconCopyButton( - data: Format.extractDateFrom( - _transaction.timestamp, - ), - ), - ], + ], + ), ), - ), - if (coin is! NanoCurrency) isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is! NanoCurrency) RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), - child: Builder( - builder: (context) { - final String feeString = - showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - ) - ? ref - .watch( - pAmountFormatter(coin), - ) - .format( - fee, - withUnitName: isTokenTx, - ) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format( - fee, - withUnitName: isTokenTx, - ); - - return Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction fee", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - feeString, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], + Text( + "Date", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - if (!isDesktop) + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) SelectableText( - feeString, + Format.extractDateFrom( + _transaction.timestamp, + ), style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1161,62 +1048,73 @@ class _TransactionDetailsViewState context, ), ), - if (isDesktop) - IconCopyButton(data: feeString), ], - ); - }, - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - Builder( - builder: (context) { - final String height; - final String confirmations; - final confirms = _transaction.getConfirmations( - currentHeight, - ); - - if (widget.coin is Bitcoincash || - widget.coin is Ecash) { - height = - _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; - confirmations = confirms.toString(); - } else if (widget.coin is Epiccash && - _transaction.slateId == null) { - confirmations = "Unknown"; - height = "Unknown"; - } else { - final confirmed = _transaction.isConfirmed( - currentHeight, - minConfirms, - ); - if (widget.coin is! Epiccash && confirmed) { - height = - "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; - } else { - height = - confirms > 0 - ? "${_transaction.height}" - : "Pending"; - } - - confirmations = confirms.toString(); - } + ), + if (!isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, + ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (isDesktop) + IconCopyButton( + data: Format.extractDateFrom( + _transaction.timestamp, + ), + ), + ], + ), + ), + if (coin is! NanoCurrency) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is! NanoCurrency) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Builder( + builder: (context) { + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + ) + ? ref + .watch( + pAmountFormatter(coin), + ) + .format( + fee, + withUnitName: isTokenTx, + ) + : "Pending" + : ref + .watch(pAmountFormatter(coin)) + .format( + fee, + withUnitName: isTokenTx, + ); - return Column( - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: @@ -1227,7 +1125,7 @@ class _TransactionDetailsViewState CrossAxisAlignment.start, children: [ Text( - "Block height", + "Transaction fee", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1241,7 +1139,7 @@ class _TransactionDetailsViewState const SizedBox(height: 2), if (isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1264,7 +1162,7 @@ class _TransactionDetailsViewState ), if (!isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1282,144 +1180,310 @@ class _TransactionDetailsViewState ), ), if (isDesktop) - IconCopyButton(data: height), + IconCopyButton(data: feeString), ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", + ); + }, + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + Builder( + builder: (context) { + final String height; + final String confirmations; + final confirms = _transaction + .getConfirmations(currentHeight); + + if (widget.coin is Bitcoincash || + widget.coin is Ecash) { + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; + confirmations = confirms.toString(); + } else if (widget.coin is Epiccash && + _transaction.slateId == null) { + confirmations = "Unknown"; + height = "Unknown"; + } else { + final confirmed = _transaction.isConfirmed( + currentHeight, + minConfirms, + ); + if (widget.coin is! Epiccash && confirmed) { + height = + "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; + } else { + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; + } + + confirmations = confirms.toString(); + } + + return Column( + children: [ + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Block height", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + height, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + if (!isDesktop) + SelectableText( + height, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - confirmations, + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), - if (!isDesktop) - SelectableText( - confirmations, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], ), - if (isDesktop) - IconCopyButton(data: height), - ], - ), - ), - ], - ); - }, - ), - if (coin is Ethereum) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Ethereum) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Nonce", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.nonce.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + if (!isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ), - ], - ), + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + ], + ); + }, ), - if (kDebugMode) + if (coin is Ethereum) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Ethereum) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Nonce", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.nonce.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (kDebugMode) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (kDebugMode) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tx sub type", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.subType.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (kDebugMode) RoundedWhiteContainer( padding: isDesktop @@ -1430,318 +1494,278 @@ class _TransactionDetailsViewState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Tx sub type", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.subType.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.txid, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (coin is! Epiccash) + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Transaction ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), const SizedBox(height: 8), - if (coin is! Epiccash) - CustomTextButton( - text: "Open in block explorer", - onTap: () async { - final uri = - getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); - - if (ref - .read( - prefsChangeNotifierProvider, - ) - .hideBlockExplorerWarning == - false) { - final shouldContinue = - await showExplorerWarning( - "${uri.scheme}://${uri.host}", + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.txid, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (coin is! Epiccash) + const SizedBox(height: 8), + if (coin is! Epiccash) + CustomTextButton( + text: "Open in block explorer", + onTap: () async { + final uri = + getBlockExplorerTransactionUrlFor( + coin: coin, + txid: _transaction.txid, ); - if (!shouldContinue) { - return; + if (ref + .read( + prefsChangeNotifierProvider, + ) + .hideBlockExplorerWarning == + false) { + final shouldContinue = + await showExplorerWarning( + "${uri.scheme}://${uri.host}", + ); + + if (!shouldContinue) { + return; + } } - } - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - try { - await launchUrl( - uri, - mode: - LaunchMode - .externalApplication, - ); - } catch (_) { - if (context.mounted) { - unawaited( - showDialog( - context: context, - builder: - (_) => StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), - ), + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + try { + await launchUrl( + uri, + mode: + LaunchMode + .externalApplication, ); + } catch (_) { + if (context.mounted) { + unawaited( + showDialog( + context: context, + builder: + ( + _, + ) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), + ), + ); + } + } finally { + // Future.delayed( + // const Duration(seconds: 1), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); } - } finally { - // Future.delayed( - // const Duration(seconds: 1), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - } - }, - ), - // ), - // ), - ], - ), - ), - if (isDesktop) const SizedBox(width: 12), - if (isDesktop) - IconCopyButton(data: _transaction.txid), - ], - ), - ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // const SizedBox( - // height: 12, - // ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Text( - // "Mint Transaction ID", - // style: STextStyles.itemSubtitle(context), - // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // // Flexible( - // // child: FittedBox( - // // fit: BoxFit.scaleDown, - // // child: - // SelectableText( - // _transaction.otherData ?? "Unknown", - // style: STextStyles.itemSubtitle12(context), - // ), - // // ), - // // ), - // const SizedBox( - // height: 8, - // ), - // BlueTextButton( - // text: "Open in block explorer", - // onTap: () async { - // final uri = getBlockExplorerTransactionUrlFor( - // coin: coin, - // txid: _transaction.otherData ?? "Unknown", - // ); - // // ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = false; - // try { - // await launchUrl( - // uri, - // mode: LaunchMode.externalApplication, - // ); - // } catch (_) { - // unawaited(showDialog( - // context: context, - // builder: (_) => StackOkDialog( - // title: "Could not open in block explorer", - // message: - // "Failed to open \"${uri.toString()}\"", - // ), - // )); - // } finally { - // // Future.delayed( - // // const Duration(seconds: 1), - // // () => ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = true, - // // ); - // } - // }, - // ), - // ], - // ), - // ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Slate ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.slateId ?? "Unknown", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], + }, + ), + // ), + // ), + ], + ), ), if (isDesktop) const SizedBox(width: 12), if (isDesktop) - IconCopyButton( - data: _transaction.slateId ?? "Unknown", - ), + IconCopyButton(data: _transaction.txid), ], ), ), - if (!isDesktop) const SizedBox(height: 12), - ], + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // const SizedBox( + // height: 12, + // ), + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Mint Transaction ID", + // style: STextStyles.itemSubtitle(context), + // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // // Flexible( + // // child: FittedBox( + // // fit: BoxFit.scaleDown, + // // child: + // SelectableText( + // _transaction.otherData ?? "Unknown", + // style: STextStyles.itemSubtitle12(context), + // ), + // // ), + // // ), + // const SizedBox( + // height: 8, + // ), + // BlueTextButton( + // text: "Open in block explorer", + // onTap: () async { + // final uri = getBlockExplorerTransactionUrlFor( + // coin: coin, + // txid: _transaction.otherData ?? "Unknown", + // ); + // // ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = false; + // try { + // await launchUrl( + // uri, + // mode: LaunchMode.externalApplication, + // ); + // } catch (_) { + // unawaited(showDialog( + // context: context, + // builder: (_) => StackOkDialog( + // title: "Could not open in block explorer", + // message: + // "Failed to open \"${uri.toString()}\"", + // ), + // )); + // } finally { + // // Future.delayed( + // // const Duration(seconds: 1), + // // () => ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = true, + // // ); + // } + // }, + // ), + // ], + // ), + // ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Slate ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.slateId ?? "Unknown", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + if (isDesktop) const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: + _transaction.slateId ?? "Unknown", + ), + ], + ), + ), + if (!isDesktop) const SizedBox(height: 12), + ], + ), ), ), ), ), ), - ), - ], + ], + ), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, diff --git a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart index 2eebe5dbe..a337cd898 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart @@ -40,10 +40,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class TransactionSearchFilterView extends ConsumerStatefulWidget { - const TransactionSearchFilterView({ - super.key, - required this.coin, - }); + const TransactionSearchFilterView({super.key, required this.coin}); static const String routeName = "/transactionSearchFilter"; @@ -82,18 +79,19 @@ class _TransactionSearchViewState _selectedFromDate = filterState.from; _keywordTextEditingController.text = filterState.keyword; - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); _toDateString = _selectedToDate == null ? "" : Format.formatDate(_selectedToDate!); - final String amount = filterState.amount == null - ? "" - : ref.read(pAmountFormatter(widget.coin)).format( - filterState.amount!, - withUnitName: false, - ); + final String amount = + filterState.amount == null + ? "" + : ref + .read(pAmountFormatter(widget.coin)) + .format(filterState.amount!, withUnitName: false); _amountTextEditingController.text = amount; } @@ -118,9 +116,10 @@ class _TransactionSearchViewState return Text( isDateSelected ? "From..." : _fromDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -130,9 +129,10 @@ class _TransactionSearchViewState return Text( isDateSelected ? "To..." : _toDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -145,13 +145,14 @@ class _TransactionSearchViewState const middleSeparatorWidth = 12.0; final isDesktop = Util.isDesktop; - final width = isDesktop - ? null - : (MediaQuery.of(context).size.width - - (middleSeparatorWidth + - (2 * middleSeparatorPadding) + - (2 * Constants.size.standardPadding))) / - 2; + final width = + isDesktop + ? null + : (MediaQuery.of(context).size.width - + (middleSeparatorWidth + + (2 * middleSeparatorPadding) + + (2 * Constants.size.standardPadding))) / + 2; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -172,7 +173,8 @@ class _TransactionSearchViewState _selectedFromDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedToDate != null && + final flag = + _selectedToDate != null && !_selectedFromDate!.isBefore(_selectedToDate!); if (flag) { _selectedToDate = DateTime.fromMillisecondsSinceEpoch( @@ -182,13 +184,15 @@ class _TransactionSearchViewState setState(() { if (flag) { - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); } - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); }); } } @@ -196,15 +200,18 @@ class _TransactionSearchViewState child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -219,18 +226,15 @@ class _TransactionSearchViewState Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateFromText, - ), + child: FittedBox(child: _dateFromText), ), ], ), @@ -239,8 +243,9 @@ class _TransactionSearchViewState ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: middleSeparatorPadding), + padding: const EdgeInsets.symmetric( + horizontal: middleSeparatorPadding, + ), child: Container( width: middleSeparatorWidth, // height: 1, @@ -263,7 +268,8 @@ class _TransactionSearchViewState _selectedToDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedFromDate != null && + final flag = + _selectedFromDate != null && !_selectedToDate!.isAfter(_selectedFromDate!); if (flag) { _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( @@ -273,13 +279,15 @@ class _TransactionSearchViewState setState(() { if (flag) { - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); } - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); }); } } @@ -287,15 +295,18 @@ class _TransactionSearchViewState child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -310,18 +321,15 @@ class _TransactionSearchViewState Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateToText, - ), + child: FittedBox(child: _dateToText), ), ], ), @@ -329,10 +337,7 @@ class _TransactionSearchViewState ), ), ), - if (isDesktop) - const SizedBox( - width: 24, - ), + if (isDesktop) const SizedBox(width: 24), ], ); } @@ -344,10 +349,7 @@ class _TransactionSearchViewState maxWidth: 576, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: _buildContent(context), ), ); @@ -375,22 +377,23 @@ class _TransactionSearchViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.size.standardPadding, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _buildContent(context), + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.size.standardPadding, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _buildContent(context)), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -415,9 +418,7 @@ class _TransactionSearchViewState const DesktopDialogCloseButton(), ], ), - SizedBox( - height: isDesktop ? 14 : 10, - ), + SizedBox(height: isDesktop ? 14 : 10), if (!isDesktop) Align( alignment: Alignment.centerLeft, @@ -428,10 +429,7 @@ class _TransactionSearchViewState ), ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), RoundedWhiteContainer( padding: EdgeInsets.all(isDesktop ? 0 : 12), child: Column( @@ -466,9 +464,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -476,14 +472,16 @@ class _TransactionSearchViewState children: [ Text( "Sent", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -494,9 +492,7 @@ class _TransactionSearchViewState ), ], ), - SizedBox( - height: isDesktop ? 4 : 10, - ), + SizedBox(height: isDesktop ? 4 : 10), Row( children: [ GestureDetector( @@ -526,9 +522,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -536,14 +530,16 @@ class _TransactionSearchViewState children: [ Text( "Received", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -554,9 +550,7 @@ class _TransactionSearchViewState ), ], ), - SizedBox( - height: isDesktop ? 4 : 10, - ), + SizedBox(height: isDesktop ? 4 : 10), Row( children: [ GestureDetector( @@ -586,9 +580,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -596,14 +588,16 @@ class _TransactionSearchViewState children: [ Text( "Trades", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -617,41 +611,35 @@ class _TransactionSearchViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Date", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), _buildDateRangePicker(), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Amount", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -665,19 +653,21 @@ class _TransactionSearchViewState controller: _amountTextEditingController, focusNode: amountTextFieldFocusNode, onChanged: (_) => setState(() {}), - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), inputFormatters: [ AmountInputFormatter( decimals: widget.coin.fractionDigits, unit: ref.watch(pAmountUnit(widget.coin)), locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), ), // // regex to validate a crypto amount with 8 decimal places @@ -687,65 +677,67 @@ class _TransactionSearchViewState // ? newValue // : oldValue), ], - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Enter ${widget.coin.ticker} amount...", keywordTextFieldFocusNode, context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _amountTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _amountTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _amountTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _amountTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Keyword", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -758,13 +750,16 @@ class _TransactionSearchViewState key: const Key("transactionSearchViewKeywordFieldKey"), controller: _keywordTextEditingController, focusNode: keywordTextFieldFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type keyword...", @@ -772,39 +767,39 @@ class _TransactionSearchViewState context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _keywordTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _keywordTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _keywordTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _keywordTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( children: [ Expanded( @@ -816,9 +811,7 @@ class _TransactionSearchViewState if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); await Future.delayed( - const Duration( - milliseconds: 75, - ), + const Duration(milliseconds: 75), ); } } @@ -855,9 +848,7 @@ class _TransactionSearchViewState // ), // ), // ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -884,16 +875,10 @@ class _TransactionSearchViewState // ), // ), // ), - if (isDesktop) - const SizedBox( - width: 32, - ), + if (isDesktop) const SizedBox(width: 32), ], ), - if (!isDesktop) - const SizedBox( - height: 20, - ), + if (!isDesktop) const SizedBox(height: 20), ], ); } @@ -902,11 +887,14 @@ class _TransactionSearchViewState final amountText = _amountTextEditingController.text; Amount? amount; if (amountText.isNotEmpty && !(amountText == "," || amountText == ".")) { - amount = amountText.contains(",") - ? Decimal.parse(amountText.replaceFirst(",", ".")) - .toAmount(fractionDigits: widget.coin.fractionDigits) - : Decimal.parse(amountText) - .toAmount(fractionDigits: widget.coin.fractionDigits); + amount = + amountText.contains(",") + ? Decimal.parse( + amountText.replaceFirst(",", "."), + ).toAmount(fractionDigits: widget.coin.fractionDigits) + : Decimal.parse( + amountText, + ).toAmount(fractionDigits: widget.coin.fractionDigits); } final TransactionFilter filter = TransactionFilter( diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart index 5219b3f26..308210124 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart @@ -198,7 +198,7 @@ class _BoostTransactionViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: child, + body: SafeArea(child: child), ), ), child: Padding( diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart index ef473b3bf..c861bbff6 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart @@ -10,8 +10,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; -import 'transaction_v2_list_item.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; @@ -21,6 +21,7 @@ import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/rounded_white_container.dart'; +import 'transaction_v2_list_item.dart'; class FusionGroupDetailsView extends ConsumerStatefulWidget { const FusionGroupDetailsView({ @@ -48,23 +49,15 @@ class _FusionGroupDetailsViewState BorderRadius get _borderRadiusFirst { return BorderRadius.only( - topLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), - topRight: Radius.circular( - Constants.size.circularBorderRadius, - ), + topLeft: Radius.circular(Constants.size.circularBorderRadius), + topRight: Radius.circular(Constants.size.circularBorderRadius), ); } BorderRadius get _borderRadiusLast { return BorderRadius.only( - bottomLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), - bottomRight: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottomLeft: Radius.circular(Constants.size.circularBorderRadius), + bottomRight: Radius.circular(Constants.size.circularBorderRadius), ); } @@ -97,16 +90,14 @@ class _FusionGroupDetailsViewState ), Flexible( child: Padding( - padding: const EdgeInsets.only( - right: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(right: 32, bottom: 32), child: RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, padding: const EdgeInsets.all(0), child: ListView.separated( shrinkWrap: true, @@ -132,9 +123,10 @@ class _FusionGroupDetailsViewState return Container( width: double.infinity, height: 1.2, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ); }, itemCount: widget.transactions.length, @@ -164,29 +156,27 @@ class _FusionGroupDetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: ListView.builder( - itemCount: widget.transactions.length, - itemBuilder: (context, index) { - BorderRadius? radius; - if (widget.transactions.length == 1) { - radius = BorderRadius.circular( - Constants.size.circularBorderRadius, - ); - } else if (index == widget.transactions.length - 1) { - radius = _borderRadiusLast; - } else if (index == 0) { - radius = _borderRadiusFirst; - } - final tx = widget.transactions[index]; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: ListView.builder( + itemCount: widget.transactions.length, + itemBuilder: (context, index) { + BorderRadius? radius; + if (widget.transactions.length == 1) { + radius = BorderRadius.circular( + Constants.size.circularBorderRadius, + ); + } else if (index == widget.transactions.length - 1) { + radius = _borderRadiusLast; + } else if (index == 0) { + radius = _borderRadiusFirst; + } + final tx = widget.transactions[index]; - return TxListItem( - tx: tx, - coin: widget.coin, - radius: radius, - ); - }, + return TxListItem(tx: tx, coin: widget.coin, radius: radius); + }, + ), ), ), ), diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index 06469c92b..a2e8e4453 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -24,7 +24,6 @@ import '../../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../../notifications/show_flush_bar.dart'; -import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/global/address_book_service_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../themes/stack_colors.dart'; @@ -634,259 +633,192 @@ class _TransactionV2DetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: - isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (isDesktop) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction details", - style: STextStyles.desktopH3(context), - ), - const DesktopDialogCloseButton(), - ], - ), - Flexible( - child: Padding( - padding: - isDesktop - ? const EdgeInsets.only(right: 32, bottom: 32) - : const EdgeInsets.all(0), - child: ConditionalParent( - condition: isDesktop, - builder: (child) { - return RoundedWhiteContainer( - borderColor: - isDesktop - ? Theme.of( - context, - ).extension()!.backgroundAppBar - : null, - padding: const EdgeInsets.all(0), - child: child, - ); - }, - child: SingleChildScrollView( - primary: isDesktop ? false : null, - child: Padding( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), - child: Container( - decoration: + body: ConditionalParent( + condition: !isDesktop, + builder: (child) => SafeArea(child: child), + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction details", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], + ), + Flexible( + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return RoundedWhiteContainer( + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, + padding: const EdgeInsets.all(0), + child: child, + ); + }, + child: SingleChildScrollView( + primary: isDesktop ? false : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: isDesktop - ? BoxDecoration( - color: - Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants - .size - .circularBorderRadius, - ), - ), - ) - : null, - child: Padding( - padding: + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), + child: Container( + decoration: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - if (isDesktop) - Row( - children: [ - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - const SizedBox(width: 16), - SelectableText( - whatIsIt( - _transaction, - currentHeight, + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, ), - style: - STextStyles.desktopTextMedium( - context, - ), ), - ], - ), - Column( - crossAxisAlignment: - isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - SelectableText( - "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.titleBold12( + ) + : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + if (isDesktop) + Row( + children: [ + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + const SizedBox(width: 16), + SelectableText( + whatIsIt( + _transaction, + currentHeight, + ), + style: + STextStyles.desktopTextMedium( context, ), + ), + ], ), - const SizedBox(height: 2), - if (price != null) - Builder( - builder: (context) { - final total = (amount.decimal * - price!) - .toAmount( - fractionDigits: 2, - ); - final formatted = total.fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider + Column( + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + SelectableText( + "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 2), + if (price != null) + Builder( + builder: (context) { + final total = + (amount.decimal * price!) + .toAmount( + fractionDigits: 2, + ); + final formatted = total + .fiatString( + locale: ref.watch( + localeServiceChangeNotifierProvider + .select( + (value) => + value + .locale, + ), + ), + ); + final ticker = ref.watch( + prefsChangeNotifierProvider .select( (value) => - value.locale, + value.currency, ), - ), - ); - final ticker = ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.currency, - ), - ); - return SelectableText( - "$amountPrefix$formatted $ticker", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ); - }, - ), - ], - ), - if (!isDesktop) - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, + ); + return SelectableText( + "$amountPrefix$formatted $ticker", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ); + }, + ), + ], ), - ], + if (!isDesktop) + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + ], + ), ), ), ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - whatIsIt(_transaction, currentHeight), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - _transaction.type == - TransactionType - .outgoing && - _transaction - .subType != - TransactionSubType - .cashFusion - ? Theme.of(context) - .extension< - StackColors - >()! - .accentColorOrange - : Theme.of(context) - .extension< - StackColors - >()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], - ), - ), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) isDesktop ? const _Divider() : const SizedBox(height: 12), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) RoundedWhiteContainer( padding: isDesktop @@ -895,393 +827,360 @@ class _TransactionV2DetailsViewState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: kDebugMode, - builder: (child) { - return Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - child, - // CustomTextButton( - // text: "Info", - // onTap: () async { - // final adr = await ref - // .read(mainDBProvider) - // .getAddress(walletId, - // addresses.first); - // if (adr != null && - // mounted) { - // if (isDesktop) { - // await showDialog< - // void>( - // context: context, - // builder: (_) => - // DesktopDialog( - // maxHeight: double - // .infinity, - // child: - // AddressDetailsView( - // addressId: - // adr.id, - // walletId: widget - // .walletId, - // ), - // ), - // ); - // } else { - // await Navigator.of( - // context) - // .pushNamed( - // AddressDetailsView - // .routeName, - // arguments: Tuple2( - // adr.id, - // widget.walletId, - // ), - // ); - // } - // } - // }, - // ) - ], - ); - }, - child: Text( - outputLabel, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Text( + "Status", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + whatIsIt(_transaction, currentHeight), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing && + _transaction + .subType != + TransactionSubType + .cashFusion + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + ), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: kDebugMode, + builder: (child) { + return Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + child, + // CustomTextButton( + // text: "Info", + // onTap: () async { + // final adr = await ref + // .read(mainDBProvider) + // .getAddress(walletId, + // addresses.first); + // if (adr != null && + // mounted) { + // if (isDesktop) { + // await showDialog< + // void>( + // context: context, + // builder: (_) => + // DesktopDialog( + // maxHeight: double + // .infinity, + // child: + // AddressDetailsView( + // addressId: + // adr.id, + // walletId: widget + // .walletId, + // ), + // ), + // ); + // } else { + // await Navigator.of( + // context) + // .pushNamed( + // AddressDetailsView + // .routeName, + // arguments: Tuple2( + // adr.id, + // widget.walletId, + // ), + // ); + // } + // } + // }, + // ) + ], + ); + }, + child: Text( + outputLabel, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), ), - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - if (data.length == 1 && - data.first.addresses.length == - 1) - FutureBuilder( - future: fetchContactNameFor( - data.first.addresses.first, - ), - builder: ( - builderContext, - AsyncSnapshot - snapshot, - ) { - String - addressOrContactName = - data + const SizedBox(height: 8), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (data.length == 1 && + data .first .addresses - .first; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { + .length == + 1) + FutureBuilder( + future: fetchContactNameFor( + data + .first + .addresses + .first, + ), + builder: ( + builderContext, + AsyncSnapshot + snapshot, + ) { + String addressOrContactName = - snapshot.data!; - } - return SelectableText( - addressOrContactName, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ); - }, - ) - else - for ( - int i = 0; - i < data.length; - i++ - ) - ConditionalParent( - condition: i > 0, - builder: - (child) => Column( + data + .first + .addresses + .first; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + addressOrContactName = + snapshot.data!; + } + return SelectableText( + addressOrContactName, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ); + }, + ) + else + for ( + int i = 0; + i < data.length; + i++ + ) + ConditionalParent( + condition: i > 0, + builder: + (child) => Column( + crossAxisAlignment: + CrossAxisAlignment + .stretch, + children: [ + const _Divider(), + child, + ], + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: Column( crossAxisAlignment: CrossAxisAlignment - .stretch, + .start, children: [ - const _Divider(), - child, + ...data[i].addresses.map(( + e, + ) { + return FutureBuilder( + future: + fetchContactNameFor( + e, + ), + builder: ( + builderContext, + AsyncSnapshot< + String + > + snapshot, + ) { + final String + addressOrContactName; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot + .hasData) { + addressOrContactName = + snapshot + .data!; + } else { + addressOrContactName = + e; + } + + return OutputCard( + address: + addressOrContactName, + amount: + data[i] + .amount, + coin: coin, + ); + }, + ); + }), ], ), - child: Padding( - padding: - const EdgeInsets.all( - 8.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - ...data[i].addresses.map(( - e, - ) { - return FutureBuilder( - future: - fetchContactNameFor( - e, - ), - builder: ( - builderContext, - AsyncSnapshot< - String - > - snapshot, - ) { - final String - addressOrContactName; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot - .hasData) { - addressOrContactName = - snapshot - .data!; - } else { - addressOrContactName = - e; - } - - return OutputCard( - address: - addressOrContactName, - amount: - data[i] - .amount, - coin: coin, - ); - }, - ); - }), - ], ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), - ), - // if (isDesktop) - // IconCopyButton( - // data: addresses.first, - // ), - ], + // if (isDesktop) + // IconCopyButton( + // data: addresses.first, + // ), + ], + ), ), - ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "On chain note", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - SelectableText( - _transaction.onChainNote ?? "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - if (isDesktop) - IconCopyButton( - data: _transaction.onChainNote ?? "", - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - (coin is Epiccash) - ? "Local Note" - : "Note ", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - isDesktop - ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, - ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .infoItemIcons, - ), - const SizedBox(width: 4), - Text( - "Edit", - style: STextStyles.link2( - context, - ), - ), - ], + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "On chain note", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - ), - ], - ), - const SizedBox(height: 8), - SelectableText( - ref - .watch( - pTransactionNote(( - txid: - (coin is Epiccash) - ? _transaction.slateId - .toString() - : _transaction.txid, - walletId: walletId, - )), - ) - ?.value ?? - "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + const SizedBox(height: 8), + SelectableText( + _transaction.onChainNote ?? "", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), + ], + ), + ), + if (isDesktop) + IconCopyButton( + data: _transaction.onChainNote ?? "", + ), + ], ), - ], - ), - ), - if (_sparkMemo != null) + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (_sparkMemo != null) RoundedWhiteContainer( padding: isDesktop @@ -1291,9 +1190,13 @@ class _TransactionV2DetailsViewState crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Text( - "Memo", + (coin is Epiccash) + ? "Local Note" + : "Note ", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1303,11 +1206,74 @@ class _TransactionV2DetailsViewState context, ), ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), ], ), const SizedBox(height: 8), SelectableText( - _sparkMemo!, + ref + .watch( + pTransactionNote(( + txid: + (coin is Epiccash) + ? _transaction.slateId + .toString() + : _transaction.txid, + walletId: walletId, + )), + ) + ?.value ?? + "", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1327,177 +1293,92 @@ class _TransactionV2DetailsViewState ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( + if (_sparkMemo != null) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (_sparkMemo != null) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Date", + Row( + children: [ + Text( + "Memo", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + const SizedBox(height: 8), + SelectableText( + _sparkMemo!, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) const SizedBox(height: 2), - if (isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), ], ), - if (!isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (isDesktop) - IconCopyButton( - data: Format.extractDateFrom( - _transaction.timestamp, - ), - ), - ], - ), - ), - if (coin is! NanoCurrency && - !(coin is Xelis && - _transaction.type == - TransactionType.incoming)) + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is! NanoCurrency && - !(coin is Xelis && - _transaction.type == - TransactionType.incoming)) RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), - child: Builder( - builder: (context) { - final String feeString = - showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms, - ) - ? ref - .watch( - pAmountFormatter(coin), - ) - .format(fee) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format(fee); - - return Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction fee", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Text( + "Date", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - feeString, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (supportsRbf && !confirmedTxn) - const SizedBox(height: 8), - if (supportsRbf && !confirmedTxn) - CustomTextButton( - text: "Boost transaction", - onTap: _boostPressed, - ), - ], - ), - if (!isDesktop) - SelectableText( - feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1514,63 +1395,74 @@ class _TransactionV2DetailsViewState context, ), ), - if (isDesktop) - IconCopyButton(data: feeString), ], - ); - }, + ), + if (!isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, + ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (isDesktop) + IconCopyButton( + data: Format.extractDateFrom( + _transaction.timestamp, + ), + ), + ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - Builder( - builder: (context) { - final String height; - final String confirmations; - final confirms = _transaction.getConfirmations( - currentHeight, - ); - - if (widget.coin is Bitcoincash || - widget.coin is Ecash) { - height = - _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; - confirmations = confirms.toString(); - } else if (widget.coin is Epiccash && - _transaction.slateId == null) { - confirmations = "Unknown"; - height = "Unknown"; - } else { - final confirmed = _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms, - ); - if (widget.coin is! Epiccash && confirmed) { - height = - "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; - } else { - height = - confirms > 0 - ? "${_transaction.height}" - : "Pending"; - } - - confirmations = confirms.toString(); - } + if (coin is! NanoCurrency && + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is! NanoCurrency && + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Builder( + builder: (context) { + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, + ) + ? ref + .watch( + pAmountFormatter(coin), + ) + .format(fee) + : "Pending" + : ref + .watch(pAmountFormatter(coin)) + .format(fee); - return Column( - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: @@ -1581,7 +1473,7 @@ class _TransactionV2DetailsViewState CrossAxisAlignment.start, children: [ Text( - "Block height", + "Transaction fee", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1595,7 +1487,7 @@ class _TransactionV2DetailsViewState const SizedBox(height: 2), if (isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1614,11 +1506,18 @@ class _TransactionV2DetailsViewState context, ), ), + if (supportsRbf && !confirmedTxn) + const SizedBox(height: 8), + if (supportsRbf && !confirmedTxn) + CustomTextButton( + text: "Boost transaction", + onTap: _boostPressed, + ), ], ), if (!isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1636,146 +1535,322 @@ class _TransactionV2DetailsViewState ), ), if (isDesktop) - IconCopyButton(data: height), + IconCopyButton(data: feeString), ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", + ); + }, + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + Builder( + builder: (context) { + final String height; + final String confirmations; + final confirms = _transaction + .getConfirmations(currentHeight); + + if (widget.coin is Bitcoincash || + widget.coin is Ecash) { + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; + confirmations = confirms.toString(); + } else if (widget.coin is Epiccash && + _transaction.slateId == null) { + confirmations = "Unknown"; + height = "Unknown"; + } else { + final confirmed = _transaction.isConfirmed( + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, + ); + if (widget.coin is! Epiccash && confirmed) { + height = + "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; + } else { + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; + } + + confirmations = confirms.toString(); + } + + return Column( + children: [ + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Block height", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + height, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + if (!isDesktop) + SelectableText( + height, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - confirmations, + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), - if (!isDesktop) - SelectableText( - confirmations, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], ), - if (isDesktop) - IconCopyButton(data: height), - ], - ), - ), - ], - ); - }, - ), - if (coin is Ethereum && - _transaction.type != TransactionType.incoming) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Ethereum && - _transaction.type != TransactionType.incoming) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Nonce", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.nonce.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + if (!isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ), - ], - ), + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + ], + ); + }, ), - if (kDebugMode) + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Nonce", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.nonce.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (kDebugMode) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (kDebugMode) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tx sub type", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.subType.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (hasTxKeyProbably) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (hasTxKeyProbably) + TxKeyWidget( + walletId: walletId, + txid: _transaction.txid, + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (kDebugMode) RoundedWhiteContainer( padding: isDesktop @@ -1786,349 +1861,300 @@ class _TransactionV2DetailsViewState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Tx sub type", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.subType.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - if (hasTxKeyProbably) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (hasTxKeyProbably) - TxKeyWidget( - walletId: walletId, - txid: _transaction.txid, - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: !isDesktop, - builder: - (child) => Row( - children: [ - Expanded(child: child), - SimpleCopyButton( - data: _transaction.txid, - ), - ], - ), - child: Text( - "Transaction ID", + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: !isDesktop, + builder: + (child) => Row( + children: [ + Expanded(child: child), + SimpleCopyButton( + data: _transaction.txid, + ), + ], + ), + child: Text( + "Transaction ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ), + const SizedBox(height: 8), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.txid, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - ), - const SizedBox(height: 8), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.txid, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (coin is! Epiccash) - const SizedBox(height: 8), - if (coin is! Epiccash) - CustomTextButton( - text: "Open in block explorer", - onTap: () async { - final uri = - getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); - - if (ref - .read( - prefsChangeNotifierProvider, - ) - .hideBlockExplorerWarning == - false) { - final shouldContinue = - await showExplorerWarning( - "${uri.scheme}://${uri.host}", + if (coin is! Epiccash) + const SizedBox(height: 8), + if (coin is! Epiccash) + CustomTextButton( + text: "Open in block explorer", + onTap: () async { + final uri = + getBlockExplorerTransactionUrlFor( + coin: coin, + txid: _transaction.txid, ); - if (!shouldContinue) { - return; + if (ref + .read( + prefsChangeNotifierProvider, + ) + .hideBlockExplorerWarning == + false) { + final shouldContinue = + await showExplorerWarning( + "${uri.scheme}://${uri.host}", + ); + + if (!shouldContinue) { + return; + } } - } - - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - try { - await launchUrl( - uri, - mode: - LaunchMode - .externalApplication, - ); - } catch (_) { - if (context.mounted) { - unawaited( - showDialog( - context: context, - builder: - (_) => StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), - ), + + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + try { + await launchUrl( + uri, + mode: + LaunchMode + .externalApplication, ); + } catch (_) { + if (context.mounted) { + unawaited( + showDialog( + context: context, + builder: + ( + _, + ) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), + ), + ); + } + } finally { + // Future.delayed( + // const Duration(seconds: 1), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); } - } finally { - // Future.delayed( - // const Duration(seconds: 1), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - } - }, - ), - // ), - // ), - ], - ), - ), - if (isDesktop) const SizedBox(width: 12), - if (isDesktop) - IconCopyButton(data: _transaction.txid), - ], - ), - ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // const SizedBox( - // height: 12, - // ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Text( - // "Mint Transaction ID", - // style: STextStyles.itemSubtitle(context), - // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // // Flexible( - // // child: FittedBox( - // // fit: BoxFit.scaleDown, - // // child: - // SelectableText( - // _transaction.otherData ?? "Unknown", - // style: STextStyles.itemSubtitle12(context), - // ), - // // ), - // // ), - // const SizedBox( - // height: 8, - // ), - // BlueTextButton( - // text: "Open in block explorer", - // onTap: () async { - // final uri = getBlockExplorerTransactionUrlFor( - // coin: coin, - // txid: _transaction.otherData ?? "Unknown", - // ); - // // ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = false; - // try { - // await launchUrl( - // uri, - // mode: LaunchMode.externalApplication, - // ); - // } catch (_) { - // unawaited(showDialog( - // context: context, - // builder: (_) => StackOkDialog( - // title: "Could not open in block explorer", - // message: - // "Failed to open \"${uri.toString()}\"", - // ), - // )); - // } finally { - // // Future.delayed( - // // const Duration(seconds: 1), - // // () => ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = true, - // // ); - // } - // }, - // ), - // ], - // ), - // ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Slate ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.slateId ?? "Unknown", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], + }, + ), + // ), + // ), + ], + ), ), if (isDesktop) const SizedBox(width: 12), if (isDesktop) - IconCopyButton( - data: _transaction.slateId ?? "Unknown", - ), + IconCopyButton(data: _transaction.txid), ], ), ), - if (!isDesktop) const SizedBox(height: 12), - // if (whatIsIt( - // _transaction, - // currentHeight, - // ) != - // "Sending") - // isDesktop - // ? const _Divider() - // : const SizedBox( - // height: 12, - // ), - ], + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // const SizedBox( + // height: 12, + // ), + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Mint Transaction ID", + // style: STextStyles.itemSubtitle(context), + // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // // Flexible( + // // child: FittedBox( + // // fit: BoxFit.scaleDown, + // // child: + // SelectableText( + // _transaction.otherData ?? "Unknown", + // style: STextStyles.itemSubtitle12(context), + // ), + // // ), + // // ), + // const SizedBox( + // height: 8, + // ), + // BlueTextButton( + // text: "Open in block explorer", + // onTap: () async { + // final uri = getBlockExplorerTransactionUrlFor( + // coin: coin, + // txid: _transaction.otherData ?? "Unknown", + // ); + // // ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = false; + // try { + // await launchUrl( + // uri, + // mode: LaunchMode.externalApplication, + // ); + // } catch (_) { + // unawaited(showDialog( + // context: context, + // builder: (_) => StackOkDialog( + // title: "Could not open in block explorer", + // message: + // "Failed to open \"${uri.toString()}\"", + // ), + // )); + // } finally { + // // Future.delayed( + // // const Duration(seconds: 1), + // // () => ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = true, + // // ); + // } + // }, + // ), + // ], + // ), + // ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Slate ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.slateId ?? "Unknown", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + if (isDesktop) const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: + _transaction.slateId ?? "Unknown", + ), + ], + ), + ), + if (!isDesktop) const SizedBox(height: 12), + // if (whatIsIt( + // _transaction, + // currentHeight, + // ) != + // "Sending") + // isDesktop + // ? const _Divider() + // : const SizedBox( + // height: 12, + // ), + ], + ), ), ), ), ), ), - ), - ], + ], + ), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, diff --git a/lib/widgets/desktop/desktop_scaffold.dart b/lib/widgets/desktop/desktop_scaffold.dart index 920c66306..805fc56a7 100644 --- a/lib/widgets/desktop/desktop_scaffold.dart +++ b/lib/widgets/desktop/desktop_scaffold.dart @@ -14,12 +14,7 @@ import '../../themes/stack_colors.dart'; import '../background.dart'; class DesktopScaffold extends StatelessWidget { - const DesktopScaffold({ - super.key, - this.background, - this.appBar, - this.body, - }); + const DesktopScaffold({super.key, this.background, this.appBar, this.body}); final Color? background; final Widget? appBar; @@ -35,10 +30,7 @@ class DesktopScaffold extends StatelessWidget { // crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (appBar != null) appBar!, - if (body != null) - Expanded( - child: body!, - ), + if (body != null) Expanded(child: body!), ], ), ), @@ -73,7 +65,7 @@ class MasterScaffold extends StatelessWidget { child: Scaffold( backgroundColor: background ?? Colors.transparent, appBar: appBar as PreferredSizeWidget?, - body: body, + body: SafeArea(child: body), ), ); } From 8d51d904d102f64756e9229efebaeb6e524af311 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 13:42:33 -0600 Subject: [PATCH 087/206] autosave and organise --- .../restore_options_view.dart | 16 ++++---- .../verify_recovery_phrase_view.dart | 9 +++-- .../intermediate/lib_salvium_wallet.dart | 37 ++++++------------- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index 40607b103..e09882a7c 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -416,8 +416,7 @@ class _SeedRestoreOptionState extends ConsumerState { final currentLength = ref.watch(mnemonicWordCountStateProvider); - final isMoneroAnd25 = widget.coin is Monero && currentLength == 25; - final isWowneroAnd25 = widget.coin is Wownero && currentLength == 25; + final isCnAnd25 = widget.coin is CryptonoteCurrency && currentLength == 25; final bool supportsPassphrase; if (widget.coin.hasMnemonicPassphraseSupport) { @@ -432,7 +431,7 @@ class _SeedRestoreOptionState extends ConsumerState { return Column( children: [ - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + if (isCnAnd25 || widget.coin is Epiccash) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -459,9 +458,9 @@ class _SeedRestoreOptionState extends ConsumerState { ), ], ), - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + if (isCnAnd25 || widget.coin is Epiccash) SizedBox(height: Util.isDesktop ? 16 : 8), - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + if (isCnAnd25 || widget.coin is Epiccash) ref.watch(_pIsUsingDate) ? RestoreFromDatePicker( onTap: widget.dateChooserFunction, @@ -518,9 +517,8 @@ class _SeedRestoreOptionState extends ConsumerState { ), ), ), - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) - const SizedBox(height: 8), - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + if (isCnAnd25 || widget.coin is Epiccash) const SizedBox(height: 8), + if (isCnAnd25 || widget.coin is Epiccash) RoundedWhiteContainer( child: Center( child: Text( @@ -541,7 +539,7 @@ class _SeedRestoreOptionState extends ConsumerState { ), ), ), - if (isMoneroAnd25 || widget.coin is Epiccash || isWowneroAnd25) + if (isCnAnd25 || widget.coin is Epiccash) SizedBox(height: Util.isDesktop ? 24 : 16), Text( "Choose recovery phrase length", diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart index 06beb584a..ef959aa22 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart @@ -15,7 +15,7 @@ import 'dart:math'; import 'package:cs_monero/src/deprecated/get_height_by_date.dart' as cs_monero_deprecated; import 'package:cs_salvium/src/deprecated/get_height_by_date.dart' -as cs_salvium_deprecated; + as cs_salvium_deprecated; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -124,7 +124,8 @@ class _VerifyRecoveryPhraseViewState }); } viewOnlyWalletType = ViewOnlyWalletType.xPub; - } else if (widget.wallet is LibMoneroWallet) { + } else if (widget.wallet is LibMoneroWallet || + widget.wallet is LibSalviumWallet) { if (widget.wallet.cryptoCurrency is Monero) { height = cs_monero_deprecated.getMoneroHeightByDate( date: DateTime.now().subtract(const Duration(days: 7)), @@ -205,8 +206,8 @@ class _VerifyRecoveryPhraseViewState final w = widget.wallet as LibSalviumWallet; final info = - await w - .hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing(); + await w + .hackToCreateNewViewOnlyWalletDataFromNewlyCreatedWalletThisFunctionShouldNotBeCalledUnlessYouKnowWhatYouAreDoing(); final address = info.$1; final privateViewKey = info.$2; diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index aeff86381..231aa721e 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -250,10 +250,7 @@ abstract class LibSalviumWallet Future save() async { if (!Platform.isWindows) { final appRoot = await StackFileSystem.applicationRootDirectory(); - await _backupWalletFiles( - name: walletId, - appRoot: appRoot, - ); + await _backupWalletFiles(name: walletId, appRoot: appRoot); } await libSalviumWallet!.save(); } @@ -285,7 +282,7 @@ abstract class LibSalviumWallet final base = libSalviumWallet; // final oldInfo = getLibSalviumWalletInfo(walletId); - if (base == null /*|| (oldInfo != null && oldInfo.name != walletId)*/) { + if (base == null /*|| (oldInfo != null && oldInfo.name != walletId)*/ ) { return null; } try { @@ -737,21 +734,13 @@ abstract class LibSalviumWallet await libSalviumWallet?.save(); } - Future pathForWalletDir({ - required String name, - }) async { + Future pathForWalletDir({required String name}) async { final Directory root = await StackFileSystem.applicationRootDirectory(); - return _pathForWalletDir( - name: name, - appRoot: root, - ); + return _pathForWalletDir(name: name, appRoot: root); } - Future pathForWallet({ - required String name, - }) async => await pathForWalletDir( - name: name, - ).then((path) => '$path/$name'); + Future pathForWallet({required String name}) async => + await pathForWalletDir(name: name).then((path) => '$path/$name'); void onSyncingUpdate({ required int syncHeight, @@ -1511,10 +1500,7 @@ Future _backupWalletFiles({ required String name, required Directory appRoot, }) async { - final path = await _pathForWallet( - name: name, - appRoot: appRoot, - ); + final path = await _pathForWallet(name: name, appRoot: appRoot); final cacheFile = File(path); final keysFile = File('$path.keys'); final addressListFile = File('$path.address.txt'); @@ -1552,8 +1538,7 @@ Future _pathForWalletDir({ Future _pathForWallet({ required String name, required Directory appRoot, -}) async => - await _pathForWalletDir( - name: name, - appRoot: appRoot, - ).then((path) => '$path/$name'); +}) async => await _pathForWalletDir( + name: name, + appRoot: appRoot, +).then((path) => '$path/$name'); From f24adaa6f282fbb54937562b97774a3464cf149f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 13:42:56 -0600 Subject: [PATCH 088/206] fix file exists error --- .../restore_wallet_view/restore_wallet_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index b70d9a0ef..a8e0f8218 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -345,7 +345,7 @@ class _RestoreWalletViewState extends ConsumerState { await (wallet as WowneroWallet).init(isRestore: true); break; - case const (Salvium): + case const (SalviumWallet): await (wallet as SalviumWallet).init(isRestore: true); break; From 97f5995e442031384e2e0fc0e33755c4345263f7 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 14:05:02 -0600 Subject: [PATCH 089/206] temporarily (lol) copy paste sync status stuff to quickly integrate syncing for salvium --- .../intermediate/lib_salvium_wallet.dart | 328 ++++++++++-------- 1 file changed, 189 insertions(+), 139 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index 231aa721e..a70c69d68 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -8,7 +8,6 @@ import 'package:isar/isar.dart'; import 'package:mutex/mutex.dart'; import 'package:stack_wallet_backup/generate_password.dart'; -import '../../../db/hive/db.dart'; import '../../../models/balance.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; @@ -104,23 +103,23 @@ abstract class LibSalviumWallet lib_salvium.Wallet? libSalviumWallet; - // lib_monero_compat.SyncStatus? get syncStatus => _syncStatus; - // lib_monero_compat.SyncStatus? _syncStatus; - // int _syncedCount = 0; - // void _setSyncStatus(lib_monero_compat.SyncStatus status) { - // if (status is lib_monero_compat.SyncedSyncStatus) { - // if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { - // _syncedCount++; - // } - // } else { - // _syncedCount = 0; - // } - // - // if (_syncedCount < 3) { - // _syncStatus = status; - // syncStatusChanged(); - // } - // } + SyncStatus? get syncStatus => _syncStatus; + SyncStatus? _syncStatus; + int _syncedCount = 0; + void _setSyncStatus(SyncStatus status) { + if (status is SyncedSyncStatus) { + if (_syncStatus is SyncedSyncStatus) { + _syncedCount++; + } + } else { + _syncedCount = 0; + } + + if (_syncedCount < 3) { + _syncStatus = status; + syncStatusChanged(); + } + } final prepareSendMutex = Mutex(); final estimateFeeMutex = Mutex(); @@ -222,10 +221,10 @@ abstract class LibSalviumWallet if (wasNull) { try { - // _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + _setSyncStatus(ConnectingSyncStatus()); libSalviumWallet?.startSyncing(); } catch (_) { - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + _setSyncStatus(FailedSyncStatus()); // TODO log } } @@ -236,17 +235,6 @@ abstract class LibSalviumWallet unawaited(refresh()); } - // @Deprecated("Only used in the case of older wallets") - // lib_monero_compat.WalletInfo? getLibSalviumWalletInfo(String walletId) { - // try { - // return DB.instance.moneroWalletInfoBox.values.firstWhere( - // (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType), - // ); - // } catch (_) { - // return null; - // } - // } - Future save() async { if (!Platform.isWindows) { final appRoot = await StackFileSystem.applicationRootDirectory(); @@ -281,8 +269,7 @@ abstract class LibSalviumWallet Future getKeys() async { final base = libSalviumWallet; - // final oldInfo = getLibSalviumWalletInfo(walletId); - if (base == null /*|| (oldInfo != null && oldInfo.name != walletId)*/ ) { + if (base == null) { return null; } try { @@ -487,7 +474,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + _setSyncStatus(FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } proxy = TorService.sharedInstance.getProxyInfo(); @@ -496,12 +483,12 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + _setSyncStatus(FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } - // _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); + _setSyncStatus(ConnectingSyncStatus()); try { if (_requireMutex) { await _torConnectingLock.protect(() async { @@ -538,9 +525,9 @@ abstract class LibSalviumWallet libSalviumWallet?.startListeners(); libSalviumWallet?.startAutoSaving(); - // _setSyncStatus(lib_monero_compat.ConnectedSyncStatus()); + // _setSyncStatus(ConnectedSyncStatus()); } catch (e, s) { - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + // _setSyncStatus(FailedSyncStatus()); Logging.instance.e( "Exception caught in $runtimeType.updateNode(): ", error: e, @@ -751,8 +738,9 @@ abstract class LibSalviumWallet currentKnownChainHeight = nodeHeight; updateChainHeight(); final blocksLeft = nodeHeight - syncHeight; + final SyncStatus status; if (blocksLeft < 100) { - // status = lib_monero_compat.SyncedSyncStatus(); + status = SyncedSyncStatus(); // if (!_hasSyncAfterStartup) { // _hasSyncAfterStartup = true; @@ -765,14 +753,14 @@ abstract class LibSalviumWallet } else { final percent = syncHeight / currentKnownChainHeight; - // status = lib_monero_compat.SyncingSyncStatus( - // blocksLeft, - // percent, - // currentKnownChainHeight, - // ); + status = SyncingSyncStatus( + blocksLeft, + percent, + currentKnownChainHeight, + ); } - // _setSyncStatus(status); + _setSyncStatus(status); _refreshTxDataHelper(); } } @@ -848,82 +836,82 @@ abstract class LibSalviumWallet ); } - // void syncStatusChanged() async { - // final _syncStatus = syncStatus; - // - // if (_syncStatus != null) { - // if (_syncStatus.progress() == 1 && refreshMutex.isLocked) { - // refreshMutex.release(); - // } - // - // WalletSyncStatus? status; - // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true); - // - // if (_syncStatus is lib_monero_compat.SyncingSyncStatus) { - // final int blocksLeft = _syncStatus.blocksLeft; - // - // // ensure at least 1 to prevent math errors - // final int height = max(1, _syncStatus.height); - // - // final nodeHeight = height + blocksLeft; - // currentKnownChainHeight = nodeHeight; - // - // // final percent = height / nodeHeight; - // final percent = _syncStatus.ptc; - // - // final highest = max(highestPercentCached, percent); - // - // final unchanged = highest == highestPercentCached; - // if (unchanged) { - // return; - // } - // - // // update cached - // if (highestPercentCached < percent) { - // highestPercentCached = percent; - // } - // - // GlobalEventBus.instance.fire( - // RefreshPercentChangedEvent(highest, walletId), - // ); - // GlobalEventBus.instance.fire( - // BlocksRemainingEvent(blocksLeft, walletId), - // ); - // } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) { - // status = WalletSyncStatus.synced; - // } else if (_syncStatus is lib_monero_compat.NotConnectedSyncStatus) { - // status = WalletSyncStatus.unableToSync; - // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - // } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) { - // status = WalletSyncStatus.syncing; - // GlobalEventBus.instance.fire( - // RefreshPercentChangedEvent(highestPercentCached, walletId), - // ); - // } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) { - // status = WalletSyncStatus.unableToSync; - // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - // } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) { - // status = WalletSyncStatus.syncing; - // GlobalEventBus.instance.fire( - // RefreshPercentChangedEvent(highestPercentCached, walletId), - // ); - // } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) { - // status = WalletSyncStatus.syncing; - // GlobalEventBus.instance.fire( - // RefreshPercentChangedEvent(highestPercentCached, walletId), - // ); - // } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) { - // status = WalletSyncStatus.unableToSync; - // xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); - // } - // - // if (status != null) { - // GlobalEventBus.instance.fire( - // WalletSyncStatusChangedEvent(status, walletId, info.coin), - // ); - // } - // } - // } + void syncStatusChanged() async { + final _syncStatus = syncStatus; + + if (_syncStatus != null) { + if (_syncStatus.progress() == 1 && refreshMutex.isLocked) { + refreshMutex.release(); + } + + WalletSyncStatus? status; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true); + + if (_syncStatus is SyncingSyncStatus) { + final int blocksLeft = _syncStatus.blocksLeft; + + // ensure at least 1 to prevent math errors + final int height = max(1, _syncStatus.height); + + final nodeHeight = height + blocksLeft; + currentKnownChainHeight = nodeHeight; + + // final percent = height / nodeHeight; + final percent = _syncStatus.ptc; + + final highest = max(highestPercentCached, percent); + + final unchanged = highest == highestPercentCached; + if (unchanged) { + return; + } + + // update cached + if (highestPercentCached < percent) { + highestPercentCached = percent; + } + + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highest, walletId), + ); + GlobalEventBus.instance.fire( + BlocksRemainingEvent(blocksLeft, walletId), + ); + } else if (_syncStatus is SyncedSyncStatus) { + status = WalletSyncStatus.synced; + } else if (_syncStatus is NotConnectedSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } else if (_syncStatus is StartingSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is FailedSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } else if (_syncStatus is ConnectingSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is ConnectedSyncStatus) { + status = WalletSyncStatus.syncing; + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + } else if (_syncStatus is LostConnectionSyncStatus) { + status = WalletSyncStatus.unableToSync; + xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false); + } + + if (status != null) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent(status, walletId, info.coin), + ); + } + } + } @override Future checkSaveInitialReceivingAddress() async { @@ -935,21 +923,20 @@ abstract class LibSalviumWallet if (_txRefreshLock) return; _txRefreshLock = true; - // final _syncStatus = syncStatus; + final _syncStatus = syncStatus; - // if (_syncStatus != null && - // _syncStatus is lib_monero_compat.SyncingSyncStatus) { - // final int blocksLeft = _syncStatus.blocksLeft; - // final tenKChange = blocksLeft ~/ 10000; - // - // // only refresh transactions periodically during a sync - // if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) { - // _lastCheckedHeight = tenKChange; - // await _refreshTxData(); - // } - // } else { - // await _refreshTxData(); - // } + if (_syncStatus != null && _syncStatus is SyncingSyncStatus) { + final int blocksLeft = _syncStatus.blocksLeft; + final tenKChange = blocksLeft ~/ 10000; + + // only refresh transactions periodically during a sync + if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) { + _lastCheckedHeight = tenKChange; + await _refreshTxData(); + } + } else { + await _refreshTxData(); + } _txRefreshLock = false; } @@ -1071,7 +1058,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + _setSyncStatus(FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } else { @@ -1079,7 +1066,7 @@ abstract class LibSalviumWallet libSalviumWallet?.stopAutoSaving(); libSalviumWallet?.stopListeners(); libSalviumWallet?.stopSyncing(); - // _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + _setSyncStatus(FailedSyncStatus()); throw Exception("TOR - clearnet mismatch"); } } @@ -1089,7 +1076,7 @@ abstract class LibSalviumWallet await refreshMutex.acquire(); libSalviumWallet?.startSyncing(); - // _setSyncStatus(lib_monero_compat.StartingSyncStatus()); + _setSyncStatus(StartingSyncStatus()); await updateTransactions(); await updateBalance(); @@ -1105,7 +1092,7 @@ abstract class LibSalviumWallet final synced = await libSalviumWallet?.isSynced(); if (synced == true) { - // _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); + _setSyncStatus(SyncedSyncStatus()); } } @@ -1542,3 +1529,66 @@ Future _pathForWallet({ name: name, appRoot: appRoot, ).then((path) => '$path/$name'); + +// ============================================================================= +// The following sync status stuff copy pasted here for now to simplify the +// integration of salvium. +// TODO: eventually rework this (one day) + +abstract class SyncStatus { + const SyncStatus(); + double progress(); +} + +class SyncingSyncStatus extends SyncStatus { + SyncingSyncStatus(this.blocksLeft, this.ptc, this.height); + + final double ptc; + final int blocksLeft; + final int height; + + @override + double progress() => ptc; + + @override + String toString() => '$blocksLeft'; +} + +class SyncedSyncStatus extends SyncStatus { + @override + double progress() => 1.0; +} + +class NotConnectedSyncStatus extends SyncStatus { + const NotConnectedSyncStatus(); + + @override + double progress() => 0.0; +} + +class StartingSyncStatus extends SyncStatus { + @override + double progress() => 0.0; +} + +class FailedSyncStatus extends SyncStatus { + @override + double progress() => 1.0; +} + +class ConnectingSyncStatus extends SyncStatus { + @override + double progress() => 0.0; +} + +class ConnectedSyncStatus extends SyncStatus { + @override + double progress() => 0.0; +} + +class LostConnectionSyncStatus extends SyncStatus { + @override + double progress() => 1.0; +} + +// ============================================================================= From 0872e7245397c221f658accf494f10131b7600b9 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 14:20:46 -0600 Subject: [PATCH 090/206] hook up salvium wallet files deletion --- lib/services/wallets.dart | 50 +++++++++++++------ .../intermediate/lib_salvium_wallet.dart | 5 ++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/lib/services/wallets.dart b/lib/services/wallets.dart index ce10f548b..7b5f9a376 100644 --- a/lib/services/wallets.dart +++ b/lib/services/wallets.dart @@ -9,6 +9,7 @@ */ import 'dart:async'; +import 'dart:io'; import 'package:compat/compat.dart' as lib_monero_compat; import 'package:isar/isar.dart'; @@ -22,6 +23,7 @@ import '../utilities/logger.dart'; import '../utilities/prefs.dart'; import '../utilities/stack_file_system.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; +import '../wallets/crypto_currency/intermediate/cryptonote_currency.dart'; import '../wallets/isar/models/wallet_info.dart'; import '../wallets/wallet/impl/epiccash_wallet.dart'; import '../wallets/wallet/intermediate/lib_monero_wallet.dart'; @@ -68,6 +70,38 @@ class Wallets { } } + Future _deleteCryptonoteWalletFilesHelper(WalletInfo info) async { + final walletId = info.walletId; + if (info.coin is Wownero) { + await lib_monero_compat.deleteWalletFiles( + name: walletId, + type: lib_monero_compat.WalletType.wownero, + appRoot: await StackFileSystem.applicationRootDirectory(), + ); + Logging.instance.d("Wownero wallet: $walletId deleted"); + } else if (info.coin is Monero) { + await lib_monero_compat.deleteWalletFiles( + name: walletId, + type: lib_monero_compat.WalletType.monero, + appRoot: await StackFileSystem.applicationRootDirectory(), + ); + Logging.instance.d("Monero wallet: $walletId deleted"); + } else if (info.coin is Salvium) { + final path = await salviumWalletDir( + walletId: walletId, + appRoot: await StackFileSystem.applicationRootDirectory(), + ); + final file = Directory(path); + final isExist = file.existsSync(); + + if (isExist) { + await file.delete(recursive: true); + } + } else { + throw Exception("Not a valid CN coin"); + } + } + Future deleteWallet( WalletInfo info, SecureStorageInterface secureStorage, @@ -88,20 +122,8 @@ class Wallets { key: Wallet.getViewOnlyWalletDataSecStoreKey(walletId: walletId), ); - if (info.coin is Wownero) { - await lib_monero_compat.deleteWalletFiles( - name: walletId, - type: lib_monero_compat.WalletType.wownero, - appRoot: await StackFileSystem.applicationRootDirectory(), - ); - Logging.instance.d("monero wallet: $walletId deleted"); - } else if (info.coin is Monero) { - await lib_monero_compat.deleteWalletFiles( - name: walletId, - type: lib_monero_compat.WalletType.monero, - appRoot: await StackFileSystem.applicationRootDirectory(), - ); - Logging.instance.d("monero wallet: $walletId deleted"); + if (info.coin is CryptonoteCurrency) { + await _deleteCryptonoteWalletFilesHelper(info); } else if (info.coin is Epiccash) { final deleteResult = await deleteEpicWallet( walletId: walletId, diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index a70c69d68..fcb1cae60 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -1530,6 +1530,11 @@ Future _pathForWallet({ appRoot: appRoot, ).then((path) => '$path/$name'); +Future salviumWalletDir({ + required String walletId, + required Directory appRoot, +}) => _pathForWalletDir(name: walletId, appRoot: appRoot); + // ============================================================================= // The following sync status stuff copy pasted here for now to simplify the // integration of salvium. From f67940acefa0ba7452be308eae19fd8697a80c4f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 15:08:23 -0600 Subject: [PATCH 091/206] auto format --- lib/app_config.dart | 6 +- .../exchange_data_loading_service.dart | 119 +++++++++--------- 2 files changed, 57 insertions(+), 68 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 62ce560c3..9f862f4c7 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -3,11 +3,7 @@ import 'wallets/crypto_currency/intermediate/frost_currency.dart'; part 'app_config.g.dart'; -enum AppFeature { - themeSelection, - buy, - swap; -} +enum AppFeature { themeSelection, buy, swap } abstract class AppConfig { static const appName = _prefix + _separator + suffix; diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index 1cfaee23b..80b7c53af 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -43,9 +43,10 @@ class ExchangeDataLoadingService { static int get currentCacheVersion => DB.instance.get( - boxName: DB.boxNameDBInfo, - key: "exchange_data_cache_version", - ) as int? ?? + boxName: DB.boxNameDBInfo, + key: "exchange_data_cache_version", + ) + as int? ?? 0; Future _updateCurrentCacheVersion(int version) async { @@ -88,11 +89,7 @@ class ExchangeDataLoadingService { ); pair?.setReceive( - await getAggregateCurrency( - AppConfig.swapDefaults.to, - rateType, - null, - ), + await getAggregateCurrency(AppConfig.swapDefaults.to, rateType, null), notifyListeners: false, ); } @@ -104,27 +101,26 @@ class ExchangeDataLoadingService { ExchangeRateType rateType, String? contract, ) async { - final currencies = await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo( - ticker, - caseSensitive: false, - ) - .and() - .tokenContractEqualTo(contract) - .findAll(); + final currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .and() + .tickerEqualTo(ticker, caseSensitive: false) + .and() + .tokenContractEqualTo(contract) + .findAll(); final items = currencies .map((e) => Tuple2(e.exchangeName, e)) @@ -145,9 +141,7 @@ class ExchangeDataLoadingService { if (_isar == null) { await initDB(); } - Logging.instance.d( - "ExchangeDataLoadingService.loadAll starting...", - ); + Logging.instance.d("ExchangeDataLoadingService.loadAll starting..."); final start = DateTime.now(); try { /* @@ -209,11 +203,12 @@ class ExchangeDataLoadingService { final responseCurrencies = await exchange.getAllCurrencies(false); if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); @@ -342,18 +337,17 @@ class ExchangeDataLoadingService { if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(MajesticBankExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadMajesticBankCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); } } @@ -366,18 +360,17 @@ class ExchangeDataLoadingService { if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(TrocadorExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(TrocadorExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadTrocadorCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadTrocadorCurrencies: $responseCurrencies"); } } @@ -385,23 +378,23 @@ class ExchangeDataLoadingService { if (_isar == null) { await initDB(); } - final responseCurrencies = - await NanswapExchange.instance.getAllCurrencies(false); + final responseCurrencies = await NanswapExchange.instance.getAllCurrencies( + false, + ); if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(NanswapExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(NanswapExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadNanswapCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadNanswapCurrencies: $responseCurrencies"); } } From b6b63bca3e690b8f96a368de73f5353921edc59a Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 08:17:33 -0600 Subject: [PATCH 092/206] fix: swap issues --- lib/app_config.dart | 3 +- lib/models/exchange/aggregate_currency.dart | 20 ++- .../change_now/estimated_exchange_amount.dart | 6 +- lib/models/isar/exchange_cache/currency.dart | 39 +++- .../exchange_currency_selection_view.dart | 168 ++++++++---------- lib/pages/exchange_view/exchange_form.dart | 77 ++------ .../exchange_data_loading_service.dart | 73 +++++--- .../exchange/trocador/trocador_api.dart | 58 +++--- scripts/app_config/configure_campfire.sh | 8 +- scripts/app_config/configure_stack_duo.sh | 8 +- scripts/app_config/configure_stack_wallet.sh | 8 +- 11 files changed, 236 insertions(+), 232 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 9f862f4c7..96b07b2c9 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -23,7 +23,8 @@ abstract class AppConfig { static List get coins => _supportedCoins; - static ({String from, String to}) get swapDefaults => _swapDefaults; + static ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) + get swapDefaults => _swapDefaults; static bool get isSingleCoinApp => coins.length == 1; diff --git a/lib/models/exchange/aggregate_currency.dart b/lib/models/exchange/aggregate_currency.dart index ffaccd3c0..580e1b3bf 100644 --- a/lib/models/exchange/aggregate_currency.dart +++ b/lib/models/exchange/aggregate_currency.dart @@ -42,13 +42,29 @@ class AggregateCurrency { bool get isStackCoin => _map.values.first!.isStackCoin; + String get fuzzyNet => _map.values.first!.getFuzzyNet(); + @override String toString() { String str = "AggregateCurrency: {"; for (final key in _map.keys) { - str += " $key: ${_map[key]},"; + str += "\n $key: ${_map[key]},"; } - str += " }"; + str += "\n}"; return str; } + + @override + bool operator ==(Object other) { + return other is AggregateCurrency && + other.ticker == ticker && + other._map.isNotEmpty && + other._map.length == _map.length && + other._map.values.first!.getFuzzyNet() == + _map.values.first!.getFuzzyNet(); + } + + @override + int get hashCode => + Object.hash(ticker, _map.values.first!.getFuzzyNet(), _map.length); } diff --git a/lib/models/exchange/change_now/estimated_exchange_amount.dart b/lib/models/exchange/change_now/estimated_exchange_amount.dart index 7648cdacb..b36efe480 100644 --- a/lib/models/exchange/change_now/estimated_exchange_amount.dart +++ b/lib/models/exchange/change_now/estimated_exchange_amount.dart @@ -29,7 +29,7 @@ class EstimatedExchangeAmount { final String? rateId; /// Date and time before which the estimated amount is valid if using `rateId`. - final DateTime validUntil; + final DateTime? validUntil; /// Dash-separated min and max estimated time in minutes. final String? transactionSpeedForecast; @@ -87,7 +87,7 @@ class EstimatedExchangeAmount { flow: _parseFlow(json["flow"] as String), type: _parseType(json["type"] as String), rateId: json["rateId"] as String?, - validUntil: DateTime.parse(json["validUntil"] as String), + validUntil: DateTime.tryParse(json["validUntil"] as String? ?? ""), transactionSpeedForecast: json["transactionSpeedForecast"] as String?, warningMessage: json["warningMessage"] as String?, depositFee: Decimal.parse(json["depositFee"].toString()), @@ -108,7 +108,7 @@ class EstimatedExchangeAmount { "flow": flow.name.replaceAll("fixedRate", "fixed-rate"), "type": type.name, "rateId": rateId, - "validUntil": validUntil.toIso8601String(), + "validUntil": validUntil?.toIso8601String(), "transactionSpeedForecast": transactionSpeedForecast, "warningMessage": warningMessage, "depositFee": depositFee.toString(), diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index 29fed140d..04c510186 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -11,6 +11,11 @@ import 'package:isar/isar.dart'; import '../../../app_config.dart'; +import '../../../services/exchange/change_now/change_now_exchange.dart'; +import '../../../services/exchange/exchange.dart'; +import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; +import '../../../services/exchange/nanswap/nanswap_exchange.dart'; +import '../../../services/exchange/trocador/trocador_exchange.dart'; import 'pair.dart'; part 'currency.g.dart'; @@ -23,12 +28,7 @@ class Currency { final String exchangeName; /// Currency ticker - @Index( - composite: [ - CompositeIndex("exchangeName"), - CompositeIndex("name"), - ], - ) + @Index(composite: [CompositeIndex("exchangeName"), CompositeIndex("name")]) final String ticker; /// Currency name @@ -68,6 +68,33 @@ class Currency { rateType == SupportedRateType.estimated || rateType == SupportedRateType.both; + // used to group coins across providers + @ignore + String? _fuzzyCache; + String getFuzzyNet() { + return _fuzzyCache ??= switch (Exchange.fromName( + exchangeName, + ).runtimeType) { + // already lower case ticker basically + const (ChangeNowExchange) => network, + + // not used at the time being + // case const (SimpleSwapExchange): + + // currently a hardcoded of coins so we can just + const (MajesticBankExchange) => ticker.toLowerCase(), + + const (TrocadorExchange) => + (network == "Mainnet" ? ticker.toLowerCase() : network), + + // only a few coins and `network` is the ticker + const (NanswapExchange) => + network.isNotEmpty ? network.toLowerCase() : ticker.toLowerCase(), + + _ => throw Exception("Unknown exchange: $exchangeName"), + }; + } + Currency({ required this.exchangeName, required this.ticker, diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 5c51ac134..291a61781 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -13,18 +13,18 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; +import 'package:tuple/tuple.dart'; import '../../../app_config.dart'; +import '../../../models/exchange/aggregate_currency.dart'; import '../../../models/isar/exchange_cache/currency.dart'; import '../../../models/isar/exchange_cache/pair.dart'; import '../../../services/exchange/exchange.dart'; import '../../../services/exchange/exchange_data_loading_service.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; -import '../../../services/exchange/nanswap/nanswap_exchange.dart'; -import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; +import '../../../utilities/logger.dart'; import '../../../utilities/prefs.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -42,14 +42,12 @@ import '../../buy_view/sub_widgets/crypto_selection_view.dart'; class ExchangeCurrencySelectionView extends StatefulWidget { const ExchangeCurrencySelectionView({ super.key, - required this.willChangeTicker, - required this.pairedTicker, + required this.pairedCurrency, required this.isFixedRate, required this.willChangeIsSend, }); - final String? willChangeTicker; - final String? pairedTicker; + final AggregateCurrency? pairedCurrency; final bool isFixedRate; final bool willChangeIsSend; @@ -64,7 +62,7 @@ class _ExchangeCurrencySelectionViewState final _searchFocusNode = FocusNode(); final isDesktop = Util.isDesktop; - List _currencies = []; + List _currencies = []; bool _loaded = false; String _searchString = ""; @@ -99,26 +97,7 @@ class _ExchangeCurrencySelectionViewState return result; } - Future> _loadCurrencies() async { - if (widget.pairedTicker == null) { - return await _getCurrencies(); - } - await ExchangeDataLoadingService.instance.initDB(); - final List currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .where() - .filter() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .or() - .exchangeNameStartsWith(TrocadorExchange.exchangeName) - .or() - .exchangeNameStartsWith(NanswapExchange.exchangeName) - .findAll(); - - return _getDistinctCurrenciesFrom(currencies); - } - - Future> _getCurrencies() async { + Future> _loadCurrencies() async { await ExchangeDataLoadingService.instance.initDB(); final currencies = await ExchangeDataLoadingService.instance.isar.currencies @@ -154,53 +133,78 @@ class _ExchangeCurrencySelectionViewState } } - return _getDistinctCurrenciesFrom(currencies); + return await _getDistinctCurrenciesFrom(currencies); } - List _getDistinctCurrenciesFrom(List currencies) { - final List distinctCurrencies = []; + Future> _getDistinctCurrenciesFrom( + List currencies, + ) async { + final Map> groups = {}; + for (final currency in currencies) { - if (!distinctCurrencies.any( - (e) => e.ticker.toLowerCase() == currency.ticker.toLowerCase(), - )) { - distinctCurrencies.add(currency); - } + final key = '${currency.ticker.toLowerCase()}|${currency.getFuzzyNet()}'; + + groups.putIfAbsent(key, () => []).add(currency); } - return distinctCurrencies; - } - List filter(String text) { - if (widget.pairedTicker == null) { - if (text.isEmpty) { - return _currencies; - } + final Set results = {}; + + for (final group in groups.values) { + final items = group + .map((e) => Tuple2(e.exchangeName, e)) + .toList(growable: false); + + results.add(AggregateCurrency(exchangeCurrencyPairs: items)); + } + + if (widget.pairedCurrency != null) { + results.remove(widget.pairedCurrency); + } - return _currencies - .where( - (e) => - e.name.toLowerCase().contains(text.toLowerCase()) || - e.ticker.toLowerCase().contains(text.toLowerCase()), - ) - .toList(); - } else { - if (text.isEmpty) { - return _currencies + final walletCoins = + results .where( - (e) => - e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase(), + (currency) => + AppConfig.coins + .where( + (coin) => + coin.ticker.toLowerCase() == + currency.ticker.toLowerCase() && + currency.fuzzyNet == coin.ticker.toLowerCase(), + ) + .isNotEmpty, ) .toList(); - } - return _currencies - .where( - (e) => - e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() && - (e.name.toLowerCase().contains(text.toLowerCase()) || - e.ticker.toLowerCase().contains(text.toLowerCase())), - ) - .toList(); + final list = results.toList(); + + // sort alphabetically by name + list.sort((a, b) => a.name.compareTo(b.name)); + + // reverse sort walletCoins to prepare for next step + walletCoins.sort((a, b) => b.name.compareTo(a.name)); + + // insert wallet coins at beginning + for (final c in walletCoins) { + list.remove(c); + list.insert(0, c); + } + + return list; + } + + List filter(String text) { + if (text.isEmpty) { + return _currencies.toList(); } + + return _currencies + .where( + (e) => + e.name.toLowerCase().contains(text.toLowerCase()) || + e.ticker.toLowerCase().contains(text.toLowerCase()), + ) + .toList(); } @override @@ -325,40 +329,8 @@ class _ExchangeCurrencySelectionViewState Flexible( child: Builder( builder: (context) { - final coins = AppConfig.coins.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, - ) - .toList(); - - // sort alphabetically by name - items.sort((a, b) => a.name.compareTo(b.name)); - - // reverse sort walletCoins to prepare for next step - walletCoins.sort((a, b) => b.name.compareTo(a.name)); - - // insert wallet coins at beginning - for (final c in walletCoins) { - items.remove(c); - items.insert(0, c); - } - return RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: ListView.builder( @@ -373,7 +345,9 @@ class _ExchangeCurrencySelectionViewState padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( onTap: () { - Navigator.of(context).pop(items[index]); + final selected = items[index]; + Logging.instance.d("swap selected: $selected"); + Navigator.of(context).pop(selected); }, child: RoundedWhiteContainer( child: Row( diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 6976d557b..70671cb5c 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -15,7 +15,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; @@ -23,8 +22,6 @@ import '../../models/exchange/aggregate_currency.dart'; import '../../models/exchange/incomplete_exchange.dart'; import '../../models/exchange/response_objects/estimate.dart'; import '../../models/exchange/response_objects/range.dart'; -import '../../models/isar/exchange_cache/currency.dart'; -import '../../models/isar/exchange_cache/pair.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart'; import '../../providers/providers.dart'; @@ -179,38 +176,6 @@ class _ExchangeFormState extends ConsumerState { ?.decimal; } - Future _getAggregateCurrency(Currency currency) async { - final rateType = ref.read(efRateTypeProvider); - final currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => - rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo(currency.ticker, caseSensitive: false) - .and() - .tokenContractEqualTo(currency.tokenContract) - .findAll(); - - final items = [Tuple2(currency.exchangeName, currency)]; - - for (final currency in currencies) { - items.add(Tuple2(currency.exchangeName, currency)); - } - - return AggregateCurrency(exchangeCurrencyPairs: items); - } - void selectSendCurrency() async { final type = ref.read(efRateTypeProvider); final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; @@ -228,20 +193,15 @@ class _ExchangeFormState extends ConsumerState { } final selectedCurrency = await _showCurrencySelectionSheet( - willChange: ref.read(efCurrencyPairProvider).send?.ticker, willChangeIsSend: true, - paired: ref.read(efCurrencyPairProvider).receive?.ticker, + paired: ref.read(efCurrencyPairProvider).receive, isFixedRate: type == ExchangeRateType.fixed, ); if (selectedCurrency != null) { - await showUpdatingExchangeRate( - whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref - .read(efCurrencyPairProvider) - .setSend(aggregateSelected, notifyListeners: true), - ), - ); + ref + .read(efCurrencyPairProvider) + .setSend(selectedCurrency, notifyListeners: true); } } @@ -254,20 +214,15 @@ class _ExchangeFormState extends ConsumerState { } final selectedCurrency = await _showCurrencySelectionSheet( - willChange: ref.read(efCurrencyPairProvider).receive?.ticker, willChangeIsSend: false, - paired: ref.read(efCurrencyPairProvider).send?.ticker, + paired: ref.read(efCurrencyPairProvider).send, isFixedRate: ref.read(efRateTypeProvider) == ExchangeRateType.fixed, ); if (selectedCurrency != null) { - await showUpdatingExchangeRate( - whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref - .read(efCurrencyPairProvider) - .setReceive(aggregateSelected, notifyListeners: true), - ), - ); + ref + .read(efCurrencyPairProvider) + .setReceive(selectedCurrency, notifyListeners: true); } } @@ -299,9 +254,8 @@ class _ExchangeFormState extends ConsumerState { _swapLock = false; } - Future _showCurrencySelectionSheet({ - required String? willChange, - required String? paired, + Future _showCurrencySelectionSheet({ + required AggregateCurrency? paired, required bool isFixedRate, required bool willChangeIsSend, }) async { @@ -310,7 +264,7 @@ class _ExchangeFormState extends ConsumerState { final result = isDesktop - ? await showDialog( + ? await showDialog( context: context, builder: (context) { return DesktopDialog( @@ -348,8 +302,7 @@ class _ExchangeFormState extends ConsumerState { context, ).extension()!.background, child: ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, + pairedCurrency: paired, isFixedRate: isFixedRate, willChangeIsSend: willChangeIsSend, ), @@ -368,15 +321,14 @@ class _ExchangeFormState extends ConsumerState { MaterialPageRoute( builder: (_) => ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, + pairedCurrency: paired, isFixedRate: isFixedRate, willChangeIsSend: willChangeIsSend, ), ), ); - if (mounted && result is Currency) { + if (mounted && result is AggregateCurrency) { return result; } else { return null; @@ -769,6 +721,7 @@ class _ExchangeFormState extends ConsumerState { ExchangeDataLoadingService.instance .getAggregateCurrency( widget.contract == null ? coin!.ticker : widget.contract!.symbol, + coin!.ticker.toLowerCase(), ExchangeRateType.estimated, widget.contract?.address, ) diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index 80b7c53af..f1a181104 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -82,6 +82,7 @@ class ExchangeDataLoadingService { pair?.setSend( await getAggregateCurrency( AppConfig.swapDefaults.from, + AppConfig.swapDefaults.fromFuzzyNet, rateType, null, ), @@ -89,7 +90,12 @@ class ExchangeDataLoadingService { ); pair?.setReceive( - await getAggregateCurrency(AppConfig.swapDefaults.to, rateType, null), + await getAggregateCurrency( + AppConfig.swapDefaults.to, + AppConfig.swapDefaults.toFuzzyNet, + rateType, + null, + ), notifyListeners: false, ); } @@ -98,29 +104,54 @@ class ExchangeDataLoadingService { Future getAggregateCurrency( String ticker, + String fuzzyNet, ExchangeRateType rateType, String? contract, ) async { - final currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => - rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo(ticker, caseSensitive: false) - .and() - .tokenContractEqualTo(contract) - .findAll(); + final List currencies; + if (contract != null) { + currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .tokenContractEqualTo(contract) + .and() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .findAll(); + } else { + currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .and() + .tickerEqualTo(ticker, caseSensitive: false) + .and() + .tokenContractIsNull() + .findAll(); + } + + currencies.retainWhere((e) => e.getFuzzyNet() == fuzzyNet); final items = currencies .map((e) => Tuple2(e.exchangeName, e)) diff --git a/lib/services/exchange/trocador/trocador_api.dart b/lib/services/exchange/trocador/trocador_api.dart index 9aff6d872..917fee3f3 100644 --- a/lib/services/exchange/trocador/trocador_api.dart +++ b/lib/services/exchange/trocador/trocador_api.dart @@ -56,9 +56,10 @@ abstract class TrocadorAPI { "Content-Type": "application/json", "API-KEY": kTrocadorApiKey, }, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); code = response.code; @@ -68,10 +69,17 @@ abstract class TrocadorAPI { final json = jsonDecode(response.body); + if (code != 200) { + throw Exception(json["error"] as String? ?? json); + } + return json; } catch (e, s) { - Logging.instance - .e("_makeRequest($uri) HTTP:$code threw: ", error: e, stackTrace: s); + Logging.instance.e( + "_makeRequest($uri) HTTP:$code threw: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -83,9 +91,7 @@ abstract class TrocadorAPI { final uri = _buildUri( isOnion: isOnion, method: "coins", - params: { - "ref": kTrocadorRefCode, - }, + params: {"ref": kTrocadorRefCode}, ); try { @@ -93,22 +99,15 @@ abstract class TrocadorAPI { if (json is List) { final list = List>.from(json); - final List coins = list - .map( - (e) => TrocadorCoin.fromMap(e), - ) - .toList(); + final List coins = + list.map((e) => TrocadorCoin.fromMap(e)).toList(); return ExchangeResponse(value: coins); } else { throw Exception("unexpected json: $json"); } } catch (e, s) { - Logging.instance.e( - "getCoins exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getCoins exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -126,10 +125,7 @@ abstract class TrocadorAPI { final uri = _buildUri( isOnion: isOnion, method: "trade", - params: { - "ref": kTrocadorRefCode, - "id": tradeId, - }, + params: {"ref": kTrocadorRefCode, "id": tradeId}, ); try { @@ -138,11 +134,7 @@ abstract class TrocadorAPI { return ExchangeResponse(value: TrocadorTrade.fromMap(map)); } catch (e, s) { - Logging.instance.e( - "getTrade exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getTrade exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -204,11 +196,7 @@ abstract class TrocadorAPI { required bool isOnion, required Map params, }) async { - final uri = _buildUri( - isOnion: isOnion, - method: "new_rate", - params: params, - ); + final uri = _buildUri(isOnion: isOnion, method: "new_rate", params: params); try { final json = await _makeGetRequest(uri); @@ -216,11 +204,7 @@ abstract class TrocadorAPI { return ExchangeResponse(value: TrocadorRate.fromMap(map)); } catch (e, s) { - Logging.instance.e( - "getNewRate exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getNewRate exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), diff --git a/scripts/app_config/configure_campfire.sh b/scripts/app_config/configure_campfire.sh index 883d67fa0..258058aae 100755 --- a/scripts/app_config/configure_campfire.sh +++ b/scripts/app_config/configure_campfire.sh @@ -62,6 +62,12 @@ final List _supportedCoins = List.unmodifiable([ Firo(CryptoCurrencyNetwork.main), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "FIRO"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "FIRO", + toFuzzyNet: "firo", +); EOF \ No newline at end of file diff --git a/scripts/app_config/configure_stack_duo.sh b/scripts/app_config/configure_stack_duo.sh index 7d1a7665a..4c871fff3 100755 --- a/scripts/app_config/configure_stack_duo.sh +++ b/scripts/app_config/configure_stack_duo.sh @@ -64,6 +64,12 @@ final List _supportedCoins = List.unmodifiable([ BitcoinFrost(CryptoCurrencyNetwork.test4), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "XMR", + toFuzzyNet: "xmr", +); EOF \ No newline at end of file diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index e46420fa0..3268eca0d 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -87,6 +87,12 @@ final List _supportedCoins = List.unmodifiable([ Xelis(CryptoCurrencyNetwork.test), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "XMR", + toFuzzyNet: "xmr", +); EOF \ No newline at end of file From 397f496e7b37abd7b1cff3f4bce9a69b57143134 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:05:25 -0600 Subject: [PATCH 093/206] clean up swap currency selection list items and add trocador warnings for ltc and firo --- .gitignore | 1 + lib/models/exchange/aggregate_currency.dart | 30 +- .../exchange_currency_selection_view.dart | 71 +++- lib/pages/exchange_view/exchange_form.dart | 93 ++++- .../sub_widgets/exchange_provider_option.dart | 332 +++++++++++------- .../token_view/sub_widgets/token_summary.dart | 28 +- .../wallet_view/desktop_token_view.dart | 116 +++--- .../exchange/trocador/trocador_exchange.dart | 38 ++ lib/widgets/coin_ticker_tag.dart | 26 ++ .../wallet_info_row/wallet_info_row.dart | 107 +++--- 10 files changed, 534 insertions(+), 308 deletions(-) create mode 100644 lib/widgets/coin_ticker_tag.dart diff --git a/.gitignore b/.gitignore index b61c79144..7b550e43e 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,4 @@ scripts/linux/build/libsecret/subprojects/gi-docgen/.meson-subproject-wrap-hash. crypto_plugins/cs_monero/built_outputs crypto_plugins/cs_monero/build crypto_plugins/*.diff +/devtools_options.yaml diff --git a/lib/models/exchange/aggregate_currency.dart b/lib/models/exchange/aggregate_currency.dart index 580e1b3bf..b2fa09f30 100644 --- a/lib/models/exchange/aggregate_currency.dart +++ b/lib/models/exchange/aggregate_currency.dart @@ -10,11 +10,12 @@ import 'package:tuple/tuple.dart'; +import '../../services/exchange/trocador/trocador_exchange.dart'; import '../isar/exchange_cache/currency.dart'; import '../isar/exchange_cache/pair.dart'; class AggregateCurrency { - final Map _map = {}; + final Map _map = {}; AggregateCurrency({ required List> exchangeCurrencyPairs, @@ -32,17 +33,26 @@ class AggregateCurrency { String? networkFor(String exchangeName) => forExchange(exchangeName)?.network; - String get ticker => _map.values.first!.ticker; + String get ticker => _map.values.first.ticker; - String get name => _map.values.first!.name; + String get name { + if (_map.values.length > 2) { + return _map.values + .firstWhere((e) => e.exchangeName != TrocadorExchange.exchangeName) + .name; + } + + // trocador hack + return _map.values.first.name.split(" (Mainnet").first; + } - String get image => _map.values.first!.image; + String get image => _map.values.first.image; - SupportedRateType get rateType => _map.values.first!.rateType; + SupportedRateType get rateType => _map.values.first.rateType; - bool get isStackCoin => _map.values.first!.isStackCoin; + bool get isStackCoin => _map.values.first.isStackCoin; - String get fuzzyNet => _map.values.first!.getFuzzyNet(); + String get fuzzyNet => _map.values.first.getFuzzyNet(); @override String toString() { @@ -60,11 +70,11 @@ class AggregateCurrency { other.ticker == ticker && other._map.isNotEmpty && other._map.length == _map.length && - other._map.values.first!.getFuzzyNet() == - _map.values.first!.getFuzzyNet(); + other._map.values.first.getFuzzyNet() == + _map.values.first.getFuzzyNet(); } @override int get hashCode => - Object.hash(ticker, _map.values.first!.getFuzzyNet(), _map.length); + Object.hash(ticker, _map.values.first.getFuzzyNet(), _map.length); } diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 291a61781..ce861d560 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -29,6 +29,7 @@ import '../../../utilities/prefs.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../widgets/background.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_loading_overlay.dart'; @@ -338,9 +339,8 @@ class _ExchangeCurrencySelectionViewState primary: isDesktop ? false : null, itemCount: items.length, itemBuilder: (builderContext, index) { - final bool hasImageUrl = items[index].image.startsWith( - "http", - ); + final image = items[index].image; + final hasImageUrl = image.startsWith("http"); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( @@ -363,18 +363,12 @@ class _ExchangeCurrencySelectionViewState ticker: items[index].ticker, size: 24, ) - // ? getIconForTicker( - // items[index].ticker, - // size: 24, - // ) : hasImageUrl - ? SvgPicture.network( - items[index].image, - width: 24, - height: 24, - placeholderBuilder: - (_) => - const LoadingIndicator(), + ? _NetImage( + url: image, + key: ValueKey( + image + items[index].fuzzyNet, + ), ) : const SizedBox( width: 24, @@ -387,11 +381,29 @@ class _ExchangeCurrencySelectionViewState crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - items[index].name, - style: STextStyles.largeMedium14( - context, - ), + Row( + children: [ + Text( + items[index].name, + style: STextStyles.largeMedium14( + context, + ), + ), + if (items[index].ticker + .toLowerCase() != + items[index].fuzzyNet + .toLowerCase()) + Padding( + padding: const EdgeInsets.only( + left: 12, + ), + child: CoinTickerTag( + ticker: + items[index].fuzzyNet + .toUpperCase(), + ), + ), + ], ), const SizedBox(height: 2), Text( @@ -425,3 +437,24 @@ class _ExchangeCurrencySelectionViewState ); } } + +class _NetImage extends StatelessWidget { + const _NetImage({super.key, required this.url}); + + final String url; + + @override + Widget build(BuildContext context) { + if (url.endsWith(".svg")) { + return SvgPicture.network( + key: key, + url, + width: 24, + height: 24, + placeholderBuilder: (_) => const LoadingIndicator(), + ); + } else { + return Image.network(url, width: 24, height: 24, key: key); + } + } +} diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 70671cb5c..488a74674 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -22,6 +22,7 @@ import '../../models/exchange/aggregate_currency.dart'; import '../../models/exchange/incomplete_exchange.dart'; import '../../models/exchange/response_objects/estimate.dart'; import '../../models/exchange/response_objects/range.dart'; +import '../../models/isar/exchange_cache/currency.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart'; import '../../providers/providers.dart'; @@ -47,6 +48,7 @@ import '../../widgets/desktop/desktop_dialog.dart'; import '../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../widgets/desktop/primary_button.dart'; import '../../widgets/desktop/secondary_button.dart'; +import '../../widgets/dialogs/basic_dialog.dart'; import '../../widgets/rounded_container.dart'; import '../../widgets/rounded_white_container.dart'; import '../../widgets/stack_dialog.dart'; @@ -343,9 +345,80 @@ class _ExchangeFormState extends ConsumerState { update(); } + Future _checkTrocadorWarning(Currency from, Currency to) async { + final Set warnings = {}; + + final firoWarning = + TrocadorExchange.checkFiro(from) ?? TrocadorExchange.checkFiro(to); + final ltcWarning = + TrocadorExchange.checkLtc(from) ?? TrocadorExchange.checkLtc(to); + + if (firoWarning != null) warnings.add(firoWarning); + if (ltcWarning != null) warnings.add(ltcWarning); + + if (warnings.isNotEmpty) { + final title = warnings.map((e) => e.message).join(" and "); + final message = warnings.map((e) => e.messageDetail).join(" "); + + final result = await showDialog( + context: context, + builder: (context) { + return BasicDialog( + title: title, + message: message, + canPopWithBackButton: true, + flex: true, + desktopHeight: 400, + leftButton: SecondaryButton( + label: "Cancel", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: () => Navigator.of(context).pop(false), + ), + rightButton: PrimaryButton( + label: "Continue", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: () => Navigator.of(context).pop(true), + ), + ); + }, + ); + + return result == true; + } else { + return true; + } + } + void onExchangePressed() async { final exchangeName = ref.read(efExchangeProvider).name; + final fromCurrency = ref + .read(efCurrencyPairProvider) + .send + ?.forExchange(exchangeName); + final toCurrency = ref + .read(efCurrencyPairProvider) + .receive + ?.forExchange(exchangeName); + + if (fromCurrency == null || toCurrency == null) { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "Missing currency!", + message: "This should not happen. Please contact support", + ), + ); + + return; + } + + if (exchangeName == TrocadorExchange.exchangeName) { + final canContinue = await _checkTrocadorWarning(fromCurrency, toCurrency); + if (!canContinue) return; + } + final rateType = ref.read(efRateTypeProvider); final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; final fromNetwork = ref @@ -361,15 +434,17 @@ class _ExchangeFormState extends ConsumerState { final sendAmount = ref.read(efSendAmountProvider)!; if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") { - await showDialog( - context: context, - builder: - (context) => const StackOkDialog( - title: "WOW error", - message: - "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", - ), - ); + if (mounted) { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "WOW error", + message: + "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", + ), + ); + } return; } diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart index 5b11876e8..8b56ae213 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart @@ -14,10 +14,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import '../../../app_config.dart'; +import '../../../models/exchange/aggregate_currency.dart'; import '../../../models/exchange/response_objects/estimate.dart'; import '../../../providers/exchange/exchange_form_state_provider.dart'; import '../../../providers/global/locale_provider.dart'; import '../../../services/exchange/exchange.dart'; +import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount_formatter.dart'; @@ -30,6 +32,9 @@ import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../widgets/animated_text.dart'; import '../../../widgets/conditional_parent.dart'; +import '../../../widgets/custom_buttons/blue_text_button.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/dialogs/basic_dialog.dart'; import '../../../widgets/exchange/trocador/trocador_kyc_info_button.dart'; import '../../../widgets/exchange/trocador/trocador_rating_type_enum.dart'; @@ -54,18 +59,26 @@ class _ExchangeOptionState extends ConsumerState { @override Widget build(BuildContext context) { - final sendCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.send)); - final receivingCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.receive)); + final sendCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.send), + ); + final receivingCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.receive), + ); final reversed = ref.watch(efReversedProvider); - final amount = reversed - ? ref.watch(efReceiveAmountProvider) - : ref.watch(efSendAmountProvider); + final amount = + reversed + ? ref.watch(efReceiveAmountProvider) + : ref.watch(efSendAmountProvider); final data = ref.watch(efEstimatesListProvider(widget.exchange.name)); final estimates = data?.item1.value; + final pair = + sendCurrency != null && receivingCurrency != null + ? (from: sendCurrency, to: receivingCurrency) + : null; + return AnimatedSize( duration: const Duration(milliseconds: 500), curve: Curves.easeInOutCubicEmphasized, @@ -76,6 +89,7 @@ class _ExchangeOptionState extends ConsumerState { return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: "", loadingString: true, ); @@ -94,10 +108,10 @@ class _ExchangeOptionState extends ConsumerState { int decimals; try { - decimals = AppConfig.getCryptoCurrencyForTicker( - receivingCurrency.ticker, - )! - .fractionDigits; + decimals = + AppConfig.getCryptoCurrencyForTicker( + receivingCurrency.ticker, + )!.fractionDigits; } catch (_) { decimals = 8; // some reasonable alternative } @@ -123,46 +137,50 @@ class _ExchangeOptionState extends ConsumerState { final String rateString; if (coin != null) { - rateString = "1 ${sendCurrency.ticker.toUpperCase()} " + rateString = + "1 ${sendCurrency.ticker.toUpperCase()} " "~ ${ref.watch(pAmountFormatter(coin)).format(rate)}"; } else { final formatter = AmountFormatter( unit: AmountUnit.normal, locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), coin: Bitcoin( CryptoCurrencyNetwork.main, ), // some sane default maxDecimals: 8, // some sane default ); - rateString = "1 ${sendCurrency.ticker.toUpperCase()} " + rateString = + "1 ${sendCurrency.ticker.toUpperCase()} " "~ ${formatter.format(rate, withUnitName: false)}" " ${receivingCurrency.ticker.toUpperCase()}"; } return ConditionalParent( condition: i > 0, - builder: (child) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - isDesktop - ? Container( - height: 1, - color: Theme.of(context) - .extension()! - .background, - ) - : const SizedBox( - height: 16, - ), - child, - ], - ), + builder: + (child) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + isDesktop + ? Container( + height: 1, + color: + Theme.of(context) + .extension()! + .background, + ) + : const SizedBox(height: 16), + child, + ], + ), child: _ProviderOption( key: Key(widget.exchange.name + e.exchangeProvider), exchange: widget.exchange, + pair: pair, estimate: e, rateString: rateString, kycRating: e.kycRating, @@ -189,16 +207,18 @@ class _ExchangeOptionState extends ConsumerState { message ??= "Amount too large"; } } else if (data?.item1.value == null) { - final rateType = ref.watch(efRateTypeProvider) == - ExchangeRateType.estimated - ? "estimated" - : "fixed"; + final rateType = + ref.watch(efRateTypeProvider) == + ExchangeRateType.estimated + ? "estimated" + : "fixed"; message ??= "Pair unavailable on $rateType rate flow"; } return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: message ?? "Failed to fetch rate", rateColor: Theme.of(context).extension()!.textError, @@ -211,6 +231,7 @@ class _ExchangeOptionState extends ConsumerState { return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: "n/a", ); } @@ -225,6 +246,7 @@ class _ProviderOption extends ConsumerStatefulWidget { super.key, required this.exchange, required this.estimate, + required this.pair, required this.rateString, this.kycRating, this.loadingString = false, @@ -233,6 +255,7 @@ class _ProviderOption extends ConsumerStatefulWidget { final Exchange exchange; final Estimate? estimate; + final ({AggregateCurrency from, AggregateCurrency to})? pair; final String rateString; final String? kycRating; final bool loadingString; @@ -246,12 +269,59 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { final isDesktop = Util.isDesktop; late final String _id; + final Set _warnings = {}; + + bool _warningLock = false; + void _showNoSparkWarning() async { + if (_warningLock) return; + _warningLock = true; + try { + await showDialog( + context: context, + builder: (context) { + return BasicDialog( + title: _warnings.map((e) => e.message).join(" and "), + message: _warnings.map((e) => e.messageDetail).join(" "), + canPopWithBackButton: true, + flex: true, + desktopHeight: 400, + rightButton: PrimaryButton( + label: "OK", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: Navigator.of(context).pop, + ), + ); + }, + ); + } finally { + _warningLock = false; + } + } @override void initState() { + super.initState(); _id = "${widget.exchange.name} (${widget.estimate?.exchangeProvider ?? widget.exchange.name})"; - super.initState(); + + if (widget.exchange.name == TrocadorExchange.exchangeName && + widget.pair != null) { + final from = widget.pair!.from.forExchange(widget.exchange.name); + final to = widget.pair!.to.forExchange(widget.exchange.name); + + if (from != null) { + final firoWarning = TrocadorExchange.checkFiro(from); + if (firoWarning != null) _warnings.add(firoWarning); + final ltcWarning = TrocadorExchange.checkLtc(from); + if (ltcWarning != null) _warnings.add(ltcWarning); + } + if (to != null) { + final firoWarning = TrocadorExchange.checkFiro(to); + if (firoWarning != null) _warnings.add(firoWarning); + final ltcWarning = TrocadorExchange.checkLtc(to); + if (ltcWarning != null) _warnings.add(ltcWarning); + } + } } @override @@ -265,10 +335,9 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { return ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: () { ref.read(efExchangeProvider.notifier).state = widget.exchange; @@ -289,127 +358,138 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { child: Padding( padding: EdgeInsets.only(top: isDesktop ? 20.0 : 15.0), child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, value: _id, groupValue: groupValue, onChanged: (_) { ref.read(efExchangeProvider.notifier).state = widget.exchange; ref - .read(efExchangeProviderNameProvider.notifier) - .state = - widget.estimate?.exchangeProvider ?? - widget.exchange.name; + .read(efExchangeProviderNameProvider.notifier) + .state = widget.estimate?.exchangeProvider ?? + widget.exchange.name; }, ), ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Padding( padding: const EdgeInsets.only(top: 5.0), child: SizedBox( width: isDesktop ? 32 : 24, height: isDesktop ? 32 : 24, - child: widget.estimate?.exchangeProviderLogo != null && - widget - .estimate! - .exchangeProviderLogo! - .isNotEmpty - ? ClipRRect( - borderRadius: BorderRadius.circular(5), - child: Image.network( - widget.estimate!.exchangeProviderLogo!, - loadingBuilder: ( - context, - child, - loadingProgress, - ) { - if (loadingProgress == null) { - return child; - } else { - return const Center( - child: - CircularProgressIndicator(), - ); - } - }, - errorBuilder: (context, error, stackTrace) { - return SvgPicture.asset( - Assets.exchange.getIconFor( - exchangeName: widget.exchange.name, + child: + widget.estimate?.exchangeProviderLogo != null && + widget + .estimate! + .exchangeProviderLogo! + .isNotEmpty + ? ClipRRect( + borderRadius: BorderRadius.circular(5), + child: Image.network( + widget.estimate!.exchangeProviderLogo!, + loadingBuilder: ( + context, + child, + loadingProgress, + ) { + if (loadingProgress == null) { + return child; + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + errorBuilder: (context, error, stackTrace) { + return SvgPicture.asset( + Assets.exchange.getIconFor( + exchangeName: widget.exchange.name, + ), + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, + ); + }, + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, + ), + ) + : SvgPicture.asset( + Assets.exchange.getIconFor( + exchangeName: widget.exchange.name, + ), + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, ), - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ); - }, - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ), - ) - : SvgPicture.asset( - Assets.exchange.getIconFor( - exchangeName: widget.exchange.name, - ), - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - widget.estimate?.exchangeProvider ?? - widget.exchange.name, - style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, + ConditionalParent( + condition: _warnings.isNotEmpty, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + child, + CustomTextButton( + text: _warnings.first.value, + onTap: () { + _showNoSparkWarning(); + }, + ), + ], + ), + child: Text( + widget.estimate?.exchangeProvider ?? + widget.exchange.name, + style: STextStyles.titleBold12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark2, + ), ), ), widget.loadingString ? AnimatedText( - stringsToLoopThrough: const [ - "Loading", - "Loading.", - "Loading..", - "Loading...", - ], - style: - STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ) + stringsToLoopThrough: const [ + "Loading", + "Loading.", + "Loading..", + "Loading...", + ], + style: STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ) : Text( - widget.rateString, - style: - STextStyles.itemSubtitle12(context).copyWith( - color: widget.rateColor ?? - Theme.of(context) - .extension()! - .textSubtitle1, - ), + widget.rateString, + style: STextStyles.itemSubtitle12(context).copyWith( + color: + widget.rateColor ?? + Theme.of( + context, + ).extension()!.textSubtitle1, ), + ), ], ), ), if (widget.kycRating != null) TrocadorKYCInfoButton( - kycType: TrocadorKYCType.fromString( - widget.kycRating!, - ), + kycType: TrocadorKYCType.fromString(widget.kycRating!), ), ], ), diff --git a/lib/pages/token_view/sub_widgets/token_summary.dart b/lib/pages/token_view/sub_widgets/token_summary.dart index 9bebfda49..2c09077cb 100644 --- a/lib/pages/token_view/sub_widgets/token_summary.dart +++ b/lib/pages/token_view/sub_widgets/token_summary.dart @@ -34,6 +34,7 @@ import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../wallets/isar/providers/eth/token_balance_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/rounded_container.dart'; import '../../buy_view/buy_in_wallet_view.dart'; @@ -121,7 +122,11 @@ class TokenSummary extends ConsumerWidget { ), ), const SizedBox(width: 10), - CoinTickerTag(walletId: walletId), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), + ), + ), ], ), if (price != null) const SizedBox(height: 6), @@ -325,24 +330,3 @@ class TokenOptionsButton extends StatelessWidget { ); } } - -class CoinTickerTag extends ConsumerWidget { - const CoinTickerTag({super.key, required this.walletId}); - - final String walletId; - - @override - Widget build(BuildContext context, WidgetRef ref) { - return RoundedContainer( - padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), - radiusMultiplier: 0.25, - color: Theme.of(context).extension()!.ethTagBG, - child: Text( - ref.watch(pWalletCoin(walletId)).ticker, - style: STextStyles.w600_12(context).copyWith( - color: Theme.of(context).extension()!.ethTagText, - ), - ), - ); - } -} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart index e30245c4d..577d4e322 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart @@ -12,13 +12,10 @@ import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; -import '../../../pages/token_view/sub_widgets/token_summary.dart'; import '../../../pages/token_view/sub_widgets/token_transaction_list_widget.dart'; import '../../../pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart'; -import 'sub_widgets/desktop_wallet_features.dart'; -import 'sub_widgets/desktop_wallet_summary.dart'; -import 'sub_widgets/my_wallet.dart'; import '../../../providers/providers.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../themes/stack_colors.dart'; @@ -26,20 +23,20 @@ import '../../../utilities/assets.dart'; import '../../../utilities/text_styles.dart'; import '../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../widgets/desktop/desktop_app_bar.dart'; import '../../../widgets/desktop/desktop_scaffold.dart'; import '../../../widgets/desktop/secondary_button.dart'; import '../../../widgets/icon_widgets/eth_token_icon.dart'; import '../../../widgets/rounded_white_container.dart'; +import 'sub_widgets/desktop_wallet_features.dart'; +import 'sub_widgets/desktop_wallet_summary.dart'; +import 'sub_widgets/my_wallet.dart'; /// [eventBus] should only be set during testing class DesktopTokenView extends ConsumerStatefulWidget { - const DesktopTokenView({ - super.key, - required this.walletId, - this.eventBus, - }); + const DesktopTokenView({super.key, required this.walletId, this.eventBus}); static const String routeName = "/desktopTokenView"; @@ -57,9 +54,10 @@ class _DesktopTokenViewState extends ConsumerState { @override void initState() { - initialSyncStatus = ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced; + initialSyncStatus = + ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced; super.initState(); } @@ -79,32 +77,26 @@ class _DesktopTokenViewState extends ConsumerState { flex: 3, child: Row( children: [ - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), SecondaryButton( - padding: const EdgeInsets.only( - left: 12, - right: 18, - ), + padding: const EdgeInsets.only(left: 12, right: 18), buttonHeight: ButtonHeight.s, label: ref.watch(pWalletName(widget.walletId)), icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () { ref.refresh(feeSheetSessionCacheProvider); Navigator.of(context).pop(); }, ), - const SizedBox( - width: 15, - ), + const SizedBox(width: 15), ], ), ), @@ -120,9 +112,7 @@ class _DesktopTokenViewState extends ConsumerState { ), size: 32, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( ref.watch( pCurrentTokenWallet.select( @@ -131,11 +121,11 @@ class _DesktopTokenViewState extends ConsumerState { ), style: STextStyles.desktopH3(context), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), CoinTickerTag( - walletId: widget.walletId, + ticker: ref.watch( + pWalletCoin(widget.walletId).select((s) => s.ticker), + ), ), ], ), @@ -159,30 +149,25 @@ class _DesktopTokenViewState extends ConsumerState { ), size: 40, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), DesktopWalletSummary( walletId: widget.walletId, isToken: true, - initialSyncStatus: ref - .watch(pWallets) - .getWallet(widget.walletId) - .refreshMutex - .isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, + initialSyncStatus: + ref + .watch(pWallets) + .getWallet(widget.walletId) + .refreshMutex + .isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, ), const Spacer(), - DesktopWalletFeatures( - walletId: widget.walletId, - ), + DesktopWalletFeatures(walletId: widget.walletId), ], ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Row( children: [ SizedBox( @@ -190,26 +175,27 @@ class _DesktopTokenViewState extends ConsumerState { child: Text( "My wallet", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Recent transactions", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, ), ), CustomTextButton( @@ -233,9 +219,7 @@ class _DesktopTokenViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 14, - ), + const SizedBox(height: 14), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -251,13 +235,9 @@ class _DesktopTokenViewState extends ConsumerState { ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( - child: TokenTransactionsList( - walletId: widget.walletId, - ), + child: TokenTransactionsList(walletId: widget.walletId), ), ], ), diff --git a/lib/services/exchange/trocador/trocador_exchange.dart b/lib/services/exchange/trocador/trocador_exchange.dart index 3bae214b6..ffb217a9f 100644 --- a/lib/services/exchange/trocador/trocador_exchange.dart +++ b/lib/services/exchange/trocador/trocador_exchange.dart @@ -36,6 +36,22 @@ class TrocadorExchange extends Exchange { static const onlySupportedNetwork = "Mainnet"; + static ProviderWarning? checkFiro(Currency currency) { + if (currency.ticker.toLowerCase() == "firo" && + currency.name.contains("No Spark")) { + return ProviderWarning.noSpark; + } + return null; + } + + static ProviderWarning? checkLtc(Currency currency) { + if (currency.ticker.toLowerCase() == "ltc" && + currency.name.contains("not MW")) { + return ProviderWarning.noMWEB; + } + return null; + } + @override Future> createTrade({ required String from, @@ -421,3 +437,25 @@ class TrocadorExchange extends Exchange { @override bool get supportsTor => true; } + +enum ProviderWarning { + noSpark("NO SPARK"), + noMWEB("NO MW"); + + final String value; + const ProviderWarning(this.value); + + String get message => switch (this) { + ProviderWarning.noSpark => "No Spark", + ProviderWarning.noMWEB => "No MimbleWimble", + }; + + String get messageDetail => switch (this) { + ProviderWarning.noSpark => + "Trocador does not support Firo transactions involving Spark addresses," + " including both sending to and receiving from them.", + ProviderWarning.noMWEB => + "Trocador does not support Litecoin transactions involving MWEB " + "(MimbleWimble Extension Block) addresses.", + }; +} diff --git a/lib/widgets/coin_ticker_tag.dart b/lib/widgets/coin_ticker_tag.dart new file mode 100644 index 000000000..f15e6548d --- /dev/null +++ b/lib/widgets/coin_ticker_tag.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import '../themes/stack_colors.dart'; +import '../utilities/text_styles.dart'; +import 'rounded_container.dart'; + +class CoinTickerTag extends StatelessWidget { + const CoinTickerTag({super.key, required this.ticker}); + + final String ticker; + + @override + Widget build(BuildContext context) { + return RoundedContainer( + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), + radiusMultiplier: 0.25, + color: Theme.of(context).extension()!.ethTagBG, + child: Text( + ticker, + style: STextStyles.w600_12(context).copyWith( + color: Theme.of(context).extension()!.ethTagText, + ), + ), + ); + } +} diff --git a/lib/widgets/wallet_info_row/wallet_info_row.dart b/lib/widgets/wallet_info_row/wallet_info_row.dart index 2cc35b7aa..381d0e0d5 100644 --- a/lib/widgets/wallet_info_row/wallet_info_row.dart +++ b/lib/widgets/wallet_info_row/wallet_info_row.dart @@ -12,12 +12,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; -import '../../pages/token_view/sub_widgets/token_summary.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; +import '../../wallets/isar/providers/wallet_info_provider.dart'; +import '../coin_ticker_tag.dart'; import '../custom_buttons/blue_text_button.dart'; import 'sub_widgets/wallet_info_row_balance.dart'; import 'sub_widgets/wallet_info_row_coin_icon.dart'; @@ -43,8 +43,9 @@ class WalletInfoRow extends ConsumerWidget { EthContract? contract; if (contractAddress != null) { contract = ref.watch( - mainDBProvider - .select((value) => value.getEthContractSync(contractAddress!)), + mainDBProvider.select( + (value) => value.getEthContractSync(contractAddress!), + ), ); } @@ -63,39 +64,40 @@ class WalletInfoRow extends ConsumerWidget { coin: wallet.info.coin, contractAddress: contractAddress, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), contract != null ? Row( - children: [ - Text( - contract.name, - style: - STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - const SizedBox( - width: 4, + children: [ + Text( + contract.name, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), - CoinTickerTag( - walletId: walletId, + ), + const SizedBox(width: 4), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), ), - ], - ) - : Text( - wallet.info.name, - style: STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, ), + ], + ) + : Text( + wallet.info.name, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), + ), ], ), ), @@ -129,36 +131,33 @@ class WalletInfoRow extends ConsumerWidget { coin: wallet.info.coin, contractAddress: contractAddress, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - contract != null - ? Row( - children: [ - Text( - contract.name, - style: STextStyles.titleBold12(context), - ), - const SizedBox( - width: 4, - ), - CoinTickerTag( - walletId: walletId, - ), - ], - ) - : Text( - wallet.info.name, + if (contract != null) + Row( + children: [ + Text( + contract.name, style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(width: 4), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), + ), + ), + ], + ) + else + Text( + wallet.info.name, + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 2), WalletInfoRowBalance( walletId: walletId, contractAddress: contractAddress, From 24c022aaab601ec6896d27b72651fc3cc06facb0 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:26:12 -0600 Subject: [PATCH 094/206] pass full currency into incomplete exchange model --- lib/models/exchange/incomplete_exchange.dart | 19 ++++--- lib/pages/exchange_view/exchange_form.dart | 23 ++------ .../exchange_step_views/step_3_view.dart | 57 ++++++++++--------- .../exchange_steps/step_scaffold.dart | 6 +- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/lib/models/exchange/incomplete_exchange.dart b/lib/models/exchange/incomplete_exchange.dart index 3608b8b05..86441bc90 100644 --- a/lib/models/exchange/incomplete_exchange.dart +++ b/lib/models/exchange/incomplete_exchange.dart @@ -12,14 +12,16 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import '../../utilities/enums/exchange_rate_type_enum.dart'; +import '../isar/exchange_cache/currency.dart'; import 'response_objects/estimate.dart'; import 'response_objects/trade.dart'; class IncompleteExchangeModel extends ChangeNotifier { - final String sendTicker; - final String? sendNetwork; - final String receiveTicker; - final String? receiveNetwork; + final Currency sendCurrency; + final Currency receiveCurrency; + + String get sendTicker => sendCurrency.ticker; + String get receiveTicker => receiveCurrency.ticker; final String rateInfo; @@ -76,10 +78,8 @@ class IncompleteExchangeModel extends ChangeNotifier { } IncompleteExchangeModel({ - required this.sendTicker, - required this.sendNetwork, - required this.receiveTicker, - required this.receiveNetwork, + required this.sendCurrency, + required this.receiveCurrency, required this.rateInfo, required this.sendAmount, required this.receiveAmount, @@ -87,5 +87,6 @@ class IncompleteExchangeModel extends ChangeNotifier { required this.reversed, required this.walletInitiated, Estimate? estimate, - }) : _estimate = estimate; + }) : _estimate = estimate, + assert(sendCurrency.exchangeName == receiveCurrency.exchangeName); } diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 488a74674..93e15c4bb 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -420,20 +420,11 @@ class _ExchangeFormState extends ConsumerState { } final rateType = ref.read(efRateTypeProvider); - final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; - final fromNetwork = ref - .read(efCurrencyPairProvider) - .send - ?.networkFor(exchangeName); - final toTicker = ref.read(efCurrencyPairProvider).receive?.ticker ?? ""; - final toNetwork = ref - .read(efCurrencyPairProvider) - .receive - ?.networkFor(exchangeName); final estimate = ref.read(efEstimateProvider)!; final sendAmount = ref.read(efSendAmountProvider)!; - if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") { + if (rateType == ExchangeRateType.fixed && + toCurrency.ticker.toUpperCase() == "WOW") { if (mounted) { await showDialog( context: context, @@ -461,7 +452,7 @@ class _ExchangeFormState extends ConsumerState { switch (rateType) { case ExchangeRateType.estimated: rate = - "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; + "1 ${fromCurrency.ticker.toUpperCase()} ~${(amountToReceive / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toCurrency.ticker.toUpperCase()}"; break; case ExchangeRateType.fixed: bool? shouldCancel; @@ -568,15 +559,13 @@ class _ExchangeFormState extends ConsumerState { return; } rate = - "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(scaleOnInfinitePrecision: 12).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; + "1 ${fromCurrency.ticker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(scaleOnInfinitePrecision: 12).toStringAsFixed(8)} ${toCurrency.ticker.toUpperCase()}"; break; } final model = IncompleteExchangeModel( - sendTicker: fromTicker.toUpperCase(), - sendNetwork: fromNetwork, - receiveTicker: toTicker.toUpperCase(), - receiveNetwork: toNetwork, + sendCurrency: fromCurrency, + receiveCurrency: toCurrency, rateInfo: rate, sendAmount: amountToSend, receiveAmount: amountToReceive, diff --git a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart index 46457ae2a..4f0b352c3 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart @@ -74,7 +74,7 @@ class _Step3ViewState extends ConsumerState { FocusScope.of(context).unfocus(); await Future.delayed(const Duration(milliseconds: 75)); } - if (mounted) { + if (context.mounted) { Navigator.of(context).pop(); } }, @@ -243,32 +243,33 @@ class _Step3ViewState extends ConsumerState { ), ); - final ExchangeResponse response = - await ref - .read(efExchangeProvider) - .createTrade( - from: model.sendTicker, - fromNetwork: model.sendNetwork, - to: model.receiveTicker, - toNetwork: model.receiveNetwork, - fixedRate: - model.rateType != - ExchangeRateType.estimated, - amount: - model.reversed - ? model.receiveAmount - : model.sendAmount, - addressTo: - model.recipientAddress!, - extraId: null, - addressRefund: - supportsRefund - ? model.refundAddress! - : "", - refundExtraId: "", - estimate: model.estimate, - reversed: model.reversed, - ); + final ExchangeResponse + response = await ref + .read(efExchangeProvider) + .createTrade( + from: model.sendTicker, + fromNetwork: + model.sendCurrency.network, + to: model.receiveTicker, + toNetwork: + model.receiveCurrency.network, + fixedRate: + model.rateType != + ExchangeRateType.estimated, + amount: + model.reversed + ? model.receiveAmount + : model.sendAmount, + addressTo: model.recipientAddress!, + extraId: null, + addressRefund: + supportsRefund + ? model.refundAddress! + : "", + refundExtraId: "", + estimate: model.estimate, + reversed: model.reversed, + ); if (response.value == null) { if (context.mounted) { @@ -339,7 +340,7 @@ class _Step3ViewState extends ConsumerState { ), ); - if (mounted) { + if (context.mounted) { unawaited( Navigator.of(context).pushNamed( Step4View.routeName, diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart index 3fe2b20d7..606d9fa68 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart @@ -96,9 +96,11 @@ class _StepScaffoldState extends ConsumerState { .read(efExchangeProvider) .createTrade( from: ref.read(desktopExchangeModelProvider)!.sendTicker, - fromNetwork: ref.read(desktopExchangeModelProvider)!.sendNetwork, + fromNetwork: + ref.read(desktopExchangeModelProvider)!.sendCurrency.network, to: ref.read(desktopExchangeModelProvider)!.receiveTicker, - toNetwork: ref.read(desktopExchangeModelProvider)!.receiveNetwork, + toNetwork: + ref.read(desktopExchangeModelProvider)!.receiveCurrency.network, fixedRate: ref.read(desktopExchangeModelProvider)!.rateType != ExchangeRateType.estimated, From daf112e0f3527b4072999091a2c5de608228ac8d Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:58:14 -0600 Subject: [PATCH 095/206] hack in prevention of spark sends to trocador swaps --- lib/app_config.dart | 8 +- lib/pages/exchange_view/send_from_view.dart | 132 ++++++++++---------- 2 files changed, 74 insertions(+), 66 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 96b07b2c9..09eeae26f 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -72,7 +72,13 @@ abstract class AppConfig { /// Fuzzy logic. Use with caution!! @Deprecated("dangerous") static CryptoCurrency getCryptoCurrencyByPrettyName(final String prettyName) { - final name = prettyName.replaceAll(" ", "").toLowerCase(); + // trocador hack + const hackSplitter = " (Mainnet"; + final name = + prettyName.contains(hackSplitter) + ? prettyName.split(hackSplitter).first.toLowerCase() + : prettyName.replaceAll(" ", "").toLowerCase(); + try { return coins.firstWhere( (e) => e.identifier.toLowerCase() == name || e.prettyName == prettyName, diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index bad0a3aac..8f397e79e 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -20,6 +20,7 @@ import '../../models/exchange/response_objects/trade.dart'; import '../../pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; +import '../../services/exchange/trocador/trocador_exchange.dart'; import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; @@ -406,12 +407,6 @@ class _SendFromCardState extends ConsumerState { @override Widget build(BuildContext context) { - final wallet = ref.watch(pWallets).getWallet(walletId); - - final locale = ref.watch( - localeServiceChangeNotifierProvider.select((value) => value.locale), - ); - final coin = ref.watch(pWalletCoin(walletId)); final isFiro = coin is Firo; @@ -430,70 +425,77 @@ class _SendFromCardState extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - MaterialButton( - splashColor: - Theme.of(context).extension()!.highlight, - key: Key("walletsSheetItemButtonFiroPrivateKey_$walletId"), - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (!trade.exchangeName.startsWith( + TrocadorExchange.exchangeName, + )) + MaterialButton( + splashColor: + Theme.of(context).extension()!.highlight, + key: Key( + "walletsSheetItemButtonFiroPrivateKey_$walletId", ), - ), - onPressed: () async { - if (mounted) { - unawaited(_send(shouldSendPublicFiroFunds: false)); - } - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - top: 6, - left: 16, - right: 16, - bottom: 6, + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Use private balance", - style: STextStyles.itemSubtitle(context), - ), - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - ref - .watch( - pWalletBalanceTertiary(walletId), - ) - .spendable, - ), - style: STextStyles.itemSubtitle(context), - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronRight, - height: 14, - width: 7, - color: - Theme.of( - context, - ).extension()!.infoItemLabel, - ), - ], + ), + onPressed: () async { + if (mounted) { + unawaited(_send(shouldSendPublicFiroFunds: false)); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + top: 6, + left: 16, + right: 16, + bottom: 6, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Use private balance", + style: STextStyles.itemSubtitle(context), + ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable, + ), + style: STextStyles.itemSubtitle(context), + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronRight, + height: 14, + width: 7, + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ], + ), ), ), ), - ), MaterialButton( splashColor: Theme.of(context).extension()!.highlight, From 941b5531e145d83d4b3cfba8edc0ba50d86d9277 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 18:22:11 -0600 Subject: [PATCH 096/206] Fix factorn wallet overrides --- lib/wallets/wallet/impl/fact0rn_wallet.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/wallets/wallet/impl/fact0rn_wallet.dart b/lib/wallets/wallet/impl/fact0rn_wallet.dart index 14c8106a9..14a9d4be8 100644 --- a/lib/wallets/wallet/impl/fact0rn_wallet.dart +++ b/lib/wallets/wallet/impl/fact0rn_wallet.dart @@ -305,18 +305,22 @@ class Fact0rnWallet // Typical SegWit estimation @override - Amount roughFeeEstimate(int inputCount, int outputCount, int feeRatePerKB) { + Amount roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * - (feeRatePerKB / 1000).ceil(), + (feeRatePerKB.toInt() / 1000).ceil(), ), fractionDigits: cryptoCurrency.fractionDigits, ); } @override - int estimateTxFee({required int vSize, required int feeRatePerKB}) { - return vSize * (feeRatePerKB / 1000).ceil(); + int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { + return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } } From b5d2be8d35717fc3675d7d04faf400ca6b65caa7 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 18:47:49 -0600 Subject: [PATCH 097/206] WIP: mobile camera permissions qr scanning clean up --- .../restore/restore_frost_ms_wallet_view.dart | 29 +- .../restore_view_only_wallet_view.dart | 4 +- .../restore_wallet_view.dart | 33 +- .../subviews/add_address_book_entry_view.dart | 7 +- .../add_new_contact_address_view.dart | 12 +- .../subviews/edit_contact_address_view.dart | 12 +- .../new_contact_address_entry_form.dart | 249 ++--- lib/pages/buy_view/buy_form.dart | 972 +++++++++--------- .../exchange_step_views/step_2_view.dart | 58 +- .../sub_widgets/transfer_option_widget.dart | 229 ++--- .../sub_widgets/update_option_widget.dart | 94 +- .../paynym/add_new_paynym_follow_view.dart | 319 +++--- lib/pages/send_view/frost_ms/recipient.dart | 222 ++-- lib/pages/send_view/send_view.dart | 34 +- lib/pages/send_view/token_send_view.dart | 33 +- .../add_edit_node_view.dart | 19 +- .../paynym/desktop_paynym_send_dialog.dart | 4 +- .../wallet_view/sub_widgets/desktop_send.dart | 7 +- .../sub_widgets/desktop_token_send.dart | 8 +- .../global/barcode_scanner_provider.dart | 7 + lib/providers/global/clipboard_provider.dart | 7 + lib/providers/providers.dart | 2 + lib/utilities/barcode_scanner_interface.dart | 58 ++ lib/widgets/textfields/frost_step_field.dart | 145 +-- 24 files changed, 1333 insertions(+), 1231 deletions(-) create mode 100644 lib/providers/global/barcode_scanner_provider.dart create mode 100644 lib/providers/global/clipboard_provider.dart diff --git a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart index 64deee9be..9b388a5a3 100644 --- a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -14,6 +13,7 @@ import '../../../../providers/providers.dart'; import '../../../../services/frost.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; +import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/logger.dart'; import '../../../../utilities/show_loading.dart'; @@ -212,7 +212,7 @@ class _RestoreFrostMsWalletViewState await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await BarcodeScanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); configFieldController.text = qrResult.rawContent; @@ -238,11 +238,26 @@ class _RestoreFrostMsWalletViewState } } } on PlatformException catch (e, s) { - Logging.instance.w( - "Failed to get camera permissions while trying to scan qr code: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions while trying to scan qr code: ", + error: e, + stackTrace: s, + ); + } } } diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart index 75bda4577..2ad57cf02 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart @@ -15,7 +15,6 @@ import '../../../providers/global/secure_store_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/constants.dart'; import '../../../utilities/text_styles.dart'; @@ -50,7 +49,7 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { required this.coin, required this.restoreBlockHeight, this.enableLelantusScanning = false, - this.barcodeScanner = const BarcodeScannerWrapper(), + this.clipboard = const ClipboardWrapper(), }); @@ -60,7 +59,6 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { final CryptoCurrency coin; final int restoreBlockHeight; final bool enableLelantusScanning; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 90ef055e2..22df0c440 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -77,7 +77,7 @@ class RestoreWalletView extends ConsumerStatefulWidget { required this.mnemonicPassphrase, required this.restoreBlockHeight, this.enableLelantusScanning = false, - this.barcodeScanner = const BarcodeScannerWrapper(), + this.clipboard = const ClipboardWrapper(), }); @@ -90,7 +90,6 @@ class RestoreWalletView extends ConsumerStatefulWidget { final int restoreBlockHeight; final bool enableLelantusScanning; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override @@ -110,8 +109,6 @@ class _RestoreWalletViewState extends ConsumerState { final List _inputStatuses = []; // final List _focusNodes = []; - late final BarcodeScannerInterface scanner; - late final TextSelectionControls textSelectionControls; bool _hideSeedWords = false; @@ -161,7 +158,6 @@ class _RestoreWalletViewState extends ConsumerState { ? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste) : CustomMaterialTextSelectionControls(onPaste: onControlsPaste); - scanner = widget.barcodeScanner; for (int i = 0; i < _seedWordCount; i++) { _controllers.add(TextEditingController()); _inputStatuses.add(FormInputStatus.empty); @@ -601,7 +597,7 @@ class _RestoreWalletViewState extends ConsumerState { Future scanMnemonicQr() async { try { - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); final results = AddressUtils.decodeQRSeedData(qrResult.rawContent); @@ -618,11 +614,26 @@ class _RestoreWalletViewState extends ConsumerState { } } on PlatformException catch (e, s) { // likely failed to get camera permissions - Logging.instance.e( - "Restore wallet qr scan failed: $e", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.e( + "Restore wallet qr scan failed: $e", + error: e, + stackTrace: s, + ); + } } } diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart index 22ecb4407..84e9be9fa 100644 --- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart +++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart @@ -21,7 +21,6 @@ import '../../../providers/ui/address_book_providers/contact_name_is_not_empty_s import '../../../providers/ui/address_book_providers/valid_contact_state_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/constants.dart'; import '../../../utilities/text_styles.dart'; @@ -43,13 +42,11 @@ import 'new_contact_address_entry_form.dart'; class AddAddressBookEntryView extends ConsumerStatefulWidget { const AddAddressBookEntryView({ super.key, - this.barcodeScanner = const BarcodeScannerWrapper(), this.clipboard = const ClipboardWrapper(), }); static const String routeName = "/addAddressBookEntry"; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override @@ -63,7 +60,6 @@ class _AddAddressBookEntryViewState late final FocusNode nameFocusNode; late final ScrollController scrollController; - late final BarcodeScannerInterface scanner; late final ClipboardInterface clipboard; Emoji? _selectedEmoji; @@ -72,7 +68,7 @@ class _AddAddressBookEntryViewState @override initState() { ref.refresh(addressEntryDataProviderFamilyRefresher); - scanner = widget.barcodeScanner; + clipboard = widget.clipboard; nameController = TextEditingController(); @@ -114,7 +110,6 @@ class _AddAddressBookEntryViewState key: Key("contactAddressEntryForm_$id"), id: ref.read(addressEntryDataProvider(id)).id, clipboard: clipboard, - barcodeScanner: scanner, ), ); setState(() {}); diff --git a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart index 2954c4d3f..374752024 100644 --- a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart @@ -18,7 +18,6 @@ import '../../../providers/ui/address_book_providers/address_entry_data_provider import '../../../providers/ui/address_book_providers/valid_contact_state_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -33,7 +32,6 @@ class AddNewContactAddressView extends ConsumerStatefulWidget { const AddNewContactAddressView({ super.key, required this.contactId, - this.barcodeScanner = const BarcodeScannerWrapper(), this.clipboard = const ClipboardWrapper(), }); @@ -41,7 +39,6 @@ class AddNewContactAddressView extends ConsumerStatefulWidget { final String contactId; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override @@ -53,13 +50,12 @@ class _AddNewContactAddressViewState extends ConsumerState { late final String contactId; - late final BarcodeScannerInterface barcodeScanner; late final ClipboardInterface clipboard; @override void initState() { contactId = widget.contactId; - barcodeScanner = widget.barcodeScanner; + clipboard = widget.clipboard; super.initState(); @@ -173,11 +169,7 @@ class _AddNewContactAddressViewState ], ), const SizedBox(height: 16), - NewContactAddressEntryForm( - id: 0, - barcodeScanner: barcodeScanner, - clipboard: clipboard, - ), + NewContactAddressEntryForm(id: 0, clipboard: clipboard), const SizedBox(height: 16), const Spacer(), Row( diff --git a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart index 774fac6be..652ff94e3 100644 --- a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart @@ -18,7 +18,6 @@ import '../../../providers/ui/address_book_providers/address_entry_data_provider import '../../../providers/ui/address_book_providers/valid_contact_state_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -34,7 +33,7 @@ class EditContactAddressView extends ConsumerStatefulWidget { super.key, required this.contactId, required this.addressEntry, - this.barcodeScanner = const BarcodeScannerWrapper(), + this.clipboard = const ClipboardWrapper(), }); @@ -43,7 +42,6 @@ class EditContactAddressView extends ConsumerStatefulWidget { final String contactId; final ContactAddressEntry addressEntry; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override @@ -56,7 +54,6 @@ class _EditContactAddressViewState late final String contactId; late final ContactAddressEntry addressEntry; - late final BarcodeScannerInterface barcodeScanner; late final ClipboardInterface clipboard; Future save(ContactEntry contact) async { @@ -97,7 +94,6 @@ class _EditContactAddressViewState void initState() { contactId = widget.contactId; addressEntry = widget.addressEntry; - barcodeScanner = widget.barcodeScanner; clipboard = widget.clipboard; super.initState(); @@ -211,11 +207,7 @@ class _EditContactAddressViewState ], ), const SizedBox(height: 16), - NewContactAddressEntryForm( - id: 0, - barcodeScanner: barcodeScanner, - clipboard: clipboard, - ), + NewContactAddressEntryForm(id: 0, clipboard: clipboard), const SizedBox(height: 24), ConditionalParent( condition: isDesktop, diff --git a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart index f1f399f13..818393aec 100644 --- a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart +++ b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart @@ -42,13 +42,11 @@ class NewContactAddressEntryForm extends ConsumerStatefulWidget { const NewContactAddressEntryForm({ super.key, required this.id, - required this.barcodeScanner, required this.clipboard, }); final int id; - final BarcodeScannerInterface barcodeScanner; final ClipboardInterface clipboard; @override @@ -72,7 +70,7 @@ class _NewContactAddressEntryFormState // .read(shouldShowLockscreenOnResumeStateProvider // .state) // .state = false; - final qrResult = await widget.barcodeScanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); // Future.delayed( // const Duration(seconds: 2), @@ -102,9 +100,10 @@ class _NewContactAddressEntryFormState // now check for non standard encoded basic address } else if (ref.read(addressEntryDataProvider(widget.id)).coin != null) { - if (ref.read(addressEntryDataProvider(widget.id)).coin!.validateAddress( - qrResult.rawContent, - )) { + if (ref + .read(addressEntryDataProvider(widget.id)) + .coin! + .validateAddress(qrResult.rawContent)) { addressController.text = qrResult.rawContent; ref.read(addressEntryDataProvider(widget.id)).address = qrResult.rawContent; @@ -115,16 +114,39 @@ class _NewContactAddressEntryFormState // .read(shouldShowLockscreenOnResumeStateProvider // .state) // .state = true; - Logging.instance.w("Failed to get camera permissions to scan address qr code: ", error: e, stackTrace: s); + + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions to scan address qr code: ", + error: e, + stackTrace: s, + ); + } } } @override void initState() { - addressLabelController = TextEditingController() - ..text = ref.read(addressEntryDataProvider(widget.id)).addressLabel ?? ""; - addressController = TextEditingController() - ..text = ref.read(addressEntryDataProvider(widget.id)).address ?? ""; + addressLabelController = + TextEditingController() + ..text = + ref.read(addressEntryDataProvider(widget.id)).addressLabel ?? ""; + addressController = + TextEditingController() + ..text = ref.read(addressEntryDataProvider(widget.id)).address ?? ""; addressLabelFocusNode = FocusNode(); addressFocusNode = FocusNode(); coins = [...AppConfig.coins]; @@ -153,18 +175,17 @@ class _NewContactAddressEntryFormState final isDesktop = Util.isDesktop; if (isDesktop) { coins = [...AppConfig.coins]; - coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + coins.removeWhere((e) => e is Firo && e.network.isTestNet); final showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins; if (showTestNet) { coins = coins.toList(); } else { - coins = coins - .where((e) => e.network != CryptoCurrencyNetwork.test) - .toList(); + coins = + coins + .where((e) => e.network != CryptoCurrencyNetwork.test) + .toList(); } } @@ -181,24 +202,23 @@ class _NewContactAddressEntryFormState offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 4, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), ), isExpanded: true, value: ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.coin), + addressEntryDataProvider( + widget.id, + ).select((value) => value.coin), ), onChanged: (value) { if (value is CryptoCurrency) { @@ -222,23 +242,20 @@ class _NewContactAddressEntryFormState child: Row( children: [ SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), height: 24, width: 24, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( coin.prettyName, - style: - STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ], @@ -285,54 +302,54 @@ class _NewContactAddressEntryFormState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.coin), + addressEntryDataProvider( + widget.id, + ).select((value) => value.coin), ) == null ? Text( - "Select cryptocurrency", - style: STextStyles.fieldLabel(context), - ) + "Select cryptocurrency", + style: STextStyles.fieldLabel(context), + ) : Row( - children: [ - SvgPicture.file( - File( - ref.watch( - coinIconProvider( - ref.watch( - addressEntryDataProvider(widget.id) - .select( - (value) => value.coin, - ), - )!, - ), + children: [ + SvgPicture.file( + File( + ref.watch( + coinIconProvider( + ref.watch( + addressEntryDataProvider( + widget.id, + ).select((value) => value.coin), + )!, ), ), - height: 20, - width: 20, - ), - const SizedBox( - width: 12, ), - Text( - ref - .watch( - addressEntryDataProvider(widget.id) - .select((value) => value.coin), - )! - .prettyName, - style: STextStyles.itemSubtitle12(context), - ), - ], - ), + height: 20, + width: 20, + ), + const SizedBox(width: 12), + Text( + ref + .watch( + addressEntryDataProvider( + widget.id, + ).select((value) => value.coin), + )! + .prettyName, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), if (!isDesktop) SvgPicture.asset( Assets.svg.chevronDown, width: 8, height: 4, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), ], ), @@ -341,10 +358,7 @@ class _NewContactAddressEntryFormState ), ), ), - if (!AppConfig.isSingleCoinApp) - const SizedBox( - height: 8, - ), + if (!AppConfig.isSingleCoinApp) const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -361,25 +375,26 @@ class _NewContactAddressEntryFormState context, ).copyWith( labelStyle: isDesktop ? STextStyles.fieldLabel(context) : null, - suffixIcon: addressLabelController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - addressLabelController.text = ""; - }); - }, - ), - ], + suffixIcon: + addressLabelController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + addressLabelController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), onChanged: (newValue) { ref.read(addressEntryDataProvider(widget.id)).addressLabel = @@ -388,9 +403,7 @@ class _NewContactAddressEntryFormState }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -410,8 +423,9 @@ class _NewContactAddressEntryFormState child: Row( children: [ if (ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.address), + addressEntryDataProvider( + widget.id, + ).select((value) => value.address), ) != null) TextFieldIconButton( @@ -425,8 +439,9 @@ class _NewContactAddressEntryFormState child: const XIcon(), ), if (ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.address), + addressEntryDataProvider( + widget.id, + ).select((value) => value.address), ) == null) TextFieldIconButton( @@ -438,8 +453,10 @@ class _NewContactAddressEntryFormState if (data?.text != null && data!.text!.isNotEmpty) { String content = data.text!.trim(); if (content.contains("\n")) { - content = - content.substring(0, content.indexOf("\n")); + content = content.substring( + 0, + content.indexOf("\n"), + ); } addressController.text = content; ref @@ -451,8 +468,9 @@ class _NewContactAddressEntryFormState ), if (!Util.isDesktop && ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.address), + addressEntryDataProvider( + widget.id, + ).select((value) => value.address), ) == null) TextFieldIconButton( @@ -460,9 +478,7 @@ class _NewContactAddressEntryFormState onTap: _onQrTapped, child: const QrCodeIcon(), ), - const SizedBox( - width: 8, - ), + const SizedBox(width: 8), ], ), ), @@ -485,21 +501,18 @@ class _NewContactAddressEntryFormState ), ), if (!ref.watch( - addressEntryDataProvider(widget.id) - .select((value) => value.isValidAddress), + addressEntryDataProvider( + widget.id, + ).select((value) => value.isValidAddress), ) && addressController.text.isNotEmpty) Row( children: [ - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( "Invalid address", textAlign: TextAlign.left, diff --git a/lib/pages/buy_view/buy_form.dart b/lib/pages/buy_view/buy_form.dart index d68a02e4f..d62a2bdc4 100644 --- a/lib/pages/buy_view/buy_form.dart +++ b/lib/pages/buy_view/buy_form.dart @@ -64,13 +64,11 @@ class BuyForm extends ConsumerStatefulWidget { this.coin, this.tokenContract, this.clipboard = const ClipboardWrapper(), - this.scanner = const BarcodeScannerWrapper(), }); final CryptoCurrency? coin; final ClipboardInterface clipboard; - final BarcodeScannerInterface scanner; final EthContract? tokenContract; @override @@ -81,7 +79,6 @@ class _BuyFormState extends ConsumerState { late final CryptoCurrency? coin; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late final TextEditingController _receiveAddressController; late final TextEditingController _buyAmountController; @@ -162,13 +159,14 @@ class _BuyFormState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => WillPopScope( - child: const CustomLoadingOverlay( - message: "Loading currency data", - eventBus: null, - ), - onWillPop: () async => shouldPop, - ), + builder: + (context) => WillPopScope( + child: const CustomLoadingOverlay( + message: "Loading currency data", + eventBus: null, + ), + onWillPop: () async => shouldPop, + ), ), ); await _loadSimplexCryptos(); @@ -202,66 +200,62 @@ class _BuyFormState extends ConsumerState { _fiatFocusNode.unfocus(); _cryptoFocusNode.unfocus(); - final result = isDesktop - ? await showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxHeight: 700, - maxWidth: 580, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( + final result = + isDesktop + ? await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxHeight: 700, + maxWidth: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Choose a crypto to buy", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( padding: const EdgeInsets.only( left: 32, + right: 32, + bottom: 32, ), - child: Text( - "Choose a crypto to buy", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Row( - children: [ - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - borderColor: Theme.of(context) - .extension()! - .background, - child: CryptoSelectionView( - coins: coins, + child: Row( + children: [ + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: CryptoSelectionView(coins: coins), ), ), - ), - ], + ], + ), ), ), - ), - ], - ), - ); - }, - ) - : await Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => CryptoSelectionView( - coins: coins, + ], + ), + ); + }, + ) + : await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => CryptoSelectionView(coins: coins), ), - ), - ); + ); if (mounted && result is Crypto) { onSelected(result); @@ -274,13 +268,14 @@ class _BuyFormState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => WillPopScope( - child: const CustomLoadingOverlay( - message: "Loading currency data", - eventBus: null, - ), - onWillPop: () async => shouldPop, - ), + builder: + (context) => WillPopScope( + child: const CustomLoadingOverlay( + message: "Loading currency data", + eventBus: null, + ), + onWillPop: () async => shouldPop, + ), ), ); await _loadSimplexFiats(); @@ -334,66 +329,62 @@ class _BuyFormState extends ConsumerState { _fiatFocusNode.unfocus(); _cryptoFocusNode.unfocus(); - final result = isDesktop - ? await showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxHeight: 700, - maxWidth: 580, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( + final result = + isDesktop + ? await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxHeight: 700, + maxWidth: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Choose a fiat with which to pay", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( padding: const EdgeInsets.only( left: 32, + right: 32, + bottom: 32, ), - child: Text( - "Choose a fiat with which to pay", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Row( - children: [ - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - borderColor: Theme.of(context) - .extension()! - .background, - child: FiatSelectionView( - fiats: fiats, + child: Row( + children: [ + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: FiatSelectionView(fiats: fiats), ), ), - ), - ], + ], + ), ), ), - ), - ], - ), - ); - }, - ) - : await Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FiatSelectionView( - fiats: fiats, + ], + ), + ); + }, + ) + : await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FiatSelectionView(fiats: fiats), ), - ), - ); + ); if (mounted && result is Fiat) { onSelected(result); @@ -411,25 +402,28 @@ class _BuyFormState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => WillPopScope( - child: const CustomLoadingOverlay( - message: "Loading quote data", - eventBus: null, - ), - onWillPop: () async => shouldPop, - ), + builder: + (context) => WillPopScope( + child: const CustomLoadingOverlay( + message: "Loading quote data", + eventBus: null, + ), + onWillPop: () async => shouldPop, + ), ), ); quote = SimplexQuote( crypto: selectedCrypto!, fiat: selectedFiat!, - youPayFiatPrice: buyWithFiat - ? Decimal.parse(_buyAmountController.text) - : Decimal.parse("100"), // dummy value - youReceiveCryptoAmount: buyWithFiat - ? Decimal.parse("0.000420282") // dummy value - : Decimal.parse(_buyAmountController.text), // Ternary for this + youPayFiatPrice: + buyWithFiat + ? Decimal.parse(_buyAmountController.text) + : Decimal.parse("100"), // dummy value + youReceiveCryptoAmount: + buyWithFiat + ? Decimal.parse("0.000420282") // dummy value + : Decimal.parse(_buyAmountController.text), // Ternary for this id: "id", // anything; we get an ID back receivingAddress: _receiveAddressController.text, buyWithFiat: buyWithFiat, @@ -469,16 +463,12 @@ class _BuyFormState extends ConsumerState { "Simplex API unresponsive", style: STextStyles.desktopH3(context), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Text( "Simplex API unresponsive, please try again later", style: STextStyles.smallMed14(context), ), - const SizedBox( - height: 56, - ), + const SizedBox(height: 56), Row( children: [ const Spacer(), @@ -506,9 +496,10 @@ class _BuyFormState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -558,16 +549,12 @@ class _BuyFormState extends ConsumerState { "Simplex API error", style: STextStyles.desktopH3(context), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Text( quoteResponse.exception!.errorMessage, style: STextStyles.smallMed14(context), ), - const SizedBox( - height: 56, - ), + const SizedBox(height: 56), Row( children: [ const Spacer(), @@ -596,9 +583,10 @@ class _BuyFormState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -622,11 +610,9 @@ class _BuyFormState extends ConsumerState { } else { Logging.instance.d("_loadQuote: $response"); return BuyResponse( - exception: response.exception ?? - BuyException( - response.toString(), - BuyExceptionType.generic, - ), + exception: + response.exception ?? + BuyException(response.toString(), BuyExceptionType.generic), ); } } @@ -638,66 +624,62 @@ class _BuyFormState extends ConsumerState { _fiatFocusNode.unfocus(); _cryptoFocusNode.unfocus(); - final result = isDesktop - ? await showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxHeight: 700, - maxWidth: 580, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( + final result = + isDesktop + ? await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxHeight: 700, + maxWidth: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Preview quote", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( padding: const EdgeInsets.only( left: 32, + right: 32, + bottom: 32, ), - child: Text( - "Preview quote", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: Row( - children: [ - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - borderColor: Theme.of(context) - .extension()! - .background, - child: BuyQuotePreviewView( - quote: quote, + child: Row( + children: [ + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + borderColor: + Theme.of( + context, + ).extension()!.background, + child: BuyQuotePreviewView(quote: quote), ), ), - ), - ], + ], + ), ), ), - ), - ], - ), - ); - }, - ) - : await Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => BuyQuotePreviewView( - quote: quote, + ], + ), + ); + }, + ) + : await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => BuyQuotePreviewView(quote: quote), ), - ), - ); + ); if (mounted && result is SimplexQuote) { onSelected(result); @@ -708,12 +690,10 @@ class _BuyFormState extends ConsumerState { try { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); + await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); @@ -743,13 +723,26 @@ class _BuyFormState extends ConsumerState { }); } } on PlatformException catch (e, s) { - // here we ignore the exception caused by not giving permission - // to use the camera to scan a qr code - Logging.instance.e( - "Failed to get camera permissions while trying to scan qr code in SendView: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.e( + "Failed to get camera permissions while trying to scan qr code in $runtimeType: ", + error: e, + stackTrace: s, + ); + } } } @@ -759,7 +752,6 @@ class _BuyFormState extends ConsumerState { _buyAmountController = TextEditingController(); clipboard = widget.clipboard; - scanner = widget.scanner; coins = ref.read(simplexProvider).supportedCryptos; fiats = ref.read(simplexProvider).supportedFiats; @@ -776,8 +768,10 @@ class _BuyFormState extends ConsumerState { ); // TODO enum this or something // TODO set defaults better; should probably explicitly enumerate the coins & fiats used and pull the specific ones we need rather than generating them as defaults here - selectedFiat = - Fiat.fromJson({'ticker': 'USD', 'name': 'United States Dollar'}); + selectedFiat = Fiat.fromJson({ + 'ticker': 'USD', + 'name': 'United States Dollar', + }); selectedCrypto = Crypto.fromJson({ 'ticker': widget.coin?.ticker ?? 'BTC', 'name': widget.coin?.prettyName ?? 'Bitcoin', @@ -815,24 +809,21 @@ class _BuyFormState extends ConsumerState { return ConditionalParent( condition: isDesktop, - builder: (child) => SizedBox( - width: 458, - child: child, - ), + builder: (child) => SizedBox(width: 458, child: child), child: ConditionalParent( condition: !isDesktop, - builder: (child) => LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, - ), + builder: + (child) => LayoutBuilder( + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ), ), - ), - ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -843,9 +834,7 @@ class _BuyFormState extends ConsumerState { color: Theme.of(context).extension()!.textDark3, ), ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), MouseRegion( cursor: SystemMouseCursors.click, onEnter: (_) => setState(() => _hovering1 = true), @@ -855,16 +844,19 @@ class _BuyFormState extends ConsumerState { selectCrypto(); }, child: RoundedContainer( - padding: - const EdgeInsets.symmetric(vertical: 6, horizontal: 2), - color: _hovering1 - ? Theme.of(context) - .extension()! - .currencyListItemBG - .withOpacity(_hovering1 ? 0.3 : 0) - : Theme.of(context) - .extension()! - .textFieldDefaultBG, + padding: const EdgeInsets.symmetric( + vertical: 6, + horizontal: 2, + ), + color: + _hovering1 + ? Theme.of(context) + .extension()! + .currencyListItemBG + .withOpacity(_hovering1 ? 0.3 : 0) + : Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: Padding( padding: const EdgeInsets.all(12), child: Row( @@ -873,9 +865,7 @@ class _BuyFormState extends ConsumerState { ticker: selectedCrypto?.ticker ?? "BTC", size: 20, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Text( selectedCrypto?.ticker ?? "ERR", @@ -884,9 +874,10 @@ class _BuyFormState extends ConsumerState { ), SvgPicture.asset( Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .buttonTextSecondaryDisabled, + color: + Theme.of(context) + .extension()! + .buttonTextSecondaryDisabled, width: 10, height: 5, ), @@ -896,9 +887,7 @@ class _BuyFormState extends ConsumerState { ), ), ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -912,9 +901,7 @@ class _BuyFormState extends ConsumerState { ), ], ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), MouseRegion( cursor: SystemMouseCursors.click, onEnter: (_) => setState(() => _hovering2 = true), @@ -924,16 +911,19 @@ class _BuyFormState extends ConsumerState { selectFiat(); }, child: RoundedContainer( - padding: - const EdgeInsets.symmetric(vertical: 3, horizontal: 2), - color: _hovering2 - ? Theme.of(context) - .extension()! - .currencyListItemBG - .withOpacity(_hovering2 ? 0.3 : 0) - : Theme.of(context) - .extension()! - .textFieldDefaultBG, + padding: const EdgeInsets.symmetric( + vertical: 3, + horizontal: 2, + ), + color: + _hovering2 + ? Theme.of(context) + .extension()! + .currencyListItemBG + .withOpacity(_hovering2 ? 0.3 : 0) + : Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: Padding( padding: const EdgeInsets.only( left: 12.0, @@ -949,9 +939,10 @@ class _BuyFormState extends ConsumerState { horizontal: 6, ), decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .currencyListItemBG, + color: + Theme.of( + context, + ).extension()!.currencyListItemBG, borderRadius: BorderRadius.circular(4), ), child: Text( @@ -960,22 +951,19 @@ class _BuyFormState extends ConsumerState { ), textAlign: TextAlign.center, style: STextStyles.smallMed12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), - const SizedBox( - width: 8, - ), + const SizedBox(width: 8), Text( selectedFiat?.ticker ?? 'ERR', style: STextStyles.largeMedium14(context), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( child: Text( selectedFiat?.name ?? 'Error', @@ -984,9 +972,10 @@ class _BuyFormState extends ConsumerState { ), SvgPicture.asset( Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .buttonTextSecondaryDisabled, + color: + Theme.of(context) + .extension()! + .buttonTextSecondaryDisabled, width: 10, height: 5, ), @@ -996,9 +985,7 @@ class _BuyFormState extends ConsumerState { ), ), ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1021,9 +1008,7 @@ class _BuyFormState extends ConsumerState { ), ], ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1037,12 +1022,13 @@ class _BuyFormState extends ConsumerState { // ? _BuyFormState.minFiat.toStringAsFixed(2) ?? '50.00' // : _BuyFormState.minCrypto.toStringAsFixed(8), focusNode: _buyAmountFocusNode, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.left, // inputFormatters: [NumericalRangeFormatter()], onChanged: (_) { @@ -1060,9 +1046,10 @@ class _BuyFormState extends ConsumerState { ), hintText: "0", hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, ), prefixIcon: FittedBox( fit: BoxFit.scaleDown, @@ -1073,33 +1060,34 @@ class _BuyFormState extends ConsumerState { const SizedBox(width: 2), buyWithFiat ? Container( - padding: const EdgeInsets.symmetric( - vertical: 3, - horizontal: 6, - ), - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .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) + padding: const EdgeInsets.symmetric( + vertical: 3, + horizontal: 6, + ), + decoration: BoxDecoration( + color: + Theme.of(context) .extension()! - .accentColorDark, - ), + .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()! + .accentColorDark, ), - ) - : CoinIconForTicker( - ticker: selectedCrypto?.ticker ?? "BTC", - size: 20, ), + ) + : CoinIconForTicker( + ticker: selectedCrypto?.ticker ?? "BTC", + size: 20, + ), SizedBox( width: buyWithFiat ? 8 : 10, ), // maybe make isDesktop-aware? @@ -1108,9 +1096,10 @@ class _BuyFormState extends ConsumerState { ? selectedFiat?.ticker ?? "ERR" : selectedCrypto?.ticker ?? "ERR", style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ], @@ -1125,65 +1114,63 @@ class _BuyFormState extends ConsumerState { children: [ _buyAmountController.text.isNotEmpty ? TextFieldIconButton( - key: const Key( - "buyViewClearAmountFieldButtonKey", - ), - onTap: () { - // if (_BuyFormState.buyWithFiat) { - // _buyAmountController.text = _BuyFormState - // .minFiat - // .toStringAsFixed(2); - // } else { - // if (selectedCrypto?.ticker == - // _BuyFormState.boundedCryptoTicker) { - // _buyAmountController.text = _BuyFormState - // .minCrypto - // .toStringAsFixed(8); - // } - // } - _buyAmountController.text = ""; - validateAmount(); - }, - child: const XIcon(), - ) + key: const Key( + "buyViewClearAmountFieldButtonKey", + ), + onTap: () { + // if (_BuyFormState.buyWithFiat) { + // _buyAmountController.text = _BuyFormState + // .minFiat + // .toStringAsFixed(2); + // } else { + // if (selectedCrypto?.ticker == + // _BuyFormState.boundedCryptoTicker) { + // _buyAmountController.text = _BuyFormState + // .minCrypto + // .toStringAsFixed(8); + // } + // } + _buyAmountController.text = ""; + validateAmount(); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "buyViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = await clipboard - .getData(Clipboard.kTextPlain); + key: const Key( + "buyViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = await clipboard + .getData(Clipboard.kTextPlain); - final amountString = - Decimal.tryParse(data?.text ?? ""); - if (amountString != null) { - _buyAmountController.text = - amountString.toString(); + final amountString = Decimal.tryParse( + data?.text ?? "", + ); + if (amountString != null) { + _buyAmountController.text = + amountString.toString(); - validateAmount(); - } - }, - child: _buyAmountController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + validateAmount(); + } + }, + child: + _buyAmountController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), ], ), ), ), ), ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), if (_amountOutOfRangeErrorString.isNotEmpty) Text( _amountOutOfRangeErrorString, style: STextStyles.errorSmall(context), ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1205,41 +1192,37 @@ class _BuyFormState extends ConsumerState { ); Navigator.of(context) .pushNamed( - ChooseFromStackView.routeName, - arguments: coin, - ) + ChooseFromStackView.routeName, + arguments: coin, + ) .then((value) async { - if (value is String) { - final wallet = ref.read(pWallets).getWallet(value); - - // _toController.text = manager.walletName; - // model.recipientAddress = - // await manager.currentReceivingAddress; - _receiveAddressController.text = - (await wallet.getCurrentReceivingAddress())! - .value; - - setState(() { - _addressToggleFlag = - _receiveAddressController.text.isNotEmpty; + if (value is String) { + final wallet = ref + .read(pWallets) + .getWallet(value); + + // _toController.text = manager.walletName; + // model.recipientAddress = + // await manager.currentReceivingAddress; + _receiveAddressController.text = + (await wallet.getCurrentReceivingAddress())! + .value; + + setState(() { + _addressToggleFlag = + _receiveAddressController.text.isNotEmpty; + }); + validateAmount(); + } }); - validateAmount(); - } - }); } catch (e, s) { - Logging.instance.w( - "", - error: e, - stackTrace: s, - ); + Logging.instance.w("", error: e, stackTrace: s); } }, ), ], ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1289,105 +1272,115 @@ class _BuyFormState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _receiveAddressController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _receiveAddressController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _addressToggleFlag ? TextFieldIconButton( - key: const Key( - "buyViewClearAddressFieldButtonKey", - ), - onTap: () { - _receiveAddressController.text = ""; - _address = ""; - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) + key: const Key( + "buyViewClearAddressFieldButtonKey", + ), + onTap: () { + _receiveAddressController.text = ""; + _address = ""; + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "buyViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = await clipboard - .getData(Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = data.text!.trim(); - if (content.contains("\n")) { - content = content.substring( - 0, - content.indexOf("\n"), - ); - } - - _receiveAddressController.text = content; - _address = content; - - setState(() { - _addressToggleFlag = - _receiveAddressController - .text.isNotEmpty; - }); - } - }, - child: _receiveAddressController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + key: const Key( + "buyViewPasteAddressFieldButtonKey", ), + onTap: () async { + final ClipboardData? data = await clipboard + .getData(Clipboard.kTextPlain); + if (data?.text != null && + data!.text!.isNotEmpty) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring( + 0, + content.indexOf("\n"), + ); + } + + _receiveAddressController.text = content; + _address = content; + + setState(() { + _addressToggleFlag = + _receiveAddressController + .text + .isNotEmpty; + }); + } + }, + child: + _receiveAddressController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_receiveAddressController.text.isEmpty && AppConfig.isStackCoin(selectedCrypto?.ticker) && isDesktop) TextFieldIconButton( key: const Key("buyViewAddressBookButtonKey"), onTap: () async { - final entry = - await showDialog( + final entry = await showDialog< + ContactAddressEntry? + >( context: context, - builder: (context) => DesktopDialog( - maxWidth: 696, - maxHeight: 600, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 696, + maxHeight: 600, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Address book", - style: STextStyles.desktopH3( - context, + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.only( + left: 32, + ), + child: Text( + "Address book", + style: + STextStyles.desktopH3( + context, + ), + ), ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: AddressBookAddressChooser( + coin: AppConfig.coins + .firstWhere( + (e) => + e.ticker + .toLowerCase() == + selectedCrypto!.ticker + .toString() + .toLowerCase(), + ), ), ), - const DesktopDialogCloseButton(), ], ), - Expanded( - child: AddressBookAddressChooser( - coin: AppConfig.coins.firstWhere( - (e) => - e.ticker.toLowerCase() == - selectedCrypto!.ticker - .toString() - .toLowerCase(), - ), - ), - ), - ], - ), - ), + ), ); if (entry != null) { @@ -1408,10 +1401,10 @@ class _BuyFormState extends ConsumerState { TextFieldIconButton( key: const Key("buyViewAddressBookButtonKey"), onTap: () { - Navigator.of(context, rootNavigator: isDesktop) - .pushNamed( - AddressBookView.routeName, - ); + Navigator.of( + context, + rootNavigator: isDesktop, + ).pushNamed(AddressBookView.routeName); }, child: const AddressBookIcon(), ), @@ -1429,20 +1422,17 @@ class _BuyFormState extends ConsumerState { ), ), ), - SizedBox( - height: isDesktop ? 10 : 4, - ), + SizedBox(height: isDesktop ? 10 : 4), if (_receivingAddressValidationErrorString.isNotEmpty) Text( _receivingAddressValidationErrorString, style: STextStyles.errorSmall(context), ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, - enabled: _addressToggleFlag && + enabled: + _addressToggleFlag && _amountOutOfRangeErrorString.isEmpty && _buyAmountController.text.isNotEmpty, onPressed: () { diff --git a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart index 618bafb05..621b981ec 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart @@ -44,14 +44,12 @@ class Step2View extends ConsumerStatefulWidget { super.key, required this.model, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), }); static const String routeName = "/exchangeStep2"; final IncompleteExchangeModel model; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; @override ConsumerState createState() => _Step2ViewState(); @@ -60,7 +58,6 @@ class Step2View extends ConsumerStatefulWidget { class _Step2ViewState extends ConsumerState { late final IncompleteExchangeModel model; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late final TextEditingController _toController; late final TextEditingController _refundController; @@ -72,7 +69,7 @@ class _Step2ViewState extends ConsumerState { void _onRefundQrTapped() async { try { - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); final paymentData = AddressUtils.parsePaymentUri( qrResult.rawContent, @@ -100,17 +97,32 @@ class _Step2ViewState extends ConsumerState { }); } } on PlatformException catch (e, s) { - Logging.instance.w( - "Failed to get camera permissions while trying to scan qr code in SendView: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions while trying to scan qr code in $runtimeType: ", + error: e, + stackTrace: s, + ); + } } } void _onToQrTapped() async { try { - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); final paymentData = AddressUtils.parsePaymentUri( qrResult.rawContent, @@ -140,11 +152,26 @@ class _Step2ViewState extends ConsumerState { }); } } on PlatformException catch (e, s) { - Logging.instance.w( - "Failed to get camera permissions while trying to scan qr code in SendView: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions while trying to scan qr code in $runtimeType: ", + error: e, + stackTrace: s, + ); + } } } @@ -152,7 +179,6 @@ class _Step2ViewState extends ConsumerState { void initState() { model = widget.model; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; _toController = TextEditingController(); _refundController = TextEditingController(); diff --git a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart index dcd8e1282..1061eb128 100644 --- a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart @@ -41,14 +41,12 @@ class TransferOptionWidget extends ConsumerStatefulWidget { required this.walletId, required this.utxo, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), }); final String walletId; final UTXO utxo; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; @override ConsumerState createState() => @@ -58,7 +56,7 @@ class TransferOptionWidget extends ConsumerStatefulWidget { class _TransferOptionWidgetState extends ConsumerState { late final String walletId; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; + late final TextEditingController _addressController; late final FocusNode _addressFocusNode; @@ -71,9 +69,7 @@ class _TransferOptionWidgetState extends ConsumerState { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); try { final wallet = ref.read(pWallets).getWallet(walletId) as NamecoinWallet; @@ -129,11 +125,7 @@ class _TransferOptionWidgetState extends ConsumerState { final opName = wallet.getOpNameDataFrom(widget.utxo)!; - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); final nameScriptHex = scriptNameUpdate(opName.fullname, opName.value); @@ -164,10 +156,7 @@ class _TransferOptionWidgetState extends ConsumerState { ), ); - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); final txData = results.first as TxData; @@ -179,15 +168,16 @@ class _TransferOptionWidgetState extends ConsumerState { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => SDialog( - child: SizedBox( - width: 580, - child: ConfirmNameTransactionView( - txData: txData, - walletId: widget.walletId, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: ConfirmNameTransactionView( + txData: txData, + walletId: widget.walletId, + ), + ), ), - ), - ), ); } else { await Navigator.of(context).pushNamed( @@ -212,12 +202,13 @@ class _TransferOptionWidgetState extends ConsumerState { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Error", - message: err, - desktopPopRootNavigator: Util.isDesktop, - maxWidth: Util.isDesktop ? 600 : null, - ), + builder: + (_) => StackOkDialog( + title: "Error", + message: err, + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), ); } } finally { @@ -245,7 +236,7 @@ class _TransferOptionWidgetState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); final coin = ref.read(pWalletCoin(walletId)); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); @@ -271,14 +262,27 @@ class _TransferOptionWidgetState extends ConsumerState { _setValidAddressProviders(_address); } } on PlatformException catch (e, s) { - // here we ignore the exception caused by not giving permission - // to use the camera to scan a qr code - Logging.instance.e( - "Failed to get camera permissions while trying to scan qr code in" - " $runtimeType", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.e( + "Failed to get camera permissions while trying to scan qr code in" + " $runtimeType", + error: e, + stackTrace: s, + ); + } } } @@ -287,7 +291,7 @@ class _TransferOptionWidgetState extends ConsumerState { super.initState(); walletId = widget.walletId; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; + _addressController = TextEditingController(); _addressFocusNode = FocusNode(); WidgetsBinding.instance.addPostFrameCallback((_) { @@ -345,72 +349,64 @@ class _TransferOptionWidgetState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _addressController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _addressController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _addressController.text.isNotEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Address Field Input.", - key: const Key( - "nameTransferClearAddressFieldButtonKey", - ), - onTap: () { - _addressController.text = ""; - _address = ""; - _setValidAddressProviders( - _address, - ); - setState(() {}); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "nameTransferClearAddressFieldButtonKey", + ), + onTap: () { + _addressController.text = ""; + _address = ""; + _setValidAddressProviders(_address); + setState(() {}); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", - key: const Key( - "nameTransferPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = data.text!.trim(); - if (content.contains("\n")) { - content = content.substring( - 0, - content.indexOf( - "\n", - ), - ); - } - - _addressController.text = content.trim(); - _address = content.trim(); - - _setValidAddressProviders( - _address, + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "nameTransferPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = await clipboard + .getData(Clipboard.kTextPlain); + if (data?.text != null && + data!.text!.isNotEmpty) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring( + 0, + content.indexOf("\n"), ); } - }, - child: _addressController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + + _addressController.text = content.trim(); + _address = content.trim(); + + _setValidAddressProviders(_address); + } + }, + child: + _addressController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_addressController.text.isEmpty) TextFieldIconButton( semanticsLabel: "Address Book Button. Opens Address Book For Address Field.", - key: const Key( - "nameTransferAddressBookButtonKey", - ), + key: const Key("nameTransferAddressBookButtonKey"), onTap: () { Navigator.of(context).pushNamed( AddressBookView.routeName, @@ -423,9 +419,7 @@ class _TransferOptionWidgetState extends ConsumerState { TextFieldIconButton( semanticsLabel: "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key( - "nameTransferScanQrButtonKey", - ), + key: const Key("nameTransferScanQrButtonKey"), onTap: _scanQr, child: const QrCodeIcon(), ), @@ -436,32 +430,28 @@ class _TransferOptionWidgetState extends ConsumerState { ), ), ), - SizedBox( - height: Util.isDesktop ? 42 : 16, - ), + SizedBox(height: Util.isDesktop ? 42 : 16), if (!Util.isDesktop) const Spacer(), ConditionalParent( condition: Util.isDesktop, - builder: (child) => Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: ButtonHeight.l, - onPressed: Navigator.of( - context, - rootNavigator: Util.isDesktop, - ).pop, - ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: child, + builder: + (child) => Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: + Navigator.of( + context, + rootNavigator: Util.isDesktop, + ).pop, + ), + ), + const SizedBox(width: 16), + Expanded(child: child), + ], ), - ], - ), child: PrimaryButton( label: "Transfer", enabled: _enableButton, @@ -470,10 +460,7 @@ class _TransferOptionWidgetState extends ConsumerState { onPressed: _preview, ), ), - if (!Util.isDesktop) - const SizedBox( - height: 16, - ), + if (!Util.isDesktop) const SizedBox(height: 16), ], ); } diff --git a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart index 80c016245..e438e420c 100644 --- a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart @@ -9,7 +9,6 @@ import '../../../models/isar/models/blockchain_data/utxo.dart'; import '../../../providers/global/wallets_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/extensions/extensions.dart'; import '../../../utilities/logger.dart'; @@ -33,14 +32,12 @@ class UpdateOptionWidget extends ConsumerStatefulWidget { required this.walletId, required this.utxo, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), }); final String walletId; final UTXO utxo; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; @override ConsumerState createState() => _BuyDomainWidgetState(); @@ -84,9 +81,7 @@ class _BuyDomainWidgetState extends ConsumerState { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); final wallet = ref.read(pWallets).getWallet(widget.walletId) as NamecoinWallet; @@ -144,11 +139,7 @@ class _BuyDomainWidgetState extends ConsumerState { final opName = wallet.getOpNameDataFrom(widget.utxo)!; - final time = Future.delayed( - const Duration( - milliseconds: 2500, - ), - ); + final time = Future.delayed(const Duration(milliseconds: 2500)); final nameScriptHex = scriptNameUpdate(opName.fullname, newValue); @@ -179,10 +170,7 @@ class _BuyDomainWidgetState extends ConsumerState { ), ); - final results = await Future.wait([ - txDataFuture, - time, - ]); + final results = await Future.wait([txDataFuture, time]); final txData = results.first as TxData; @@ -194,15 +182,16 @@ class _BuyDomainWidgetState extends ConsumerState { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => SDialog( - child: SizedBox( - width: 580, - child: ConfirmNameTransactionView( - txData: txData, - walletId: widget.walletId, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: ConfirmNameTransactionView( + txData: txData, + walletId: widget.walletId, + ), + ), ), - ), - ), ); } else { await Navigator.of(context).pushNamed( @@ -227,12 +216,13 @@ class _BuyDomainWidgetState extends ConsumerState { if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Update failed", - message: err, - desktopPopRootNavigator: Util.isDesktop, - maxWidth: Util.isDesktop ? 600 : null, - ), + builder: + (_) => StackOkDialog( + title: "Update failed", + message: err, + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), ); } } finally { @@ -269,17 +259,13 @@ class _BuyDomainWidgetState extends ConsumerState { Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: Util.isDesktop - ? CrossAxisAlignment.start - : CrossAxisAlignment.stretch, + crossAxisAlignment: + Util.isDesktop + ? CrossAxisAlignment.start + : CrossAxisAlignment.stretch, children: [ - Text( - "Edit value", - style: STextStyles.label(context), - ), - const SizedBox( - height: 6, - ), + Text("Edit value", style: STextStyles.label(context)), + const SizedBox(height: 6), TextField( controller: _controller, maxLines: null, @@ -296,9 +282,7 @@ class _BuyDomainWidgetState extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -308,18 +292,17 @@ class _BuyDomainWidgetState extends ConsumerState { return Text( "$length/$valueMaxLength", style: STextStyles.w500_10(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), ); }, ), ], ), - SizedBox( - height: Util.isDesktop ? 32 : 16, - ), + SizedBox(height: Util.isDesktop ? 32 : 16), if (!Util.isDesktop) const Spacer(), Row( children: [ @@ -327,15 +310,11 @@ class _BuyDomainWidgetState extends ConsumerState { child: SecondaryButton( label: "Cancel", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, - onPressed: Navigator.of( - context, - rootNavigator: Util.isDesktop, - ).pop, + onPressed: + Navigator.of(context, rootNavigator: Util.isDesktop).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Update", @@ -346,10 +325,7 @@ class _BuyDomainWidgetState extends ConsumerState { ), ], ), - if (!Util.isDesktop) - const SizedBox( - height: 16, - ), + if (!Util.isDesktop) const SizedBox(height: 16), ], ); } diff --git a/lib/pages/paynym/add_new_paynym_follow_view.dart b/lib/pages/paynym/add_new_paynym_follow_view.dart index 5f9e7bb71..d74a17429 100644 --- a/lib/pages/paynym/add_new_paynym_follow_view.dart +++ b/lib/pages/paynym/add_new_paynym_follow_view.dart @@ -16,9 +16,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/paynym/paynym_account.dart'; import '../../providers/global/paynym_api_provider.dart'; +import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/barcode_scanner_interface.dart'; import '../../utilities/constants.dart'; +import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../widgets/conditional_parent.dart'; @@ -40,10 +42,7 @@ import 'subwidgets/featured_paynyms_widget.dart'; import 'subwidgets/paynym_card.dart'; class AddNewPaynymFollowView extends ConsumerStatefulWidget { - const AddNewPaynymFollowView({ - super.key, - required this.walletId, - }); + const AddNewPaynymFollowView({super.key, required this.walletId}); final String walletId; @@ -73,9 +72,7 @@ class _AddNewPaynymFollowViewState showDialog( barrierDismissible: false, context: context, - builder: (context) => const LoadingIndicator( - width: 200, - ), + builder: (context) => const LoadingIndicator(width: 200), ).then((_) => didPopLoading = true), ); @@ -104,12 +101,7 @@ class _AddNewPaynymFollowViewState if (data?.text != null && data!.text!.isNotEmpty) { String content = data.text!.trim(); if (content.contains("\n")) { - content = content.substring( - 0, - content.indexOf( - "\n", - ), - ); + content = content.substring(0, content.indexOf("\n")); } _searchString = content; @@ -129,7 +121,7 @@ class _AddNewPaynymFollowViewState await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await const BarcodeScannerWrapper().scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); final pCodeString = qrResult.rawContent; @@ -141,6 +133,21 @@ class _AddNewPaynymFollowViewState offset: pCodeString.length, ); }); + } on PlatformException catch (e, s) { + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } } catch (_) { // scan failed } @@ -166,100 +173,95 @@ class _AddNewPaynymFollowViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => MasterScaffold( - isDesktop: isDesktop, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - titleSpacing: 0, - title: Text( - "New follow", - style: STextStyles.navBarTitle(context), - overflow: TextOverflow.ellipsis, - ), - ), - body: SafeArea( - child: LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(16), - child: child, - ), - ), + builder: + (child) => MasterScaffold( + isDesktop: isDesktop, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "New follow", + style: STextStyles.navBarTitle(context), + overflow: TextOverflow.ellipsis, + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ), + ), ), ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "New follow", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "New follow", - style: STextStyles.desktopH3(context), + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, ), + child: child, ), - const DesktopDialogCloseButton(), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), - child: child, - ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), Text( "Featured PayNyms", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.sectionLabelMedium12(context), - ), - const SizedBox( - height: 12, - ), - FeaturedPaynymsWidget( - walletId: widget.walletId, - ), - const SizedBox( - height: 24, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.sectionLabelMedium12(context), ), + const SizedBox(height: 12), + FeaturedPaynymsWidget(walletId: widget.walletId), + const SizedBox(height: 24), Text( "Add new", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.sectionLabelMedium12(context), - ), - const SizedBox( - height: 12, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.sectionLabelMedium12(context), ), + const SizedBox(height: 12), if (isDesktop) Row( children: [ @@ -268,9 +270,10 @@ class _AddNewPaynymFollowViewState children: [ RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, height: 56, child: Center( child: TextField( @@ -286,9 +289,10 @@ class _AddNewPaynymFollowViewState style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + color: + Theme.of(context) + .extension()! + .textFieldActiveText, // height: 1.8, ), decoration: InputDecoration( @@ -296,11 +300,9 @@ class _AddNewPaynymFollowViewState hoverColor: Colors.transparent, fillColor: Colors.transparent, contentPadding: const EdgeInsets.all(16), - hintStyle: - STextStyles.desktopTextFieldLabel(context) - .copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.desktopTextFieldLabel( + context, + ).copyWith(fontSize: 14), enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, errorBorder: InputBorder.none, @@ -313,30 +315,38 @@ class _AddNewPaynymFollowViewState children: [ _searchController.text.isNotEmpty ? TextFieldIconButton( - onTap: _clear, - child: RoundedContainer( - padding: - const EdgeInsets.all(8), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: const XIcon(), + onTap: _clear, + child: RoundedContainer( + padding: const EdgeInsets.all( + 8, ), - ) + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonBackSecondary, + child: const XIcon(), + ), + ) : TextFieldIconButton( - key: const Key( - "paynymPasteAddressFieldButtonKey", - ), - onTap: _paste, - child: RoundedContainer( - padding: - const EdgeInsets.all(8), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: const ClipboardIcon(), + key: const Key( + "paynymPasteAddressFieldButtonKey", + ), + onTap: _paste, + child: RoundedContainer( + padding: const EdgeInsets.all( + 8, ), + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonBackSecondary, + child: const ClipboardIcon(), ), + ), TextFieldIconButton( key: const Key( "paynymScanQrButtonKey", @@ -344,9 +354,10 @@ class _AddNewPaynymFollowViewState onTap: _scanQr, child: RoundedContainer( padding: const EdgeInsets.all(8), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: const QrCodeIcon(), ), ), @@ -361,9 +372,7 @@ class _AddNewPaynymFollowViewState ], ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), PaynymSearchButton(onPressed: _search), ], ), @@ -396,16 +405,16 @@ class _AddNewPaynymFollowViewState children: [ _searchController.text.isNotEmpty ? TextFieldIconButton( - onTap: _clear, - child: const XIcon(), - ) + onTap: _clear, + child: const XIcon(), + ) : TextFieldIconButton( - key: const Key( - "paynymPasteAddressFieldButtonKey", - ), - onTap: _paste, - child: const ClipboardIcon(), + key: const Key( + "paynymPasteAddressFieldButtonKey", ), + onTap: _paste, + child: const ClipboardIcon(), + ), TextFieldIconButton( key: const Key("paynymScanQrButtonKey"), onTap: _scanQr, @@ -418,34 +427,27 @@ class _AddNewPaynymFollowViewState ), ), ), + if (!isDesktop) const SizedBox(height: 12), if (!isDesktop) - const SizedBox( - height: 12, - ), - if (!isDesktop) - SecondaryButton( - label: "Search", - onPressed: _search, - ), - if (_didSearch) - const SizedBox( - height: 20, - ), + SecondaryButton(label: "Search", onPressed: _search), + if (_didSearch) const SizedBox(height: 20), if (_didSearch && _searchResult == null) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Nothing found. Please check the payment code.", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.label(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.label(context), ), ], ), @@ -453,11 +455,12 @@ class _AddNewPaynymFollowViewState if (_didSearch && _searchResult != null) RoundedWhiteContainer( padding: const EdgeInsets.all(0), - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, child: PaynymCard( key: UniqueKey(), label: _searchResult!.nymName, diff --git a/lib/pages/send_view/frost_ms/recipient.dart b/lib/pages/send_view/frost_ms/recipient.dart index ba8b9dbd7..36122962c 100644 --- a/lib/pages/send_view/frost_ms/recipient.dart +++ b/lib/pages/send_view/frost_ms/recipient.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../../../providers/global/locale_provider.dart'; +import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/address_utils.dart'; import '../../../utilities/amount/amount.dart'; @@ -11,7 +11,6 @@ import '../../../utilities/amount/amount_formatter.dart'; import '../../../utilities/amount/amount_input_formatter.dart'; import '../../../utilities/amount/amount_unit.dart'; import '../../../utilities/barcode_scanner_interface.dart'; -import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/constants.dart'; import '../../../utilities/logger.dart'; import '../../../utilities/text_styles.dart'; @@ -25,12 +24,6 @@ import '../../../widgets/rounded_container.dart'; import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; -//TODO: move the following two providers elsewhere -final pClipboard = - Provider((ref) => const ClipboardWrapper()); -final pBarcodeScanner = - Provider((ref) => const BarcodeScannerWrapper()); - // final _pPrice = Provider.family((ref, coin) { // return ref.watch( // priceAnd24hChangeNotifierProvider @@ -40,8 +33,8 @@ final pBarcodeScanner = final pRecipient = StateProvider.family<({String address, Amount? amount})?, int>( - (ref, index) => null, -); + (ref, index) => null, + ); class Recipient extends ConsumerStatefulWidget { const Recipient({ @@ -79,8 +72,9 @@ class _RecipientState extends ConsumerState { void _updateRecipientData() { final address = addressController.text; - final amount = - ref.read(pAmountFormatter(widget.coin)).tryParse(amountController.text); + final amount = ref + .read(pAmountFormatter(widget.coin)) + .tryParse(amountController.text); ref.read(pRecipient(widget.index).notifier).state = ( address: address, @@ -91,9 +85,9 @@ class _RecipientState extends ConsumerState { void _cryptoAmountChanged() async { if (!_cryptoAmountChangeLock) { - Amount? cryptoAmount = ref.read(pAmountFormatter(widget.coin)).tryParse( - amountController.text, - ); + Amount? cryptoAmount = ref + .read(pAmountFormatter(widget.coin)) + .tryParse(amountController.text); if (cryptoAmount != null) { if (ref.read(pRecipient(widget.index))?.amount != null && ref.read(pRecipient(widget.index))?.amount == cryptoAmount) { @@ -124,11 +118,7 @@ class _RecipientState extends ConsumerState { try { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration( - milliseconds: 75, - ), - ); + await Future.delayed(const Duration(milliseconds: 75)); } final qrResult = await ref.read(pBarcodeScanner).scan(); @@ -150,14 +140,12 @@ class _RecipientState extends ConsumerState { // autofill amount field if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: widget.coin.fractionDigits, - ); - amountController.text = - ref.read(pAmountFormatter(widget.coin)).format( - amount, - withUnitName: false, - ); + final Amount amount = Decimal.parse( + paymentData.amount!, + ).toAmount(fractionDigits: widget.coin.fractionDigits); + amountController.text = ref + .read(pAmountFormatter(widget.coin)) + .format(amount, withUnitName: false); } } else { addressController.text = qrResult.rawContent.trim(); @@ -169,12 +157,27 @@ class _RecipientState extends ConsumerState { _updateRecipientData(); } on PlatformException catch (e, s) { - Logging.instance.e( - "Failed to get camera permissions while " - "trying to scan qr code in SendView: $e\n$s", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.e( + "Failed to get camera permissions while " + "trying to scan qr code in SendView: $e\n$s", + error: e, + stackTrace: s, + ); + } } } @@ -221,9 +224,7 @@ class _RecipientState extends ConsumerState { @override Widget build(BuildContext context) { final String locale = ref.watch( - localeServiceChangeNotifierProvider.select( - (value) => value.locale, - ), + localeServiceChangeNotifierProvider.select((value) => value.locale), ); return RoundedContainer( @@ -248,9 +249,7 @@ class _RecipientState extends ConsumerState { ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -281,72 +280,73 @@ class _RecipientState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _addressIsEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _addressIsEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ !_addressIsEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Address Field Input.", - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - addressController.text = ""; + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + addressController.text = ""; + + setState(() { + _addressIsEmpty = true; + }); + + _updateRecipientData(); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = await ref + .read(pClipboard) + .getData(Clipboard.kTextPlain); + if (data?.text != null && + data!.text!.isNotEmpty) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring( + 0, + content.indexOf("\n"), + ); + } + + addressController.text = content.trim(); setState(() { - _addressIsEmpty = true; + _addressIsEmpty = + addressController.text.isEmpty; }); _updateRecipientData(); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = await ref - .read(pClipboard) - .getData(Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = data.text!.trim(); - if (content.contains("\n")) { - content = content.substring( - 0, - content.indexOf("\n"), - ); - } - - addressController.text = content.trim(); - - setState(() { - _addressIsEmpty = - addressController.text.isEmpty; - }); - - _updateRecipientData(); - } - }, - child: _addressIsEmpty - ? const ClipboardIcon() - : const XIcon(), - ), + } + }, + child: + _addressIsEmpty + ? const ClipboardIcon() + : const XIcon(), + ), if (_addressIsEmpty) TextFieldIconButton( - semanticsLabel: "Scan QR Button. " + semanticsLabel: + "Scan QR Button. " "Opens Camera For Scanning QR Code.", - key: const Key( - "sendViewScanQrButtonKey", - ), + key: const Key("sendViewScanQrButtonKey"), onTap: _onQrTapped, child: const QrCodeIcon(), ), @@ -357,9 +357,7 @@ class _RecipientState extends ConsumerState { ), ), ), - SizedBox( - height: isSingle ? 12 : 8, - ), + SizedBox(height: isSingle ? 12 : 8), if (isSingle) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -380,10 +378,7 @@ class _RecipientState extends ConsumerState { // ), ], ), - if (isSingle) - const SizedBox( - height: 8, - ), + if (isSingle) const SizedBox(height: 8), TextField( autocorrect: false, enableSuggestions: false, @@ -396,12 +391,13 @@ class _RecipientState extends ConsumerState { onChanged: (_) { _updateRecipientData(); }, - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( @@ -411,14 +407,9 @@ class _RecipientState extends ConsumerState { ), ], decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - top: 12, - right: 12, - ), + contentPadding: const EdgeInsets.only(top: 12, right: 12), hintText: "0", - hintStyle: STextStyles.fieldLabel(context).copyWith( - fontSize: 14, - ), + hintStyle: STextStyles.fieldLabel(context).copyWith(fontSize: 14), prefixIcon: FittedBox( fit: BoxFit.scaleDown, child: Padding( @@ -428,9 +419,10 @@ class _RecipientState extends ConsumerState { .watch(pAmountUnit(widget.coin)) .unitForCoin(widget.coin), style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 4ea893ea7..d2806d513 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -83,7 +83,6 @@ class SendView extends ConsumerStatefulWidget { required this.coin, this.autoFillData, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), this.accountLite, }); @@ -93,7 +92,6 @@ class SendView extends ConsumerStatefulWidget { final CryptoCurrency coin; final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; final PaynymAccountLite? accountLite; @override @@ -111,7 +109,6 @@ class _SendViewState extends ConsumerState { late final String walletId; late final CryptoCurrency coin; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late TextEditingController sendToController; late TextEditingController cryptoAmountController; @@ -271,7 +268,7 @@ class _SendViewState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); // Future.delayed( // const Duration(seconds: 2), @@ -307,13 +304,27 @@ class _SendViewState extends ConsumerState { // shouldShowLockscreenOnResumeStateProvider // .state) // .state = true; - // here we ignore the exception caused by not giving permission - // to use the camera to scan a qr code - Logging.instance.e( - "Failed to get camera permissions while trying to scan qr code in SendView: ", - error: e, - stackTrace: s, - ); + + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.e( + "Failed to get camera permissions while trying to scan qr code in SendView: ", + error: e, + stackTrace: s, + ); + } } } @@ -1055,7 +1066,6 @@ class _SendViewState extends ConsumerState { _data = widget.autoFillData; walletId = widget.walletId; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; isStellar = coin is Stellar; isFiro = coin is Firo; isEth = coin is Ethereum; diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 8d9f41327..635df7e89 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -69,7 +69,6 @@ class TokenSendView extends ConsumerStatefulWidget { required this.tokenContract, this.autoFillData, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), }); static const String routeName = "/tokenSendView"; @@ -79,7 +78,6 @@ class TokenSendView extends ConsumerStatefulWidget { final EthContract tokenContract; final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; @override ConsumerState createState() => _TokenSendViewState(); @@ -90,7 +88,6 @@ class _TokenSendViewState extends ConsumerState { late final CryptoCurrency coin; late final EthContract tokenContract; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late TextEditingController sendToController; late TextEditingController cryptoAmountController; @@ -154,7 +151,7 @@ class _TokenSendViewState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); // Future.delayed( // const Duration(seconds: 2), @@ -223,13 +220,26 @@ class _TokenSendViewState extends ConsumerState { // shouldShowLockscreenOnResumeStateProvider // .state) // .state = true; - // here we ignore the exception caused by not giving permission - // to use the camera to scan a qr code - Logging.instance.w( - "Failed to get camera permissions while trying to scan qr code in SendView: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions while trying to scan qr code in SendView: ", + error: e, + stackTrace: s, + ); + } } } @@ -581,7 +591,6 @@ class _TokenSendViewState extends ConsumerState { coin = widget.coin; tokenContract = widget.tokenContract; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; sendToController = TextEditingController(); cryptoAmountController = TextEditingController(); diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 61450faad..ca6918811 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -10,7 +10,6 @@ import 'dart:async'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -24,6 +23,7 @@ import '../../../../providers/global/secure_store_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; +import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/enums/sync_type_enum.dart'; import '../../../../utilities/flutter_secure_storage_interface.dart'; @@ -374,8 +374,23 @@ class _AddEditNodeViewState extends ConsumerState { } } else { try { - final result = await BarcodeScanner.scan(); + final result = await ref.read(pBarcodeScanner).scan(); await _processQrData(result.rawContent); + } on PlatformException catch (e, s) { + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } } catch (e, s) { Logging.instance.e("$runtimeType._scanQr()", error: e, stackTrace: s); } diff --git a/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart b/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart index 476a3eb24..1ff4405df 100644 --- a/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart @@ -24,7 +24,6 @@ import '../../../themes/coin_icon_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount_formatter.dart'; -import '../../../utilities/barcode_scanner_interface.dart'; import '../../../utilities/clipboard_interface.dart'; import '../../../utilities/text_styles.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; @@ -39,14 +38,13 @@ class DesktopPaynymSendDialog extends ConsumerStatefulWidget { required this.walletId, this.autoFillData, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), + this.accountLite, }); final String walletId; final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; final PaynymAccountLite? accountLite; @override diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 7dd007a2e..609f1d757 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -37,7 +37,6 @@ import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/amount/amount_input_formatter.dart'; import '../../../../utilities/amount/amount_unit.dart'; import '../../../../utilities/assets.dart'; -import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/clipboard_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/logger.dart'; @@ -78,14 +77,13 @@ class DesktopSend extends ConsumerStatefulWidget { required this.walletId, this.autoFillData, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), + this.accountLite, }); final String walletId; final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; final PaynymAccountLite? accountLite; @override @@ -96,7 +94,6 @@ class _DesktopSendState extends ConsumerState { late final String walletId; late final CryptoCurrency coin; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late TextEditingController sendToController; late TextEditingController cryptoAmountController; @@ -894,7 +891,7 @@ class _DesktopSendState extends ConsumerState { walletId = widget.walletId; coin = ref.read(pWalletInfo(walletId)).coin; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; + isStellar = coin is Stellar; sendToController = TextEditingController(); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 48e8cb230..34071ea8e 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -30,7 +30,6 @@ import '../../../../utilities/amount/amount.dart'; import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/amount/amount_input_formatter.dart'; import '../../../../utilities/amount/amount_unit.dart'; -import '../../../../utilities/barcode_scanner_interface.dart'; import '../../../../utilities/clipboard_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/logger.dart'; @@ -61,14 +60,13 @@ class DesktopTokenSend extends ConsumerStatefulWidget { required this.walletId, this.autoFillData, this.clipboard = const ClipboardWrapper(), - this.barcodeScanner = const BarcodeScannerWrapper(), + this.accountLite, }); final String walletId; final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; - final BarcodeScannerInterface barcodeScanner; final PaynymAccountLite? accountLite; @override @@ -79,7 +77,6 @@ class _DesktopTokenSendState extends ConsumerState { late final String walletId; late final CryptoCurrency coin; late final ClipboardInterface clipboard; - late final BarcodeScannerInterface scanner; late TextEditingController sendToController; late TextEditingController cryptoAmountController; @@ -423,7 +420,7 @@ class _DesktopTokenSendState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await scanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); @@ -588,7 +585,6 @@ class _DesktopTokenSendState extends ConsumerState { walletId = widget.walletId; coin = ref.read(pWallets).getWallet(walletId).info.coin; clipboard = widget.clipboard; - scanner = widget.barcodeScanner; sendToController = TextEditingController(); cryptoAmountController = TextEditingController(); diff --git a/lib/providers/global/barcode_scanner_provider.dart b/lib/providers/global/barcode_scanner_provider.dart new file mode 100644 index 000000000..3623b20a1 --- /dev/null +++ b/lib/providers/global/barcode_scanner_provider.dart @@ -0,0 +1,7 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../utilities/barcode_scanner_interface.dart'; + +final pBarcodeScanner = Provider( + (ref) => const BarcodeScannerWrapper(), +); diff --git a/lib/providers/global/clipboard_provider.dart b/lib/providers/global/clipboard_provider.dart new file mode 100644 index 000000000..956d03c02 --- /dev/null +++ b/lib/providers/global/clipboard_provider.dart @@ -0,0 +1,7 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../utilities/clipboard_interface.dart'; + +final pClipboard = Provider( + (ref) => const ClipboardWrapper(), +); diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart index 90e0ced3a..3db18af2f 100644 --- a/lib/providers/providers.dart +++ b/lib/providers/providers.dart @@ -19,6 +19,8 @@ export './exchange/exchange_form_state_provider.dart'; export './exchange/exchange_send_from_wallet_id_provider.dart'; export './exchange/trade_note_service_provider.dart'; export './exchange/trade_sent_from_stack_lookup_provider.dart'; +export './global/barcode_scanner_provider.dart'; +export './global/clipboard_provider.dart'; export './global/duress_provider.dart'; export './global/locale_provider.dart'; export './global/node_service_provider.dart'; diff --git a/lib/utilities/barcode_scanner_interface.dart b/lib/utilities/barcode_scanner_interface.dart index 77df4904f..7579eedcf 100644 --- a/lib/utilities/barcode_scanner_interface.dart +++ b/lib/utilities/barcode_scanner_interface.dart @@ -8,7 +8,16 @@ * */ +import 'dart:io'; + import 'package:barcode_scan2/barcode_scan2.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import '../widgets/desktop/primary_button.dart'; +import '../widgets/desktop/secondary_button.dart'; +import '../widgets/stack_dialog.dart'; +import 'logger.dart'; abstract class BarcodeScannerInterface { Future scan({ScanOptions options = const ScanOptions()}); @@ -27,3 +36,52 @@ class BarcodeScannerWrapper implements BarcodeScannerInterface { } } } + +/// Check if cam perms permanently denied on mobile and open app settings +Future checkCamPermDeniedMobileAndOpenAppSettings( + BuildContext context, { + required Logging logging, +}) async { + if (Platform.isAndroid || Platform.isIOS) { + final status = await Permission.camera.status; + if (status == PermissionStatus.permanentlyDenied && context.mounted) { + final trySettings = await showDialog( + context: context, + builder: + (context) => StackDialog( + title: "Camera permissions required", + message: "Open settings?", + leftButton: SecondaryButton( + label: "Cancel", + onPressed: Navigator.of(context).pop, + ), + rightButton: PrimaryButton( + label: "Continue", + onPressed: () => Navigator.of(context).pop(true), + ), + ), + ); + + if (trySettings == true) { + final success = await openAppSettings(); + if (!success) { + logging.e("Failed to open app settings"); + if (context.mounted) { + await showDialog( + context: context, + builder: + (context) => StackDialog( + title: "Could not open app settings", + message: "You will need manually go find your app settings", + rightButton: PrimaryButton( + label: "Ok", + onPressed: Navigator.of(context).pop, + ), + ), + ); + } + } + } + } + } +} diff --git a/lib/widgets/textfields/frost_step_field.dart b/lib/widgets/textfields/frost_step_field.dart index 3c86f1fed..31364555b 100644 --- a/lib/widgets/textfields/frost_step_field.dart +++ b/lib/widgets/textfields/frost_step_field.dart @@ -1,10 +1,12 @@ import 'dart:io'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; +import '../../utilities/barcode_scanner_interface.dart'; import '../../utilities/constants.dart'; import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; @@ -16,7 +18,7 @@ import '../icon_widgets/qrcode_icon.dart'; import '../icon_widgets/x_icon.dart'; import '../textfield_icon_button.dart'; -class FrostStepField extends StatefulWidget { +class FrostStepField extends ConsumerStatefulWidget { const FrostStepField({ super.key, required this.controller, @@ -35,10 +37,10 @@ class FrostStepField extends StatefulWidget { final bool showQrScanOption; @override - State createState() => _FrostStepFieldState(); + ConsumerState createState() => _FrostStepFieldState(); } -class _FrostStepFieldState extends State { +class _FrostStepFieldState extends ConsumerState { final _xKey = UniqueKey(); final _pasteKey = UniqueKey(); late final Key? _qrKey; @@ -46,13 +48,8 @@ class _FrostStepFieldState extends State { bool _isEmpty = true; final _inputBorder = OutlineInputBorder( - borderSide: const BorderSide( - width: 0, - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + borderSide: const BorderSide(width: 0, color: Colors.transparent), + borderRadius: BorderRadius.circular(Constants.size.circularBorderRadius), ); late final void Function(String) _changed; @@ -79,12 +76,10 @@ class _FrostStepFieldState extends State { if (Platform.isAndroid || Platform.isIOS) { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); + await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await BarcodeScanner.scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(); widget.controller.text = qrResult.rawContent; @@ -106,11 +101,26 @@ class _FrostStepFieldState extends State { } } } on PlatformException catch (e, s) { - Logging.instance.w( - "Failed to get camera permissions while trying to scan qr code: ", - error: e, - stackTrace: s, - ); + if (mounted) { + try { + await checkCamPermDeniedMobileAndOpenAppSettings( + context, + logging: Logging.instance, + ); + } catch (e, s) { + Logging.instance.e( + "Failed to check cam permissions", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w( + "Failed to get camera permissions while trying to scan qr code: ", + error: e, + stackTrace: s, + ); + } } } @@ -118,19 +128,15 @@ class _FrostStepFieldState extends State { Widget build(BuildContext context) { return ConditionalParent( condition: widget.label != null, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - widget.label!, - style: STextStyles.w500_14(context), + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(widget.label!, style: STextStyles.w500_14(context)), + const SizedBox(height: 4), + child, + ], ), - const SizedBox( - height: 4, - ), - child, - ], - ), child: TextField( controller: widget.controller, focusNode: widget.focusNode, @@ -141,53 +147,60 @@ class _FrostStepFieldState extends State { onChanged: _changed, decoration: InputDecoration( hintText: widget.hint, - fillColor: widget.focusNode.hasFocus - ? Theme.of(context).extension()!.textFieldActiveBG - : Theme.of(context).extension()!.textFieldDefaultBG, - hintStyle: Util.isDesktop - ? STextStyles.desktopTextFieldLabel(context) - : STextStyles.fieldLabel(context), + fillColor: + widget.focusNode.hasFocus + ? Theme.of( + context, + ).extension()!.textFieldActiveBG + : Theme.of( + context, + ).extension()!.textFieldDefaultBG, + hintStyle: + Util.isDesktop + ? STextStyles.desktopTextFieldLabel(context) + : STextStyles.fieldLabel(context), enabledBorder: _inputBorder, focusedBorder: _inputBorder, errorBorder: _inputBorder, disabledBorder: _inputBorder, focusedErrorBorder: _inputBorder, suffixIcon: Padding( - padding: _isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), + padding: + _isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ !_isEmpty ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Frost Step Field Input.", - key: _xKey, - onTap: () { - widget.controller.text = ""; - - _changed(widget.controller.text); - }, - child: const XIcon(), - ) + semanticsLabel: + "Clear Button. Clears The Frost Step Field Input.", + key: _xKey, + onTap: () { + widget.controller.text = ""; + + _changed(widget.controller.text); + }, + child: const XIcon(), + ) : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Frost Step Field Input.", - key: _pasteKey, - onTap: () async { - final ClipboardData? data = - await Clipboard.getData(Clipboard.kTextPlain); - if (data?.text != null && data!.text!.isNotEmpty) { - widget.controller.text = data.text!.trim(); - } - - _changed(widget.controller.text); - }, - child: - _isEmpty ? const ClipboardIcon() : const XIcon(), - ), + semanticsLabel: + "Paste Button. Pastes From Clipboard To Frost Step Field Input.", + key: _pasteKey, + onTap: () async { + final ClipboardData? data = await Clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && data!.text!.isNotEmpty) { + widget.controller.text = data.text!.trim(); + } + + _changed(widget.controller.text); + }, + child: _isEmpty ? const ClipboardIcon() : const XIcon(), + ), if (_isEmpty && widget.showQrScanOption) TextFieldIconButton( semanticsLabel: From d831ef4e1806eead13ac7acb46b3b77904684518 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 28 May 2025 16:20:05 -0600 Subject: [PATCH 098/206] update themes --- .../default_themes/stack_duo/dark.zip | Bin 1157580 -> 881887 bytes .../default_themes/stack_duo/light.zip | Bin 1103976 -> 830068 bytes .../default_themes/stack_wallet/dark.zip | Bin 1157580 -> 881887 bytes .../default_themes/stack_wallet/light.zip | Bin 1103976 -> 830068 bytes lib/themes/theme_service.dart | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/asset_sources/default_themes/stack_duo/dark.zip b/asset_sources/default_themes/stack_duo/dark.zip index 8b31f4278dad0f955b95ffc1f518f76b28ec9643..a44c89cf8b62f7ff7e8d27554fff54086ba43cb3 100644 GIT binary patch delta 819205 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ΠXe84%4 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%0D-^#RI2)BpKsjjB>wYC? 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

xw%n(;Hr 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

ZkU-vhw=vN-2A4 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 SFMaT1EeJt$UI$U&*Z%|2y;M>F delta 1096307 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%0A&UGBjr-h}5LS9aJjtB77J!pM>Rj#xrqLjr8- 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�`g`n@81 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�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 %8xLhnvU9?N&l+<3#qR{YfuCQD&oCW^ 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

bTo_-SN`N)Vp79tw(UVP(+eFnR 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

`jCTlPsn|) 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%0AB7M^&vyjmwde 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%0AXC*($Arsya!^#&tQ#$fn9K+!DB^8&S(!LMQV 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 z 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ÅB+ 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 z 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∾*9zXAoiCBF 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 literal 1103976 zcmb@tbx>VR-z7?LcZc8(2lpVsgS)%CyAufR?(XhxK@S9n;O?#m*PDFz&P+Y?JyZ2g z)jfagI#s*6YxiF3x4PHr-3rnWkeFb9f6v+_8vpg@|GU6|k$@RGJDa*VGpVW|fx*CH z@|gWTeKtEwUp9C3Kmhv$dG`qn?7tc-{2x0(_+OnkyP5z0(~*PSf7%f&80g!$3I{G^=*;3OhudH8Ox`n#Fcl7e>33l6- zCP+0r${$a?zx#dR7vSHJJ3iljzc&4HjvRV;nK^OoF)lGF?|;eJoYWw+eSETW^Ymbt zYS%J{l0Pn$Px2D#qy}5UrdxFAcsz$vbgK zbZQegWv3^6X;P(76Dots9A}rl!sWJ$wSOqR%-YcMpsX=SONOke4QJ^mzAe&fr=>|)wWfoYVl+i z-(!NB$+~xV4cL$wbiLZ9<8F>08AuS8B@HAh9UykF(znnxS~Ey$@W-*+Bw29=wZh|~ z^J_42Aa2=DShi)lpQAKKHw>XnAxY~nH=?!Ukx~qQxadsdC5?(WVFt0K|yr$zoobBf)-841@v?3s^FRRM~s`+$2yp^75sOSRC0r z?(o^hXI-u*i_iS!$!>$E@Yi*8)K0U$?kj|XGz{$XbnG54I2hPp9{#^I^S?9H2?7j^ z@}CTK@%S%#0-Q{ZO)cF_0cM7lHl`;330bR^`IUb#qn^KEeW~ZP5rEwyoTP~!TGm=x z|H@YYix?XE?#+eDH>H+&c3^woor+|G4CI%o!9UHCoXBgj(~p(*b8+i96>tg(AmQ*h zTjr3RT&ZbB6xhhPk8AWId^x4bC<&L3a32sz2*X8V>1t_gV< zJ{TvmT~);jYH)nBulltdq(UfGC4`%krh?hT#XIqJP$!>dBZY)!&PvWyh&~w|uarc| z&ZJD@IcGiwkfyOJ}+XNc-ROwYy&j96)ZB`LOfl#U)4FLjWcdB_&ykE_79NWIJ1sy8o zu=Ct2uiqp^hMlF!K_AnD@YJ;;NzeedOYJ=cc0lD_<@NX{D;?`G-Q31}Z~IEN$71L6 zh+KMem-8s9y20w!C>oMMKr|(1ns6Akpz^u+i~2G56=Mf9Mr~yy1E@nB9?NIcfBLR> zaAFAOFZRQvm_Ffu1oJP#|7X3#{wMav_Lg?~f5quP)!_e~Pa}VrhWF1tO+Ab)4DHNK z0j&QChoV*fm*BNG(J0oEP3Cv()xCY+2wbX1YHNwN=|0{}EmA{9y;Z=i<7tv0j4|{5 za9dA*s!P8=?VB;UUmdU$Y<~7yn%tbaJnh4`Cd51LCX4~zIq>GT1bKeA@^x2-zOn1} zRI7pb2F|u$JG6PM&m&NXh%PRe_4WOUTTczW*K;N_Ck%38L&pv`%=llw2I5LH z!*YgT(n0?u46H}B6_ySmpbVyo-V))&{m$n}MFQG6vKbJX3QuMMWrqjsv81D9iHy(O zZc<-uDB;^5lA747226^;l3bYuYC0r& z!ac1)(rQG;)}t$kA9?{j9QsUX)^3rQxqho%uLSElqDI;(D>K*lszKUES}fEgx5`<3 zot&Yo?@rOZW>|nWdB~cK>GslbiP7!F@TQsXAzuA1dLpq(97xWZdjT?^n#MWY=cw}f zHkn#_IB*-f3oSkU&c!NbAJcm8q~Q`W8oU7a{MuV{vb)tbr0f3Yp^;8;Z|bk#u_+Q9M6lw)ng|Qg@c4C-t|lh4XB`p z8&aqw@2DJ>r4t^-`@`C?un-`}5fU^a_olrN3OX?Lf(&&K!f4PUti@b2s7}tYo8&CR zCh}-3HUZ&1Qh$jZt_5U(n%5!F# z>yO&~<>0@oT_iLZ81X;Z`A6;kCqe%b|3BfVt*VgIDl=l&0~Y?B90a5gdUjiAg~T&N zkLxV^y-bD)x_tI)4+5Q>O>>We^d}AU&bZo~k2PfA+th#^|1djpXXe}a1+(DC@+M&~ ze^-?RzD1bjRk!|2XXl;Ahl4*GGE?v6MegG6g@eaygVyI*phMEtl}l%YXp`{v^=WD4 z>D%1h`oz`M(D86)#HhX#)b`$LmeB)4)E5zO!m z4wFyb*yRVTJT+w{`M)!UDm9`JtAtnNRjY`lqGln}M(LPK3*Ob(c_^;wCe@^mxf7e9 zUfhhok2uNyWRm5e0EBnLm1KoR_yQ(Vi}2lL=3~u=bxHy`FbeaiB;hV+;0Mj8s3ABb zF~5kLXkXo{UhUJ00yq^OSLzrl*;;N3g zeNv(Y5ieT?gs9wEG_0s|9=5~D;**kBxS4H0;g;`Rz-xPP^JNfR3#ixnlT)sgNbPfO zgRb4yecyEn&mA0@BrDH>r;$>$E?6~a&``g#qu`DIreTv)HQe6rsI~BDLRes|iqjF8 zawmI-(sORcQy`!+FRPtU7bV%FD1*Vmhz_se~R90 zDf2PfTrJcJm(k1X$=DfUd_)NNVw&Z|*R(dyad=W3pn@{oP(GMAX6XSYh5P3LE$XU~ za#svXWN`$vD3c?4y=BA7r0+Zj)T(Saocxh)>|hoF2nJ#EVEK;9E^%pqPV9vftU7cK z=~xZfDY1&Dc*(a2%79552tND{{ATXoSrC(YTS;`jR3~#)u=PK+Usn7(U*!MXA^Rs^{>MVo+0@SD|7Mk`H0BiaSAFT( zFWSZZz_a5-((jXAzuMyo2Wi9O35(o3BtsyNHqS*;)>f}4pABud1@+m!&>1VSl}WW$ zKC=jRIC)sgf#-mC}=}Z8;tn5jS~te!!}{-?kp0T`ICfSS!%oy#gbns)_!Ru z(vp4xfqADo%TaoC<82{eRX+jT6%didC75}}EtxRHR1?P7)m)I39I8cqB;yG>c9Ip2 zJYsgyhF3HIMN)6k zb}@3Pm$}Jm+T7!vuH>3|!}zz8Ssv#JolF5kZV_9_fgpC8nO@DG+tO)GYe# zEoF?m`wNE*K5Zw$%$R|Sd8j=+-^uq0r?++1Z0EBpU|3JR)bhl&8q?~A@c8Rqk16*525Yr3r(JQxu1j?pmcyv4w8I4}6vLR` zC`ShgSkjsjPRqZn9xmr_BfOY-hGCGrp}z)wH9le@-qc_7{P0-;e1XeewS8dfoO^ur z?dAV)d#yhkiBH_Jxr}`~J#F|xh_X8Q_IP@CRe$DII=6Z_wBsZ2()hglGA0~m@%`ue zqP+e_j@%b_AMcejc|o*M@?lVecDUCLE+KWU@-`87u+nFV+N6XTmKLk&dm4T}$0SN@ z;1KobC&_y5lTzEUn|nl@4lTJ=0H)u|%M!+JQeRqpr^yn8w4z6NY6jM!+!De*{^lHSS ziJkbBOoWhPQpr%`eF&tzd#Zs8U$S^q($7M@8}8sclN2-eB#o;fx&kI5jbz%nbWj1$ zI#NoJN|DSCDiMH69c?8o%PN6+@F*p*FY~yF30j!O^gLWy-$Lc~wdS0WGzC^@`iUl>wM-6Wp#wSp}Z08{U-jina zEc`*6$4n_^3)^w=$+%#6w0WrNrx7=W9cfULrX-6n2P9en|4&NcffOe^<(g5m2!;*V zfva!PDpjk2Tg^aNV1U3%C&rJ#g`)%9XwK&Q)|nqQ&mjQ25F4dVFatG2`Hcm;t?gmQ zW1eO>GNcuP14kp__=NzC;qU=JoAvpn$?eoL+n|ZpvXFZ>ir+QuKY85<)FqTfB2sHM z9~Ua0!d4WpFl>kKj1DrE*(<UF? z(k8RbLj5J5ufg%mF2cA{N!17}S7YJ0P*HUr0BN#+a>qAc72!BGt@^zKUY*~2w& zM0Si0=81ZlNaMAW+HB+658T)T<8OlYPZRIHpbl38AKUZJnf8gP<740D@@kyY9Fok( zN6UaK$DrozR##>T`VZ63S8)9#*zTHN9vr;{{Z<(}L3aKta#xFsZ-$+oUfOP#z+RLo zlvRJChfqs@xz9|F5*t4_jgh8chwt!)w(aZTPDK|E>@B z|J@+kSeje70Br3|O#hRWLv_-+To5yE$do&lEYA$YVlLL%c*o!;B5#;TJYCDcuX#0~ z3tQmQ?{U#{VPS;x2OpFoPnS5PK(E){fb zR_e+1`BFY~*E6d(_kziv|E+C#h*mCxdc&8WpKtAqD3|EceJ<9Yh^Tk{Eangd%6)m; zcY;gB%z5WO;}~uW-ChrMzeJgv10D9tAAT56nQZX+3lNtwadpO42$k|$!%KF`Qc@(E z-6n|~YbFCRtHwQ~$`*{Xi$e9ZMMRZKxFI<7faP{%t~B!#GDDGRCLn|SKBjkI4x+vB zcr!??iXGSmvtSfMDUm8)jWh9TK;a%9Pf(PSJBmR`7J=w@kq2`*n81@rkx2c~G z<~(;n>pef*zw^!2a>Pllt~y^j9&d@ajg(PLBRFG%@ZmdYmhg|lFMNs(xK-l&rs*oe zi+XTc*1@Fg>LS4rblQ18W0Xk`Tth9OWBpV_{b2gPVVE|W97)lnu-a-?g|{U_Ka=@R z&#FBmW+^%AB=CIZFh^N$DmpGz+1x754_1i8W++4$l{PVV)p2+D;t?h^gN6{7N8}?u zF(M^5646S;m!qm%teuF)cTO_G9(b7oy>Qe#V1q=cN?6Imcr=;bhUJPV;lrd^xyya! z(JrftVw=so7udtZ#|f>gh{@c^Vn>Rv?Pj{R0)mk=>SN-+33RjKl?$O5#LwB-iw+M?G=eEa zBH-#@290Z$ID=Qi-SbqtnwD&Dryx6?Pj1p7(hH+OX_A+dlnTTvZFb#X%F-~V?7YRg z9JTe)Hh;=Y+Az2%JjlYgy1JwRmo@QYTB`}*&Nqhy@g?iPC8HzSK5?gagQ*^kp(Fe; zuOKXKe6=@u(e6IFNTiVIcPKr}wTNery&Rt@>As!5$09Sin0$9;UEG=-vAU|k`SDCm z#Bc}ZYx`3jO7EsVd-)=+i`0Wg-d@yoUyaggbYCBe7AaTa1N;5|A&p2Y^6@60cO-Q5EfT~_`)0tmE3pe5Hd^JBi5L3sNs8VGP(C0Wx{1i z>B2AP$M9nqVMvM01)i_C{u^e*4tN?|ojT9qQh!O}ryhlEE4%iA!8`*MNcCXo z2eRZP%CZska97kUy3s`GUuDDOe(1Y&>AM>J7IyOTgzA&tI0AvaD78$qb0MOAe>{{P zpB}kn$Msl7BkjPo#cAK&xjPS+{&(P2hl;#{ZDzxg8_)6TrkOj8e{&058?pXUPnk5$ z6~Q9{8qFl>sWX``Vn*@|U;84TS6uhYV~F^X=7EBy`nyE@hi2sv@n0Chaz$6v{>)5& z!TNU?N&c)JsQ(*`|MU?57f{-&$|mk`qIO@_D)1bJ*)5iIXryKH`a+C9x|zpGsw=y2>|3H_5Ww;@mIzr39vf?8cgLZU$8 z5AR2@Kv!qp-23RK`-kh>dOPIB(--;5`E$2MuKL5V)n8~c@ZU3;as_&Obx;mo-y2SA zH_=APhEF?|x$6h}2x2&g#sLnu?YPKlG~%+rB|5#6LhI|;!aZTmEL)e+LK?S_6-Vt# zAAx~jqLf`Xq~H%XeD85?HD(o)3#^u(j0jy>u9R?-(Z;92%Dxl?1_kM1zFsv0XbWyu zZ()wHJeU1$XO}3Vr0+W!Som$HOr5(MXFr3)ZN@KN9$hrK3QpIL)i@7u8z z{TA=IRKQPTPxoIJ{npoz-&_UziDTa^d%ZpNxl%!brHjk=xrguU7gK@Ohcql+R=%gU zhC5XxSnvnmhrFm~_@ai)?va~@`jNY@7SMRHtGSs>12JB9#9!<(Y&!cGDeJHRk~GCZ zICWl%uq@3HYz0u6PB8_FQf`QZKZL94lC_dB@o&FULIic?m7;eEqemAkJ4sjdM;2Uf$ikO!%KoZM}z50s`iunvsQj^ppzS1?eI^|z%NPMm4fR; zkgKyWbczYw4s3_Z_Gu@yrQn6snNKq^{w`@Rs56;w8~AmHyWP;^hbokc>s7?=f^e?z zFqn){BpDGdeR8lI_t{x(w=o(}$c1m55aX&&kjH;F&@e9_Vt|#0BsWSeE`!>1fS>Y$M|KklPwLd&Ex_q+zJH zV262jG(0Gjsb$J?`1S!knWf^izgk4DW_Og}i1<$adJ-uYSHuiXwdYgQPrA)m)@zW< zgI<(<4D>|Z$#z>8>ARCW^KfL>vvdcBMm}!I0db*!JW1J^RN3KGdj)xUvxN6}JNyjpnJHq0*S@{*O(X>VdId;cB zEF)E(_9M!=q?kkmH}bv=`|6v-EC``UyN!H9DMZ7y$W>5u?Q2ydt4}sMNTy`HA8&># zNmyL+M8ZI2Uep++r?V7cO|w|t90EiyZPh{P3aUTCzW8`qpFw#{mHz<$D*;{a0Nt2B zHsNof|GNal{ki+!V}!o}{r}vT{J&5DUFANzLT1$N2YQCf_F=Y``f{ma-J*)n369W> zf*;UsnqT3N&NnY{jq{S@_(5g|6OXbt9^Ki?8o42Khh;pKzn*oF`g-Q~A1hx*+D#Jj z&4|1!GpP=37gMr)U#(ZHCo2t)h!ac*C0OWYbSL4YXfenRe$l7 zOPl?mrsItSxS!!t!(!BX_6Pd7L{umkm|+d!1x~}CnMfJZ47n%doqL6%t`Bi~Z>RC} zR$SrVy^-$A8-JEB2+(7#aPK|7JDwzF$}9CoNoYKEIDSvDUPoL54#78mm0eE(isXW% zA2xD&e)@NGL_f|hqqz8c+J|*_CEL0eWEd+yY}Q+rzYi5L@+;G0`LWvUdQ^Aq$ff-r z2BXDDY8WC6xB|#cdjQhLAV}A1zd%B3Zp%|MRE$eh$x?5Q-%fI+g8O=ea2>1kqJTz= zxy{JOv$ulXEMJ91vIKM*9sNk`;K}2;d?m=1L|QJMG;yHMidsGf_}1TG{_+H*(^%g0 zXR7$ihJWXYHN$_46&*~SobBxl0hV^g_U3k$F7|-`=u3<9jP-=I7PMe}sA8Q&viI*Q zNs(RQ6H8j^;w@t?6cX~e?{bNaofy)p?J~bit+Dq4Ag8%~pIwaKoqT+VdtR-K zn|_TSyKhW_Zy;cAuQzDdJ-6TNW5^a1%eB3Wvg!N0D&O1f4RZKsMQJ6Db+^y)d%HUn z?Dc&)o-4gm*7JYfe_J)t?`?kQeLB_mdp}q#HK=`Kc7}Idb@Oh!YX&sdQ0}EI)EDV2 zpxw||>o%-MyVX{+nRLcvu9sPBk+~1!Ii6; zT#>KmvGlcY#CPbulbi28Lja4H%^#=>x)*vHr|PR%Yz`%EKFz(o^g&pgL~)!?d}GyH0^n>vbF+D&eI7TVn~4F(~-nzFPEn<>Tm!nBfSv}l$k2HNhI!J9Hy zZgI!DGQwcuo4G`BT^M$LXuS>`$5E}EEz`saY3@Sw%F;cZzk50cEf^f6)0(JRI@4^a zI1qGwO*A-G)IOg}8|ZK+t$-6-6=!O8wmTrm1eh5#g{McfC%o-m3Te9!cs_tKuij8v zS39}C^io$A%(ph4L6nmS}QQfzi?$}*_@EpZ4P9nL>08ki+jle(bH|^vCa3cmOVH$1Rs4z zs~xo8H_J3l_yE?c?xK}T{mfPgwJ}t)4Vy8xTud%ZZ^^}-s~4KX7D@uh_CmFS`F$A8 z4=x_fI$T3WI|6$YBnVG~mMTiU?mP_JEK&@8bW071`UQB0LRiQt8^aUNuCFcw2Whd( zcTs_a3e5nkG+NNv0$x%Lp8YPkSHE2KCsIAmb?x-hEDrr>GEL7?AH1Zev8rHH?mQ#0 zP8u)FdQrToHK|l;rqoQ%J_AiR*eN@67Lw05faCt#y){QvO@pm>GhsqE)&cw`yxAPM zxaLv)!#o<~h)JPqP~}85RLoKF*Ib8si+%8+M3()fUCHqPK5;}_Ha3_B_268;ce9V} zMgMN^#*$n7b~vSxgW&XU#%z~oY3;~;{xC`hE&N-8ntDtEEOTin+gTzg>zS=>Vg){e z5&hF@%Ti5Z6}qn@XW?#BfbZn=Y4c@EiH;tFue&ky)l~5Kz1bJz4G-9v(PbP{ zrY_h@ib(q={Fz9t5Fe~UP$V+j+`1B%$S?E0t7K9_nrJ#2o)fz8Y0DLIMyuRidNtque~QX@O-2LtIRrg9E%c}yy3=B3a-HB zAmS;Egh41V4h2B?@lM*9X_&l>UDL>=fKIFHkK^t0?G8k?-Rp(R_aPwjQ<&-6y`cls zGtyWPMD|~As%uKcK$ch4soEUs^fsIqCEV8| zsQscgSp3`M+OMC<$gh2Y^d~G^h<7RJ1~tRxh=GcjsES#gfHDSAGWC|sP=+#`C|N?( zx6DsR0gUieY(YW0;~~g-0tQJ!++j4~>V{uz^Kr|AlEIBiwHd>ke{f2q(m#=7Pq2>s zE=l>7Ls2z@F;f^d1F7?SfDXzFnohfep^Sa>o9qd05(h3xL(g{-W6z^{61&PYOIXaS zi#QW=C!@ZAd3{Rn%(84rol`vbg}Wj4#pQ3XQ!)lM?Xd8=Eb%`pyUk8S6=iiHhxdRz zn4W}0>!?aC&?CyUaW@^CxjKx46-wh_XWSRLdynJ7fpu_Fx-rHrFYpBcVd4Avd<>D6 zHL!NGib6#3ib5{buYKO%be1e>2>Qs$PiwgIG=G*6jr~%cc?fS>O3KHS`|?2vY5gFM z1v1(u+M%sV!d)+~$n`3bf}CMs#M|SLR%Aa8C}9Xp)Kr;K9L;Zo=BD;RDiIo^_+DXE zD2YB!5BsAZsHO89pJ|0qF*X2$Y?ynF^ed>a5}*oJatN+S40Of1Xmx9JiR*(Udq-I= z7zwU$(4##ayx?t-#o+z6)m4THIn2 z1K(KJF3%M%u@y9j7xRfDI;d8H>U9;}qESgmw`7FgDld-@;dXHA>+D?XhuT#7lRTeGJfVqKu9STg5PS*Lq_7^%Kx*eio6kW?z(;=rC= z-6)K*B3f|NqJeC;0Z<|_gVkpdVx`8wH0hy%?%MC9bW(4It`)`Tyi^eZR3}RDXP4bW zdFJaEgf4=$S2AXP(RwvAy-COk5s(7g(&5~y5Mw*02)}nrWUR zwRpn4erEpaj>6&vcdaWdIU)%SkT z=~*Uec*tdfCu|b?oR{k&PKRX^+2p3(QA3^|SJ9`! zD0Dj|fTp@|ySL))Kbj<=>fcd?F5%WT>j2D@%cRIRCy z=kzwHYlkfJYo93HmjE)1cE}lsK@Zi+a%^GniYg^aB%W^5c-B-QrS8PsfC^LzS3Z-{ z%PswV-F^R08K^20ToDkN7^G{^P-UV&(&e3F%GS7qq!&ype(j}I>5W}f2(Ve!0+^nO z)S*Xz5gw?fYj>q^yD|&g#RtuTjxC4Mqm-Gr4C|m` z#v$4G8AZ1~^S5%>B46Qh&N66tX5A{N_mQ6%IQNEPzwCX3nfTd)4|iTFHCfX(j&)WH zEGW5O+k0?*wN+?3T|E|_JzAId=gdX@6NT@O5hcbE<&Qf>yzY?YCRj@tV`n$4iBto% zi4}K7)RV&tX2tJZZS%@cPACkVbhqaa24^a@mLmm!2_-l!>;!AFD1>Oa5R%k2HJWMf z!775$@(NtpyTBH_w!kDF8SQ_*l#XpC~pd3CjfM_rXnBIaau-OZIn! zRDam?MS>qONS{V50j=LIRPfESz6aLw`I`pr@lVJ%AJs?F48GMV%^e?f2?dM1*0QQR zprX6JzitJKnO-)@vg$(J_#}aTUh=gnB!%XxPT5w}n5dF9p87Ot;A+C@3EhZ36t&QH z#ugJXk|kO&EHtK=AF12kTD7Al$u!O{2f8QRROmMb09kyg2)De!(`YoP>4bmqBtP!E zWoocG6aK)|>gbL?8N|f!l1=BY$*u^NN;i&&y_v%nEwmDzrBN@mM~3+(iYNaROScFe zXRgHgBmlkK2V8%jYJtMa zWaA8DcswR+rZt^ONrd05!xFj6w=yK5N=<* zjRh6NH~eVo0yW3sqeZ(ti?uJ#A&bBD`Imv-Q`C&}Z*S62H%blaj?VTGpXnM3;(I2U zTTj|6{G^MciY*9S!1i7a6)JqW4TM&?$u55KdAZrsPkaPt$gseB2ziQm z4D;(kIGFOu&a8+mfk;2jkPwFTMv}mGu^Z+3U+2lBh>9obuQuFahJ03#rtu9E72&ZU zf2@RvTOIw2Bd8tSXL!lY;?;sp8XG0xwrFxI?b2Q|S-r(HWk zhC}&*oO53M#eU%wY1J{u86nh&)ZhH9boASY3 zZsu%HBZ~Ij`NghgXVe{&GLs!|`{@su7Aw&n>?1hsPgfYB^UD)+*6ZEzV+z<PIK@NFN#e3FI8a6og=`uB=EGq)&>D#8>Iz%yIHux&_3 z44=`(DGg8EpwaPjV-0a5QE_Myp4%;vG_TpbxSNJe#9CleAmzJP8XTn=zwL0`<_*f5fZ_Z#x)*$cx;)URf*N^rgmm- z?PWeH``kiE{aUio$tCFV%lIvtD(8XiNB4z;0NCrVym*1RSTO37(+u2x2Uvi z503^zWxL9x+!!W^MFyC4=7Q{r9-<+*dYDm85-+YE<@ogFGBv8j`Vxw4cNz{D>&w1G zCWy@~H(OBOl6<={7VsM=CM{kdp)e| zEKD-*#G3e~#Qu3h48*Iou;R6c{u_H#nU5#@qG4ycyHoCaDlg^JeR!;+3FcOsB0!N+ z_ILHo&P~coy_IMY2m5+O}tr7}}=)>haEHQSYrxu+h-t05| z^qs<0QiwlcF8*LNivdolF257cmNu9wD5Ysit(~bQL0*=f+-~`-LT4G<1Bb+^S%b2J z>;|$-arJv*e=?001vnZ#%UHt?`l~K)c{Fa)+a0T=;=9EAC~dA7PQr+QjS$m3rU}%q zlXf&KR=>iAp3ym`+g$M!>2kc|(s4xEjBb9fH&>UP2Y`>euBL9!h>Ac{z)?0_kn(Gv z*|7Gm73N0A6yJd3KuSANH5TyYvXiDd$G4Upl^>|5eO8tX|572)M!v+Uz8gCMpVz5pR+*4>BD3B`rK*}O(I$o zG9mR;Bygln}Om)EyOq)uU&VlTKoS?+f510ir zgx0W_6G)hE3Q-u_l1?;nt3QTAoUp!k4sNDXQA!ANv~lN3cOZ1&Yt@j;X{4nExs7hh z0l!^K1^z zZ9ubq#!pERsY*O9Vu6ql&MCl%MZ*>fVMS31W25Fk#7;teC(>e) z8gtQ-v+aRh2xtBtOvv2?q0PbB1H;T{eNbbmx=EfD!(D7F5^PKXlLw_wB+&=a5bpM~ z-&RxNZ!jKrJ`Jf)M|+7sA;C9(Pda5h;>?8G8#7w9l?Ikh9MXAgYeSr+`EC*V+Fmse z;xUtTVkBS{9S(9<2{##0O=obGbMtLqVw4B%_Quhb{&4B)&20?iCY!zqo+k9^0ux#< z}b>cF)L)^DQOa~YN?orjA}Pp^8=f9^2c@N%gy@z=9sK}+wtc4 zR^hhWZONhA!S0uKXtFNX{?^V@?1?>U(TdLFUL5tf%$U{9M^|RQ^RU*>?=SrXW7c>f zAb%(QKEjoGm`TaJVInw%o8M6Z_&?(@s?Xm7v%5k$SYH~ zvD)wkw^HCe;7!1gq$|L=#fkem!UUrk-Ulh`#3QBeFjo|QeKO;8`_teMU#rBwyD|7ZeY|a>^fDKv6tq(C z*+#81mTIIcJX0eOqZ8nBN~9QHjww%m?C$^sArdBZ4r`efpYJsUAjZNJ+Ug_Vy>QDH zjfixJe0H&U26s7Q3!HPb{qlL{*g@Vtv!@cq#|%kHI{2i-rzmc5*CCDuEdfUK!0<}0 z!9lqOY7doyXlK72Bc8;2E%}AbWV5#C7wB?7ydAx5eX%y4qtdt+n!QnAYApBEfm9qh zr(qnXAsDXOckV<;%jZV;?&kJxh-Dr||9XgRUUt!Sm{P#kPj?^K>xo9U)*uT>8=)1x z_xe)gL$=l|J^``OO>ugI1jwxc4VW$VQl5&tA>h0Og)2n0_;FJ=nLp2D9R(Y$qLc^) zkY#@KiH>XmWAnG)CvuyM1g#}M2AYdX`1c;9hb#35!C^-;O)(+K>=Chn1rByZb$x(( zvP7pW1C_gPWS$dZh6$c;!4cwcyCm8`-XO=k zSmI!n1swy4B@owlD$#$V6P_forQU(31PYexk>3tPmA5GvlHW+_mD0zsn)oLjG!-yj zmxY;-CfT%M(-HH@wQXgDj`IN^<=2Pu_CFm@Lr+A~HvO5P{M*vLE$g~0N`+1*Wwp97 z!Qe9SUiCS<8w*-N?XLhJmzP!U>g-|4gLQZlag+~nHK3XqK;~JHWL$c5qOEP*IPLz$ z4HBYX;=0>lI{7b%YIGTSX;G48EznzOG)`i#yD;3{;#%U2i+49J~=ebsRcclRW z787xbgIgN&OAkCVueNSt;63Rti1|_Pj)#)z+FKAz1FU$xdXiw~Ng z)>Ctki|Df{Wkzx$6xDB3Vk!#RrTQ6ve;+|m3~&Y9r4b}T2=tJ4fQ8`nXJ;H-Rt85{ z*Qiv~jog^{J?b2@K{0?CxR<;p={`I3`>Z%QT%&7&fNV(#&*?!u^j_cjDKwv~z%VOI zL8wPK#4v#jG+d&}Y1ihwt0<9UQ$Y*;p-ourc<`UE8JButpusk8TRZ{XSJRqXXzLi{ znK9ARJlXCxF&0isPe*>@$tg44&MhIHU^1LOI$)D8wpSD5(gEVd(+Eh((X;{_5A*B! zib7EDK3?mM%3$k~j-P0TjGUAEfs{Z*^_QpyvslG%HvHw2o~`;6et|evP*+XuSeeRS zNuz`-dNCBn*LduGfBH@$)Thi>4y3({?+o~#Wotok)tdYA)A{k!Z4hBSXmUvee>h-% zz-%A-fBI`M_9Co(?-9Vj{@RFtHyA9)pTIEx`Blz;9cKSezNR|wmThDQIu^HI>MPz` z&2>+k4!a+uk+3yTAmKn|4rv&Fk4BUYgp@&*gdkCTe%L+aiC0bcBn?ndUjNMw$JVpY zMNYmuH?ThN_Nea*n(FO&dmq#Hdl`}-zG+|}w$t}{->>a`bSr&-8k_R}Xxw}slORr6 zb(+hydw;3zc|EC&6?i>p?R|P3IM;u_uH5ti&4e=byxqHhEXw=cylj5FpFixMx9Wd9 zQ`0>sKK=~teP{B&`_tE*>?>$K^-sgb+Ke9R)zseCqk&6-mm984M*mA{ z|J>QxkDit?4&Pf+0HAy5(m#5$8@PG1ZU5X2*tcC5So7njf4%H|x>>dOCFl!!TKu^D z(|YLeW6J*hg)8?IwCVG*y19Pq@Bb9J>36qUEBJhc<3IKx@M_}!xT^nlk~vklc|6d* zHpTfS(Vm;7UE4cu_jb`}-`ggpFK|)a1+ebEYwoty?rpX0vh`dO*WO%c-qbp2onh;> zX0!(o?Z2i-b*FZ8C)W>Gu4+%*r8xUnT6Z*;(b=v7qVs@lcSIleKJw*Vw&Y^2r>jc# z?BXdQAZn*v4%()`)(uUkb*Kdty8Yok6K$m1N1QWix-uj1ZW`WIcVS z_N&0uk(dMM6Qiv=rXBN3JZag8Y*ni;;c?G1+_%Gi*#G&t^5Yq2vpxNtpz@(zTv_@F zAWoX>*> zw3x45y+G?-%dlYg5Z@8K(69{>AP9S`Q2d+)5INjion1S0``fg$w3^9&tj)H*8iHAeKYW8{!pB~v2}@$C7bd`iqgYH34U080r z)6B#05spl)((WG~1KfiIz-<4*6C!O_?Pd&+Ekiv6mt&KL;Y>&k7LGQ@3hL_dg2b&) zc*(HYOw9RC>}iE8jt|EXK)mW!0x?+4j6tLN@;NVZ2Uc1}(LR=2!AN8X9#J5fOSSiR zD+dsKvQNU8QhcrnN1Qo#dF?RgB{CQ5?Eydf<9gn__c8R;;`i7)MraI*9SetcRWN|l zZ6U@`dQid$(6q2y$YOdd8H1fg4OBRH8NbC}bv?bduZzPiLI;Xor5co0b`k>zvCmu? zh`Jv~us?2bksQ~H?z|Y^kGi`7nGd_OCxz5)jVruTk*)-p-Ba~atwbWd(DvwTfSE7> zqw>AiX}Q?O<9fAdXE~OU`kxx^#e;}pmq2*`_wpVXnzfAUKE{-+jZhkn@tBrHF zh&aTevOYhfeqNn$S=M$ zzdGMF!69VDvWvqncu{mvbX4AhU1%~yhCFfWS#->OF!4=iWymI5uo%@INBLuf?6Jk{ zi1Uq9OovPco%MW!)j`MVSWER`xWvGW9CX`RVbHGa64(V}0X zLv9T+mTVqDTC9yd_y#rKi#kTv?_fKR5FU%hqf3ZMNpy@uK@{(0KGzA=v%m3tRn^p0 zzcs8Qre~3;9mAFTC-dLOtB8t+urku};3N+bafJB0_UP`A$gn||s>)&xB}&GDUPpWE zFRJrH)eZeo(pHEaBfeC1_O&&3qUloA-x%OHD?>>2N1m@nH8pl^{9fbF`l+KYxKUf$ zpJr#>BM6nj*6C1h~4bv*R>XfK4dcBF>U!}+D zeF=$DLl@^r6f7}R$pwoftrBw{!luR`IBbaRF=CzWzFv;1Qf44S^oXire@S;3I!am* zUG*xmV4S%@OT~d66o0;}n$p7JsMHj)Nt{_drghVxhOmO{v+5L4%?rwtbVz^c^|Gpp zJ*sm^6~$=AUXt9o4by%U#X=v@7lJJ$@uhe@_Qu*C`vYp~YOdZ(+JtIs2w0E(K@?e2 zh4{Zc)%Y!H z?4binN03IC>SKRVRmARY{#N`sG^;pungjrf#S(0+swARoC$t`mcIDyoP3_7pc7N8c z3_cONvd4_ADmG%)LrUmU(sF!bwR))*Y2(cIG#rbL4Y*qTky9*Ib`uMFKGG6o1JKt7+pj z?P7|Bf*aEm!;*9a)FH_v=rmb?-_z#Pp&pWbOm&Mb9~0AJAyY_7c-1qR26#Rs<<#ix z5ck>NWDC=(SaEtUCCUY_gGa~4iKSO`>cS>sZ9*%PfR8+$Hm8I zSb{jv&&5wZi4VOY4r@f>BoNIeIF#hQCW;4=ETUkrv&97$9ap7kM`)x%KaB4cEp44t z&sUk4q~GxM;5b>#OGl^Z{ShO-p+3)XPv&_gHxF!lY}LsF3ruE-Ar)lk`6ji*h7?Dr zF&xpN8a?#f@OKUh4?bV2q4yT1;w?jF8KL5ga{Fp5vk)+}CWkoD;a%0V3>ds#jPXeo zb{@i_24CB@O8#l8V~$Bm^D{Vi1UdYO4?^t-#2aS&->D{{yFh&ETX zOKp+~f;Ps7ANvCp$(p%LlVleup2xO&frW6QZw~FF8b?THk;e9Yyxuhbi29fiEn(N8 zy(aln%OPG3fyvTo?hIbuD9?*5(1cLI%&@XAh27ol~BW(bN-%J zJ#^&%{S1A#vl z3}`Jn=t7~W=_t{jv1}RB+a!ar1NRrji9#_$YDJiru-jdz$-*4Z;w89OG&7`z5j8Fg zib0(sZBGbbT3kIQU-FFa1mT zziBDQtW9zYMmO;%ipfSGF*&wNS|s;i3WjbvMV_y!*Lj}mV)n(wHWzCljAY2(ijR!Y zS#>BfJA}$DLC<1sVdSQ?*(BS=ru52I^no7iTp#djs-S4;^^L<)gcM#$&?|KJritd%Bw7O% zrGsJek=M(pNlC^pH&??Zy|JP)abcj>ICW8pGIZrLev$EzTEg+6%QcKhYYc1kOCf>E z5Y=n89)>h5(Jwt-uWELxR#wCA66GZihgh?=X$6f(S~A*+F(cyUEkx^8!}NTUp%IIa zqQ_8Re~}(n7|-ZBS3sKu;3NTc_)2I^kK@a#DwK`hST0FQz+hrraOD~xG~qW1cxjbY zEXX{&y}!xmNX=X30Lqlubz`HxbK%%^^ypMrH1ZqIJB{;;%+bKAKUHGAwCz36d0eqi zF6fnForOwTV?ySus-`mW!@6}#G6QNGmW`o!K4cWt*)7;Yu+E0XCGP{aN{<$UWxyzh z;?Dc5>X5v&swH5&foUMYNb@8CktZJ zeb(xa%GA`Sp7kus6hy&Vy!@g}tWK|Z{;Z|9iXn-2Y`!w-Q%#)@C_;NQ+slS7p)s#I zAD@p@j0=}BEewP0)Y*kG2}@#a4V_VocrA5g_>13z!D7_143rZ*q{q4q#Zh!+9U?(@ z(FwZ-a%OrQU&bIo!#WjhQVcY|U2>dmg+saJHdY#D*19t1+5DmTs)kQ?_O3p~zLC9S zNMnQD^MI`qje=|FwzccGO&@9HD5gboXQRTXS?>t@gYSMhJ?An zqg-@u(HLhRM?ogdUW!g??c@|pNA2BTMA|`(l=!kCy2St_G{czt7>SZ)GM61Rn9w2} zQwk1tQC_q~6k>w2B&&EgM%(^P($$ag@VD zD_ryw6{~8+1|NSLOR|b3`$N<1=A43N4WFJrUq$xPEpt2*hnfqZ`UImAErxZLOPJnNoAIX_Ib`uR!TcB@t4lC&dy9NJ z@^ro_9lFU^NOYarRmv{k{CrdOqS3yB&*;7odWFtQa(T_Z=-{)aUA|~EpquG!FYotj zE9dg#^tmN(E?(W7*?3*RAP!`AcFl~{wlFpuoox~a@*F#jl{!~%*a38jqWh6m#bsLy zr7{FdMp_rRp%cnKWcaGBYzRnM>rcjqEh85s-8_r)#n*eHQAylu_$GB-^V}D*#KsOD zni+Y8$$T8_iN@rHVMn(~L*-)`)ocS1pO+a>z9IB9PVYD`abl?|9LIwS%l1#@I#YtT zXi=@Y7EW06#KLmZB9o>g4l6-pJ}()Tw{VS^GCn-Ivfb((RVp+v9SbXM$^7oyx)bZq z`VTtm`6O=b!|B*_tjfDxv&o^zX>aj2O>KY*$=c2`~ z)jXiP+=xW$-ciSQPy59(bo9~XM~9x*&LLOoRyEf&tzH}SDAOwD$J_q6;};nc^bMnb z(zoRIafhr4vdYs*CQ>OELk81H>k>=ii~JhPW+tHP6&CxJ8A?f@_#sY?su|eg=rCs$ ztMy8~??2*o)^B?An$5alXX$qy=eEtQk}MI)uS;8t*QIQ+7c9k92~hoRf3Af6f3bhp z8heuaf`Uheyi0W4q}YlVp6Zv=;MQ!w+)O7Hx)!1&%UC#z zSjnn}LYK@!Y7qWbbKNmEy?c@BYG2y-R-cO)dXmM|GM995X)`g=em-D=D?Sm>z0C5y z_8Dz%fhXNBbiI@>m*@FHr&+%5^zA$7>F#j9ctYGxbi0t}(o}S$^Mx*#@_jxprmy5) zeKtMzuP4*HLvDHdLr8Rn6(sVm>(gvm_oiNbrTiz>YfCJF_k?W3@(Jfh+5?Wv#KOx38>smT#3> zn6-$t`9j^3EB2;4We!<9B(%8(n@?9egKNLObe|IP1kM^!ErF#Y&&vr(KFGzE7M?GcTeK9BQ}k!Btx~xNBZO@73;$5K$hNk=FcVkrMyRxLNW$O*&5T} zyVTcJymKVVKRC{6MFOx(Wc>;8SF{IbsOP~Q1U+r>-nIOp-MTpl&Yq1Q@|(G40_`;6lye(&HC>(w;!PYkn*@D-Y-6jw;!N?Wchk2UoX$gh0d4q=f{1Wbe;5G z{iNGozMFo&KTMZdKAT)-b=j{M$6RkxVYp+*1^Y8svovXnGE4^A(&Pr`=C=&!`U<~SI6yt;U{LMtyg9dX~~5i3Vq zDT}hJQT`@x!J(DZDnhRwXKir#9%#5%`Q5B)UACWY^j<=5vy0MLRsC@1qz~J=*mTOs zS3zENH-=V$fU6_n-ue8V25vg`zS@4b>rgaKf;bU(m3twLh($-^)h^+oZJ)vmpom99~d-CwTSGZG=; zM5bwt1+7VwpJrx7bmAJ36@%VltmguKEy$}2H=aFbf9#9vb=M7}VmKGOPi;6YjY%Hg zwZq5BH~XCv_JYy1w9n4iH8z&aBCC`>IhHQm&*O3qeR`iY zfAQA7I;+b~z2j2MB{rUq{U&2k!PV*XK9_gJZUtS_=gZ;lJ9pDpPwcA?`00J_ggZjE zJoY41r;IULQf=3+lvlVsN(OgZ`?6=F&W)S%KJjmyIOy`r{d_=7RZ{izF2b-cDLi{7b-rjOhy5^`R*Gn}V+AJ9 znb!9(6AqVe({Cg1&%IL8I^Uo5jZXd5Tdfnp2Q9Tt&TV71r&^6GX_i;49p}J&PHbc> z%-J2?+-Q{6>f-2>UG9Gk^w!m#Sb_LxNJ{aF=mo>qrmY-XCG~FaqL^|S z#l;#V+9`@&qTajkqTvhVn3E(<2;C;Vx&8{dXlsaUR)RK3ihO>BHfLf@LXSc75;{cC zo!a4>B7rtY>}cG2xyunP!B}@T^hSe@isd7CbVuxI?9`dqQIZ!WF3ajCZ#xO~y3_Bg z5iiQrxe6y^6L?O)}Maq$TJf`%Myefo#&2C46v`m3O;tv9T!3>}n>*j=XMaBKSXzMSu`k%QL|!3O(lI0bZj=ok6YD~SJH z^JN6?e$M4=fnG#mM7xN!PxYa7J2ltUj6}bCRML<**^}AL4BY zrw6*@UF_##pLZ@Es=Kq`@~jybSP+LPQ6E?~--SvZzwhwHSCHf#wN>#<`kq)Wv5tzM zkSHpp`Wh>#s{|>YQo`l1r1J;07fVAONPhf-k}V%+qST7k=jr1(1YRO7uOXGv-DCL` zuo)Z&)ho+2L!aKKcjutXckz`Omm-DSS;_C4Zn&F5qo7ak6B2k1z&yuUDz36r!qrA` z97&LNx#0w$d6T$0;CHDtuM- z8tY5=>v8DyHhv5^&`4;kUMN^GbcwB2Hb-3n6QoYmgn?icC({rP1(E6gK-R+;i7Z+{ z4(~!tahzKS_TnBHe=M%py@6Wu*5w5gDMvi^4wc=^{Ze8hlhj0Rctzz%T&Xb zB-|eRZ4j$;jy#p02L?lVBgu3mAPI~U3sGFf<`cvk8LAYfppZmu7A~W0? zp87^?th}#eigVx+7unoU7yJa})|$9%7s}Sa$#}ulrD7s0h(O$j0}95)HJASaIn!;i ztf{)pmkwHPd7bP`qZlpA3P9!ZAJ^9DUQ#^jT(=V-c;mhqr;YCG_jjSVSsl+ZUT0n> zBlfVo#g{oZ4$!I4Fz5weoJwEXD4SJitGO{-5x?g~7sy;?Z zZgWByYpZ?khJ9_;6wN*L@f-`EmI7vgS6H&AgH?F!;2qSny5h~CiH6~xR)$^9v2uP>~W3O z5@C3(KbnVr!!BNAI+NSsqO}&xPeG37;hVvQuMT)TwI=0KCyRfB=R0gvE4evxMqY=p z8}3A==*DSJhvE=E#|oC*HP*ku z4kY#9=tg*J;xtP0+}A;>0Cw&{s97!?`qGAN4C}qllV&TsZm6)8ok!*ZMleG*Ubq5x zM{QJ2#ubKHF+zhwAeRf#3i+0{D49jKq9%p!SzriDDJm;=Rv4qVL{hH-$7yx~XAcf?Pi+eM$QZN*s&RwfH zUnM?-hjlg@hlLjzr*PRZVUC~oBGi6q&A!|kxa!@0(e4a z*3MWMEg4*M(HM$as-G<^Z*f6hl|vyQVY*{ez!}R|rW^KV<9Wf>pg$*e$8p#m=Ux%p zbVS~m>%nLX3;ID_`Fb|A99uDi16o@1^6c)IpjO!}>R3TE`3}gA$_-?lmJGFWQR6DW zXj;4>%F%YvGqVM1MN`~?o|4)nEIFWe<)*)alELl$u7w7_T!^YWb#2b*t2J6e-n%Fd z-FLrQ+Y%`0>;>h7Fui_geZsC;xsl<<9)tyY0i!wf_6lHPFdJXc$~tl9W?SEvK!FeM zW?lftnQ}JIB`Fj7!VNuacn^&UB}hAi^J052;Dg=`2PJQ6r7k{|PRG00h*uhk9okoCDG zyT!O|eqFk}->)z``5ZNHUl!@eS}zr;#?fG>dA%ateERXBd7x3W_e!oXnMuPvkX?vTwceU9RK{>>?tpH5K=*LWkvW< zfA&m)p1k@wt7^3$I?pTg${Oz&O9ZC8c|&W1;f}RV29VeyEO9NTZjQp89_z`L8=T;o z@!1>Xnk&xFX*3L-^J>l=VF2@o4(l=5=U`7{X0n1K$P5Y-8utmUOR;z)K%&)v>Y+W7 zX}mByU}GmlpgSBgHf4J2y{W_2dtk1x};+ICt(- z!>27%J+SCe5p9;Kus&&>jZ+knXd)YtcO4>^W}~nDwJXIj+T5iQRdnTnVAnt(W{Gji zDF|OHcPiEQ~(;#wAuOh?1^E3%JVbW{Lx2iam$}jkrjp0v2$H8Pp|SKW^WF zGK^aGE*;D~o8}0{b%z|YF{lgT0UJWfLSq*LP3ekCVq>y2CkY4Uop2cPXl91>lL>=q z=jV#YPxc5DFF2pq8TAo`VcA)m^BF9a@)mbwBxqB!uxYi~EAORzQPMIN}tJXIWrmW@s_1 z&_$PKUqS>s*?Uc{F~w4-`RoOY>@;*7J13km;wI_M3MubAmV<$@GER4T1@ibV01Uc} zLyR_%*a=sRBY~x~ZJ0he4z+?HkMB-p=>$8L@d*+iFQ)OCk%-&n-wR4X^3oK2e&74$ z@PbbeD+e1At&aYN{oRq*N4k0yXz7>fGS2hi=j)`i%jcSo)ep`aEirGrjmw7Yt)gRV z>pqRys1n_#fLy$l2=-%>10xsb=kStm_E)q*m@Etg=Nhy4Ynrc+be3?tm5;%y1oWHc zty7$b<3(r3>P4n4Py{WD1MOx_3Qrf-OHdRW&*~!?zd625D zGi{n~wPhxX+vEe92}PJTiVwd&rjRG5v_fxr^1Oe0r5IP^fGKw;QAZ+Ddf@ij@!M0N z=+F*VD07hz*+?TIBiXc7jSZtb-b(TzM(!%O=&`{;?omC{_SO3KH1XTiN4%d+k24F& z#PE|`NZ9+>h!Gds3r3Tb`&_wsZgmE6zVPrKm%gd9r{*}^u-kIB&iW?%axmk%T5j8K zk?g808UXLg#U|{i8z2E~JuMTyWFyImI)@L2UYFfxx4d&z0yD2#dZ*bH2Y?hoPXNo(l^S)L4OsE8$Xw63j!pGDgq-IO1 zroVEtw-nykC?(mxmv#*4BjTVXDP7amd0ovh&f#ni0$Dd?3*o|G-b_d~N`T_rpjDr| zo-i_9kt)vkniQX?6@ zLs&e1o(Z^MCthI^6~Aqm#4YVmoGRZZeR`h`o{<#afhOW_dmCdj1g`jm(g$f{*pzU5 zA3&lbtl}M9BDtWfPX7b=Tq5$Ja0NBE@l&J&rB`BC2d+_3yxVJ6pC<;c=Vgz}$Wj8& z_>A#Bc0YwGfU409;YpB){1N1s&>ifLQ*gt{5Fh;}mn%7X2xM@;LWATUVSuL4uaJ@W zj~tt$tUv%EfrB6q7dh<+vyfH(4keOXTt!JO5*|DD3@{rAi;(XLcp}d1@E(ft^lgRQ zTu>(8!AZ_TQSl2P#@i88o4+vm%)Ak4il~tRWK$$6;eCbV8qn+X4j}!T z1lwU++ZkY<m<{KF84EiEsx*G1aG}xa9wX_x?SjcDPJzn)0xILEqY9PuW!<2o%Cut z@8vhshT@S6#Le-OZPL|r^P-W&3*v1;DO?0L^?1{>C(xCHR(Rvp=76^$EV&N45`20R- zK1V>`38XV9u$h^lv*AdIb5O@8Ls|Q{xt22fnPGR^G~3y(PK{8PsFgUr(9_^Oi!5N>?lMn9!k&JS#b=JX< zErwH->xJnHsPPp^`SkvTOrCD~Bp(x6bG2W6Gkt+Keut`je1FCrDsWE%e*H(2oSCA0)+4ppd7k~Gf&p$IPyEg3>8&=__{nn*H93JS_p=dhfG=vPVl zwNl)&hs;<~Lp3EtLkK{tI!~J-%ms4Ch@K#x@6gR?9H{-GHA6B_^hvL#!NL*^dWR&d z;pZ~~qLVjuBdaBJPIuGUw9YZ;VtP`pt?5WU(Rn^^lRlHWPCn7=?FZ;f`SAngFZFMi z)}{+xF0CKuzAk%j_OWnt_JNuMIqA|T?QeIPzZZi(od$k&Wh2e<#1u8@11{g^^KI6@ zKR!*ugLj=t^Cm zt7;H0Iad*&EzNg8qFL2aPbohWMo#A&v2LQp7Tc(kjWb9~DVx>m5Rh?*M7RlmUuf?V zqc(}wWj*DMJinA#er*%;e3qY4K@!1vy!!FB7q6z-^T~&*sweO#8RSV>k%%hNoyH1n zm|0)=m{FJ8JKXm3U{A*V>aV%N=HNPFff8Y|iY-F$PF#1oIAOrLvndQ8?##)TVPZm= z*gx6Shlkq-#}VS)?cYpqb98tt!EEv%#d&H)%1)hT6tlYPfOBJQZ>UX>3d_`zR94q{ z%5+Sd+0U~_t1XjmrX61Xs;-uqs&YQ=``kX)!s9Y_pE_;ZTzsooo@l8N3z^zxb2Ez- zcn4@_FI_f9bAcchKUw9FF}SvwHnVtPZ?kTFT!EzPEHA^3WZGrYzzMAedsXAJ!C$z* zqcc8Dn5g8)I%Q5~9V90z=bzORzr)~=B{Gp>bKsa!4Rt`*_prze0w7>ZgneaW4$DV@ zc=3#5BZe^cNp6n4lRwXVY&0QkzP#>r+wBjGU}s>+`@&@%a^cX~*Uy=QYoU zI#rfnVn8!aoP?mt*;jNil9Z$MEGZJ}r?W2k>Pd87XL&~kF4R_h(rpG*exLW?xJ;ZQ z;V_tnfsn>0r$Q-=svrRqypUma;?l^~VB_l>0kFeCnUY)u#@JuxwwM&W%#Sf%u174r_`H(vVwpuKCE6tUI zU1#=*WOr3kV_Kf6^gjD@;_@nJB_3fR7gcJefOC43EGIzttbyN-w0}VE-?ca0A8N3I2p7NE{_!zt%S?CbIy`G zbT{1^fxp)LaF||ASDROQ?k+E(eM~nFE#W?9NQl$CVaeKC1 z;r%6h8Gs>CN#PFN3|def(tKQH*Q_nCoG!Y--G2@Tr-;OMpevcxo2yRjOT>msW(eUq zm@yb76mXQeV9~7hysF(?6)BD^7SUa*^2%6U z;Jh%_3yVS?M#WewYq{pE@djfN^4ziKc|v(2qZTeyM0d`YGEM5$0T(1L@jx|NC*9m6 z5#MF8W?c;xmYj$hdejR&_xrk&vo?QiQa#VgXItuKy3Xf$(#RPFCgbOur)4&#aTw~X z+`l&GCHeirLe#W+;q~N+=zg8M#piN*yr$1tU10t=m=(wC%T%eG8P;=2M%$4=axN*(`JsEJ+;u?MwpdKH%oLfmV%w6dnl2s^9V7@+y>JmVgjHC zG-1yqKJxQnMaNiE0y$_?;G2n&xK%ySfae_(C*^bbvgR{wBiM1s$euJiIhXeY7vcm+ zfX#_+o13nUN``oib~09vPGA?$hOyek?&Jlj(9U)0I1}c|+h-Ai0lSGMB0EZFatNqC zXJ>Lx#rKr3V$AK9+>?xWmW+%mCl+ub(q?2PT?JM5W;Ga1*>xuIMY+%F9!2!(iEI`p z7gR_=JePeW*%caoincP*qd2W6P}xMgD##EM-H9~ue%nx6M0UPU*L55T zhUV3DYmu`32#d2!JDujomsvMV4!M(7s#Y6NbYv?=V8g=E+*e&pVsJ51m5w~6g;)fb z=e*sr5G-r;YN`fSUe;_Bvt+P|b5<~aF8L_Mj6V$^9begT+byx3FaWKVr5pNanex&C zo(FbP;C6hUqnnUzS`}plRA3VPS*U1~o;J)=60^g&k*4g}^l0kXys=g*HjDhYrd&BD zz1Sw4b-*tedyRG@FE(fkl7!5vJnFyBhH;0kHjdytD;mR?9Pl-i!!xsCQN2TNHmh@X zEbB5wN05Qk{IMhSmTRiDJC-k_885bX%7FlSn&Gl-e6s3d6U=U{vUD^*FQysFBb}Se z7b_g(7J%-CVH%T6uCC@;y&q>=5%X*v*f=63h$`^~b0M^k#6{g&lUu(UkGrI8w!T@P zu~{%%2bfq5TE(kX5&~@AC#yTo{ag&M(Y%wWZrVEtOw%@)wiARH8f1G(YnTy>-)}yz z7TKxO)4+fcbgH50lF{xC$;wE^@)6yAO^LNveoe(BrtKBcP$Xlw`uK*PrRQVGmCz=o zGKg%3&)URo__izGn5cEN-F>kMP;}X!kNJKzEn(u&xUClt)J(FNU@zAMfX8uuWdT%0 zR@-E`#fW{NUGahL=klz$1AQg)xwv=Ji}tV`=r+seX-KZOBaNHokxuzkzFr=;GdWI$ zn-@7qX(?_BscmPjk}V zlWoVLO5Pbet~nO?b$BOq=ZijD+#eT<{N49Trfs5G7B7A^cb)WXKI;F0w!Czp>zPKm zInbDVUUUH{>p=HY@v@zsf~tO`ZL@v0wr=Cpdf+gQbUPKt+v`Y=^-Sw#=0NvnV|RLQ z-o(gGd+R5i&yRDx(CfK)IX^B}x?YNp^K*0MJrn1I)#@l7*|2syZCE?p6T1`@qu}A9 zDSD$H18f=zF`Z!~mVnEChD~d3MW!KfmTt$T5|-7@1KAjALY6IM$5O2p*>&H0&i!dX zLoqF`_<v=W5LZhIO$JWCR1u`D72P0I5kLG}vhcNs`8sZUSu&m@CW+nT_7zR^dd z+$KD!k3-U3q2GEX-Nqur8p|7PZGOy7&-OM= zWx4^$;<38C_L?ps+AOb`7QL(oS~x1RejW3o_u?k^uTi_OdYVgXW))0_?p-`o#c^iO z#-@3++2RkKrloqgIv+(xdc7vy^@W50wsUn9d2;NZJjSr@X2Vm1(6&yy#RNSD{4=}t z3ctHuR>3t<@U$Wo&jhw&As0cB>OsJW(rHWfxp?AHj|&eos-xt*MAR&mB{*X9K%8<9 zA3sboT^!>Ix?C}knF46!aSZmDZ{y?+hYxHb+q!VWww3&JII75D3Y1iqy zcRalXR;J}kXzI#h(3fzIzzJJv*TnY(nN{#>&C;{Mj8deZ5(6eDg^;VDV*9mt_!(YkK^_@_l~F& zK(IAH`pY*Wi%Mbz68Ih~go3!{w4ge|_XAZ0L-WD$H0U;t@uuKeAU+jx#Bhdc zv-78>UThk;DkpVxZ|tHh{4bJ1%3VM4xXNtvE>rkv?8x_gZ2q07w2Dl&}mr>_kntDgAoLiW+N9 z7AQ7Av{JXzZ?N&aPW7n}dY_eg17_yX$4tHxLLmXdFY*b&N&m!*9v5b1FWqk3I{>AN zWn1+gYp~q6D&TN_M-0*vf)>@f1Lgk1hTtPzw z2jDz(8p{eFw0}G&1sQVX!EP4H=SltUkbz5vcNsk!plMuW3;i#XxgAhsRolSJbh_kg zBKgzDfv`L#h?l>%GxACZnrpEHF0;B(Xmqg31)uCP zmn8ONKhp3FCbu^a{zSAW-KVw|+>Wy;z&&}ROSvrF$0!c|WScfLB?${zsmIZITsp_b z0&_>Gvx zZKS1dMhzefZnZTSq>q))W2pv?r;~MeEXi;w-BL&1cz*+~q)wL%okm-xI~?0UURdhb z3Rq>w@55oSG0`7q8pj+>@@W`X!cL>{2h1Gkl9lmZIY6@e-=`Dl#MIC*0PapesR0N9 zKxvEdD}~kymRpB$C_0xow9GY?QfGq-O`KXGEAapz1ymcPETlGYVY0Ij1J7c}GtqUV z$EABSZtd9~L;ev)y(5eD&C|KfJnjxhVEKY2H&#E-6T?JNwRFc2C9Bb6>X?uwD{+a1 zOzTtD(P|Pv8L<;K8NhKWFv)YeBzqF&h69wgIISBKew1S`DSom|bW-4~23O<~X{$T4 z8VppZ4%zrD05aiL~bj{!~SDuqiSAEYO*$nvA zNFKV?`161}RyNvf9vCLf3|Yh!rq7_|&@ffI_iE;eo&z?ko};;cw;f;B_}rhT$X>rk zbbfno_-I+%aSBy$F;vg|sYJ#%V@DQNH6kI%p)33*xi~@RqK%5C{9-E~ZjPdLD>Q-~ zXu?X8X(*!(xLd}LGbvSwcFZXES%m?I#J%>~fm}Fz8!wYr+w3*+YI{C+Z6|+j@Wu)8 zcxa6@uJzeeH$=oIGyqNQHE#3gaE8d|xBJAvoNcQBP2Hbu7qkbkT(f7Mq4_P(QDz0~ zjo~wUOTqL`Pm-?W)3|x*?X$Ai?m2sX+jIJA+nn=f+s|DquW@UxzMWe$r+7Bi4av`) zfQVO-AO$??nAQyuPre_B*98bTnO5=)_Z{X{XNCW z39Qa+4@Rhzprz#>(gdag7mw$qBsx?^k>FYdJeYwJg)k;1N+9Jrxl*$drO)}!&ln`l zjkh2ugUAL*4YMZ2nT(U^cAlokdDN!5_iw10zzC6R-m2_W_mE4ZQB{u&x+odQ^Het_ zN2VPsZ6WiSmc?p)(?%6SI;J9B-TH=3rJL`DCf#;TT1FFrgb>cF``?Z#U3N{{Be@V< z{Jom=6fzkaW2*~$gB2x@VakgY>ytrbjM%ULW=5%k%+#|&(OQdloe*eXn-+un#Cx884 z{_1z1ef!1jmmhslDjFF*nrx2#$qj=LO6-_Ts#XB0_pGhhB+LFl0mrYGOi`PER{I(4 zFKH*w+W2|jKQkY=3HwXWwq1H~`{vuPfBO%gfAryheD&Ec{$VHo^7mi<^4l*y`cN)C z+|#D^YEX9I!=JQFxBEHwA~2jTJ0CY#>MhSA`_Bn7qj`M1l7Qb|Kb2m%bL%n)3r?fr zYAIjDK}HPUzDre@xuu^!l<#&WlW%j-C1>kN7Z!SFl$$`@uq3qI`;B3 z3eN%ki@ytYm-A)FsxUFzV)Tri1#BEav**psF*C)?F*7s7cFY(vGt-(9J7#8PW@ct) zh#_X?HShZTy{FUZq<7Md)EdpSRMYyat2GT(zj+#C?4as<^*41*sbh$FUAOgX12Yfy za}pfmc2i(8QtB^s`z#iKJK2bLduk#h~@9!VFp^^|ao_5O1QyS;yT`+-rZA zdBa+w@N7K7G>`MNAr~d~O&!0w<|FnAuBkijLn(kM8i2a_s1AB^U}cWr!V8?DbR#Gh zTPQV?a5!LF0M;bnaj{T-VgBw=VD&sOtH|V~E=?hWUYj}jeKsvKbheA|ezA8Mu*zrl z5~xqpyfhxtkgt|B_bY17G?fF^C=78Agy6B+?w5Tzsp*uxqf_5&1ug=#?h;ibcA>Q+_Zrjp#njVV}EC&hL&H)d&p=hnNdO+ zbqx!gqY?Kq<*zi`<TM_mRdn-VB0o|XPe^gAKG2tr@z|e4RCF@FTd>Y=@5UsLX*MS zi8~={*~uLQQ;sJoqE7Z4Y4c_)eQv z17Rtg^*2QEoY5IH0^W>jD@WiN9HoIy{>WRa`}kMM3b=n^6@J^2A?pEOihzz%uetFD zIiEuH1-66=MW+>YE;*fBI=P_-3q!pzm?J(TOHoO4{ZAt|FQ2njK4h7%CsD0XS%+xS zgo+Qv9O7i_6Os*#U2$>h+&v*%oFN#p;vgV6mUw~&G^qHd<4Ijm>n;|$7cooj1&v63 zky#c$K$BlC@G$1xh^Ik|DgIPQKEIjl{9$t@GcBA(=f^Hoy9x=9VHg1W(snWq{O@ip zGmpXh^FqR;3cn*%mlQKN(j+gw3x(Q#!^E&YL9aXh+M=}y5ip)N03k^^htqBq@8jzn zYB(6Z-bcs7VszYD%eticQPb>cg{kM{9+*BOp;@=RgfDK9lu{Lh-s-`xe`DYB(C4s%= z`j5W9Du0qW$G#QR{rlh^geS2NXPiR0b=lpGlF7>Vvm=i7^=Po}@;bmd9^=@DTwffW zaWj`rgnr=IpZU{pm)p42=0wuLcf#?n`|BblJDW#255dON=0V+R!h!2aiMNDEFHtl?B=9z z?z2Wpvlk_Yq#to<*Hm$OMu)rmcf$2vX0J_5AIdw1N7F-nVHOr?af4GW=VXT^?1Ok= z(6Sa^kA65@n$Xlg4OIWecTNN0{&7(_wqf^V`BD$ET1wWAz1 zV;mYrE|Srd zbbi%i*~{jmV^9fX=c5f{Rqz&t`-%$m5a7O+A<)~_L&J{|)Ihe|SMQKpU;Wi#+blah z-S~C(YBOE+>E*GF(5u~rBIdSaCX*O4*QMV^Av3QXVj)UrQEvLMwED<>7I^e~*}MJ4 z=D4@8Hx~f>%e;PWoqV|~e2-5UD7%L%+j?2o3^S0MN(%W?pl)Y9H!EN*U95P1o!;~- zAZVv1EcedArpGtm4{M|I{7>$aCFoUvEQhsgELDxs2NVR+%J^9V-P?#Rct-5Y6P4iv+*45UYTB+ygJzOC9p0>9lP+gTm zj7uGIP6^kcD$%Lx|Kn+aJ*3Mno8w? z0*uDC?-#_2yu3&DC-m0$l&N^Ad1&^n(c{Cv%P`IUMVL$7FQ^jw>p*g99ZOb7$ULmFWXv-KZM$Ta9sa=IMJ-aoJ6}Oq;UB+LG{K!KvvQVJ z?=z(Jwb;;_U**2eCri{v1lbk%RHN#TjHl8Kn&T$Y||4?g%)wUz&Y85cmFnxWM8=$X}g40j|+Wh zr)lYjO&=%cm-=-w6h8TL&|$S?(?vje>q&updckug=!P7!&~Rb?N2z<7x+4c9A1$L^ z0!xrPZCO47rd&-90Tb4~_5F>7sWC@yQ$!|=?R-NorIWS6%ECax_{A{_6TVEprLt9G_bs&N zx+Zi8Tz1~H5&f1$X6~t-9o_uup|S4il(DFmgc78<&xv=n&fTqJwcqda(dagNjf-p) zKe9*)fe`rt%VSiE=jlrv*~LI46z!)vnCTeZHsHNBpvr@cKoerTr8Z&8FHWR zJI5;n0HT*m%qRZ>VMCD6@r!`|5KNY4ySqr)Lo$bv4coUv+CB+d-dEW-s-=zooVX}3ZlBdu*g zgKAha92?*(>@k$v&Eyn+-*z6nq_39j)x+{se@4 zY;?kUPLY_v8U8~o&m)|t?{9~_Y`s#^ZAd#V#QCK;_+WJpjFU4I=?B5_8o|Ms6Iii@ zm`{6BV)dCMLmRhuXZSsP$0cQeJ5kzdAr}z%z7L`*E}r>eSnGlk8Va*n56_{|lOs z+{esK`aBrD825MVA^oWrDwRF*UeEnzu>!SU zWo1g}GuJqyomIiUeLBgLi}UkMb-You1s%m&^i8PFNSNQioM3ItPnVqj7S#c6>}>G( z3M+M#R%VZ5(w_i%lJP;2+s))>QSFwY$o4p2KW0o!?vE^^VNj+nu{VA0+UDoi^!ATI zI($$HzBquEL*G%|k&LJYN3zhOlb5r%1%3PH+)#Y-ZKU?Lu)%k(R9I^yZ#|26t>PU4 z?G+AHB@?h41BD!ety~6|-dP!vEz0_ZLp~<^cQiUdNBI1heux6@&60sB3uR1nxLO>(BmF7J>moKTV~-7vx451M_~Ke90DS z%MgY+xEfA0syq}pSbk5?n%?{ATx;RKQ}hApbC^FxD;%oq$gCdb3*H*t7kd*tFD?}i z;CtAQWv#fVU%6g%5fM&#AL0^X>`nop$KQWIyT_~4GK2He!8`R3A|UOcKw@~1!$UA? zSKT^&`iyUYM|@{O_MAo%s}n~f`wQ>TC?El9FZb}{gZ$-V@jC1J2wzN%O04u$m@1Z! zDB1MYASsSnh%i8MJA2vc-*peL)Hdb)+0NNd7ykMhC5*OmuYbd> z|FzWm>Fqgt_{wCibM0-WrLVC3)F!NhusjB?D$@Jhmse!$|%KhpjwFhUSkjUfds7%O;DbFWMvZT0h{nR>&KeKFRrLt7#{FcLGOGUb_ z)cV4hML=iXaHQFk$aJ|kN|V-fr9T+RfJN1*M-?*?{I(qD#KF-Og-%;Iv~29mVcGS~ zV`|nWm9!c)wlIGeJQLwm&yl5wVYxrlZ{_?d`tWR};dOfcREP`ExIypuSY~o+!oLt9 zV?7@L*}3!TQKPj)G@|a?ZS!giD|5%wPPTgQT5-2+V51%V4%ztNge9JWrfux+&${7c zC!RvniX3X>$_1YiAPe`Lyy6M;%}YDgkz_qQC0cweJk44Jruy$1bF~p-=cN3W$P@;t zYk)+AZLXgh4L_^VH3J(d0h+g-%OB2FKQiyib8>-?iE04NCl&rD0r&UvQnIF}NE5)^ zi&08oh`+I8lJstIS+)9}jGYs->P@JskT-%nmP7lkI-|n&fh$G?7mZ>0r*j*&iji?l zWUKjAG}_3vYkkufW7Eq17bEJ;b-GL7<6^kxxT5|RqAwwn&7O_xP~AZ{Qoe>GTZN-l zmKs=@0Q>jO9guR_!flkbgzcszdxjCVy<-~R9cqy57ce_(VR{rf>H(e&g#nQTXng<@ zAdk^?@nyn@u~FalWmD@Uls7@nD-L_;Q)j28RD(H-W+IrHkHHilBfVF2vPoA6HI|2mv% z^s&b{xzh}!_b=5De?oum`zXD8d=8omZuKBRN!b@B-cp4m^FP_a`Eg^J8`X$;vhy$T zmSdL~RY0q9cAng=ZoG?$OXYlexx$t6xvNSP?|yFF%ZO{!6V{WSvH94>UHzv%gD0iJ5r7?C<%|}C3nUAABJi$%`iu1`rz+l zWEnd7Lr7-bOWNI$Ccw^k#Ud|$13fKyn=THHc81TC4!eb zON=0mvNsc{`7&0T*YZO-G@@C(VqAKjp5`GVM3z1Vh0utEPWO;RYKjmD>W!ulp^=qd z{y{#W7IvNi`P80w@+ALd6dc>TbvL_!4kROIT6g02NDrf!!sez;^MP&l#3CbqCER0j zRVROD(fEqnkg@PxH zmlIXeKK%AeAmMGf{G~Je10el*Rl0Zb&f*hE$fdT-4IJvauuhHT*(#$gNPb0hSZLz&_Z5}hm7Srj?U-%!FbWN2nvYS`X| z`gEq_mf<)4-dA8+wdygZ;7;r)I#*W9T7#kdqEN`F8Z2BBc;?_L)~#L+0gtFnwo(@w zL!~R0S6Y(W0bUfTIxk99Peg#H0m$eQIz0q~f9kLX<1IBLb47m#DyASQhY9rs;HTyg z)5%LLpbi+tWhQ4nq1|*9sJh!!@+aA6J6sX%3z+Asne1{n_j*;gh2e94QHYre(B@38 zx*}Ec@P-CrT6s}KXjn)IDvrF>L&YazSJGRFP)PlBpf0~=HuJ=&OY}-PGSx6iF{``| z-;1E5eVNa*Js)$N+1eU^W67YV7#NM-i=Z$hVPp-t=GOu*1f553WWt;_(Lu^yJafhC zGDr)jcy$R26jp^+=+lYyF~$YM5aQ9@D)?6i){8k1dOKGWw81tEm&Fc*QT?mNO4xy1 zI9n{Kk&arHp!uiSsc8`cds@<^1j8MgE$z@yWOgrjHDpSA2X|yG60<^QxzBQQS{cj$ zaj%S@F-+9Qa4(H@tsLH#CU41QU5JfcFV<}mQ}l!*U#MwK>wB3~PJ41Ob&_}bcT7>$ zB1O;KLiL3skz6fXiB18&c4_m+EG*#zuS0l<5-<3PN2Jq^gk+GgrwXSmfNsrjpORha zf-*4~_Nbf>zJOVemsoeZVP22l48As*iI;%7jB}ocS`=B*=YapXNL{{!K+?jpSGmEn zKD7y((|VBhyT?ifC$+?!_Wj(lTt}T5<8mJZ#9jHnQ(2wDFGY(B+zY|kNPzMmy)*z8 zIhT1PoB^{8L`C4MxH1B6T^y;7i|)sCr$f~NUaVNEC|=Wr*#_F5F4{uAPb`z))eshT zJbqf0-TMOYlje5?(Pq3bYu^r?qT?Ldim(^FA`O*kIj3Ts8694+W{#Tsrj145SN^?C6UO3y&LL>?FwMtC|ss zDdysfZ1p+xy?J8yaQ9v*o+X_vmFD46{3z8yZG0buF)8D3NZ7O5j_3NZ$m3#SNe8;F zI%z%>wsFmJ={gN;Q5otHjJ5}7{)$@3AgFUrJYyz;ui^sNVS`6HfELiS$Clu9)OT-< z;htoYn%)Ffn!`HE!Na4iig(G~Y)%*kosn_l%nbDTXan-07=AlmTCr;5I}QF!svmbd zC0B}SX`)C%jE3+0W^W{%;_s$}zC-I7Th2obJwD2-{Rt;$A>4yURMODXgcwnF!%(xn zCcW~$U;h%mE4GMt503xFx4Lxx$z<=k2a8Jsr+-oNEu)|P^vy|Ht=jnACp3C8Vq1`P z+RksPkyfM6D)HhUO3Ghkac!cGk3CLImTQs>bpv@rUs!owp=nP2i5ZiuJjbN!8hkdz_=V!; zN}$}dGXHA7wx}{?WY%IEto>u0TYCoW_f>xT{ERb)7Hzyp>KRutFpHQILf)v(x?J6r z5JzLuISkD__qp1nj$lqDEPLc%5b(0)*ua7!z18Y1%VVhj#ugLYwJXK%0&+EU}Pu^wqnA>)#TsQ`{| zc2**m=?`D@IR%PQVi@c=)usp7*+;s{*GwEIeR)E$zHe5sN)Tyiku2E-wwxuHEN16o z2VRy8)})Yaau&-|3|Ic0UI~L(ObWA{l()Y#6{xr*Ujr)ndNJddx9qBBZCbz8H~&$! zCSrB`}_#UGKJgyvKlMw z2I|!7l3%(TJ~jfsMmm}k1th{*!sDEl)+gm;o;xmpuE8EzwszB8F6kwY@3TujC%}<$ znlO@n>v6N9G33LKweJTQ?ia~am#U$6^`VL#NH+~@)d~cynwGI4xU2@S-$-XO6KDlce|Uae;QYtDW-(#2#>&hG!H`i%2ugbI>Oq28vy|8dkTrrc~ACJf>U zb8FqO-9LII6yvJ{c2T{AB4Ad61}{GozrRiM^uAuMemu{I0p2e*YkS{QKVDN$TZRDq zy00#JzORlSjKb!~!}2zpuh~X|7tJ^i(;9Wc!Ny6{WLbV1EJx8)N>S)O*fM=%NmW~o zNQ!ZtTtav#z1Ug5E}R%WyS4&5D0#k$`X{`tdZ=+kL{T!9pK2mHYtvG*FXzb}-n%w6 z)8tEelG?bnA~Z3C(bfWkQCu$;V{;ACzq@2Q{FF}~e+JCPp_5cP>wY}1gKl%xHYgFD z)V`j10&WlQ|JZZu#mSuuSxAm=IUsPja3Z`|#!GUbcxjt84x|4lF1oYwJMYBA3<2s?K8;6ECDf zkX3CvEmihEegGe20>D6{kJJzJ|L_a?HUVgc#t;zyp%nbj`~vDvkUY`<%`b5CVzxGQ zbYONhcQE_^!5C=7PNEHvV@N#(44die<=HHz?THsMg2I2Bh+z^&6aZM2{D-Fhj>{b> zIxO$#g?AuEnD&T%S8HX6dNY`8b4HKBraM5!Uy~ymoabl6B-JwYjbR9Nkdlr1oM=zI zq#PuvB@DIY{1Es3N!?b1%P*M7sDK+^#H8{em#Rm7+EE!2{CmG1Mw3_@ z^3WL{UbY}TpM`QUH#N8RF#rG4O38764dwUsJJMvRB*Vlpyk@7z%sYlX=XQy6b{!1=xR)+k~b#46}1d^KZyB9J9Bn2s7D*W<&4JriT&UEqTgBGdwWkQXUD zQQSpNax1!QJ+^@NZzl*bR2g~rI98oKLRGA+Turqc?WBpgoYdUR3cW1-q>K!$tazil z9PeHdXlU1}(nwR;;jC8A84E;sjwT__8O1YA^$Eu1<+4|@nz7{v(H03wCy#~NQ-KJz zd_9(lc$(+`>OxA*xG5u z(oVw-U+Ga1nst#(yDf|y%n5n9?EORncD&AH3pfg&ceSURmQ<7V%Ivkm_<~&lG|~i} z=ZvoojKbm#H`P=9#EqM?%#8Reurt|uwcvlXw;NElctm25fE20)A!NgAeusXCM$?@q z6-1`f)5&bouIINm(9(4RV1lE{j!WdDt4k{if-?U`;SnmA!2I!7{^;4cm~;c+!XFwvDew3q0B8Q5+q~I; zf1fI4f;WG6`fNtsmu^np$F7qIc)cB)!T)}Ik`piwaBU;=V}$sD;>`ZtNM|P`SMF^F z4`3XwV`mQ9xgP9ozCO0(9_;dG4Jv*It{(7Bxv)P~GNNX5sMmHiA!$uO(+@((0QR&oVN8=w4Aa#lei5hY|M<-`%3+ zk`K|_`oW^@n6$TzJO!=^&cr{%jY}1-+*?&1~Va) z*wHaRHE+@Rjat;M;a993n=9uy?luI{-Pk&kk{(~s4+%9Eb(|r3jKl<2ysw7pzRePv zhZLFh#hMQx4(K0$)i?)L@48y)VaZ zkrVXr=#brhurm$Yal0Oj<9e*yjo>TUVZ8pXZc)jZJ$cj+-0cwW8D+Q?==(didwO=< zFhie@_+O*f6d4jG-KWF-$Lapt9X}liLfpey_doaleG&d2cXaizWHoiPb};(SK<~MzP0B1C9s?hh#0(Ie>@y&8G#NG zcfePzMt&|Ytvi0eO~-({@!DR{_z(8gMo1ZL!>Y6z+#81 z*R?f)U)zoOv}nnGloty_Z$`b*U(KQMA1EHJl52w_nE=sJ(HCschqH~JV}Km z_rv#{OVj5pSHC9)Kw>*Wb{jjt16GrI(E+Wy;jl7Nr%VUv0vn|LZT$5OW*AnN4PqY4 zvo>9mMi)!6FRi6{)FMAd&Tnf?IVXVh!{_cI#oc?rjvS8O(dSb9Dr{uyi^+%}GA`0s zAjjS;9V^+?hPR2ut)>1eQgqtKz3@N6mR>|qmJ@(gD|Ym88M`qqukjWEQxWU#NMl1lLTqG)v8BG^Cwc8|qe# zaO%LSR^2k|cBL&77!aj)X#Pmq2ePLFCzzD0D{#;aZMs@A$zpRfAEnjZ*(FtDUM7G| z-OUQo?p@7vn5{rHg;+$@Rrt<=5m~8o7F|h-CKEI12(E02vSATCI7MiZ$i~rY1oDm? zg^~^qe8ADxWZ45I)rh1_tuMBz1TAwS0Z?B)ygjb<)=RdEkfZUAZ-QO(o%EiVk-@Mu z_15<%f%Lh=i3pIGgBv_p@waM)cV*9(0+Zt-=ER~!A<6*pR;K{S-V(BsT5)z~F={U9 zG9@>~Lu5}yF5}IBGf(FFMO~}FJF_qp5c7w%su+KF$XnIK`CR{xL6~1HJ7>LtYt<>g z=>a`Y=xvMvL1fK{$z?!qLy7I;lqAvpTIq%P=t#cACe-cUE)FWW7=&YcZ`7P6xCwmmEK7i9g-}Q6*xtP zZnU8U*xzpbALY(i)B&8n%t9hSu-SZ4e-JtUjdaa6ruUZ(dpA+wLQ)t2|=hX!{&~@iSPqo^Agnj?8-a44;6{ z?dK0}Uz5-u(cSB&Dx53e@CX}X2@-3ZS}k0!B-8QX22%D&XWXLXHPOdwC+QHk+84+sx~+z1Ac z*}c9w$sb3d2F=K^`QF{nTNEwAd<kBDhRX;)}+hmQ5fwuP%Nz zR8&Uc-rA7uB^bo8HH~7yZ{9;e)#ikob{vZ@K5B%KM+nle_DsSIxaIdk?h3SvPHr#Q zh|8{*H!Y<2T_SmJ_B*bdQSloIM6QP;GZQEjJs;>yIKz;7HL=KMKK$_{V>u@9JcJ&y{_?R6o}M>1LvBj{88b zvuasz%1;2?S!hp@Vr?5w+NVmxHKLHif}1U+*WevOc`vx%!kWpPo?fyh9^$ez%b-(# zC~k5QM_#Not6(=zvdAvpJ>NB~eYr+iPqqj0V!IWP;1!y#ANHI&zbX?e`#HaDMJC`g z{GDn|jWbc*0mnnTFEsc!CqdX8dXtMuKP*0kDK;Vnvn=E){u;MV9(y0Q=@#CKCujU# zQ3!$lGza{)`Z>%u!y@9L*EAe#9ILO~GE(X1RW)?iw1_eI&6G?uFJxCqiDr(3uy$DU$qx^g(E$+Ah)s@ziJm1+xd-Q+0eBYoN zi`C)wg7nTWpS<0@+u5hQOcnKEPaR0FO12r|L`G2Q8Wk#H}D&gmp-+z{wQFXT^w?CVeK(EMB^7 zp&Hx=QaVLXgj1&mGf%T=A{%=lGY!4Q0!bZ@FELF37l;{3XC_F_QmGta0@a8pGcY5P z-@f=3!VZu1(^*-G{s8Li@}q?_%Q3JST7wL$bav}SLFR=YPr)lo_-7;%i`-UO^%)cl zCIt|9Wn%U3;@(jf%Co#Xv6r0{oCMZ70+NqeE0SfxG!SCRaD++-EjDF?D=73B@=8&d z5sC;IiUjghaIDTTzv6Pr8oSU{v4UMI=4)kx|MO?}p98>8vqoL}*fS#UCv3)i-T%#! zTg~+c0WIS&>63b7ULo!ChORP_VVi1`7=8E;`So)Y4g-s4Vf_X2M^z5u-C_gv8}oQo zg7&1`v*_FP=lOI?qs**l0}s5?3+aYj5bF(~bkR9yqAixFOGd>9)3tDSQ6LBE2`#6; zA-i2xnDXQp8p!kO!7`%=S-yl{<>SH^L{af!Ad%MzuEzbL4_(E#T8DgvVENNshEV38+)jgj=x-xSgw?_W{qmmK z(i%{ksryeHL}Y%HyH(;^Lt#Gjk?rb6%o*dvn~$`8xE7Rx$1T=vvi1@r*Zh{t?(&-I z4MDy~ZBuRE5$X?U>Lf3J0+WH#D&CR6X^QFnZjAhT9Un!%AcbfRET>0;w5X0jPc?_& zwtNvdWwbUDDC9NbZ&H0h8d8}d?SsrMG(r_*^NSFzEE$i_yYLl5RG`{(cgN|&2*?r;@kyt*O>&k5p8I6 zG1BUX)T|&3@i}HBCPJXvR}N$Ff-^`aHa44tOam%QM~Xaj=k%e|EjWo`NZ9}$L_ zasmS0P5+wI@~>&p1baoqCn2vs;iG&-;$H)?X|b^)B_y0MR3lC}x6>D5TUs79{A^I> zL$r+e9)9~Bsy$ED`hIeZGWQYDlU{U7X-EKLU^Z0vOQ{3LFNme7KtHhYjhu(Hu z`HhXOarub+rirLu|E}gGl%F(2ijxyTMTz^e*L1n*=4{u1b4;1>8PMe_B@y<|{h>u7 zgQ#@`ZP%%~86SQWOHU1QQ^S&nm``wL`>3MOo{kEv&Gc{XiuW}UU-fxQ6mGeKDG)xJ zN*HPqD(@O1Oq)o2o&0rSMxrEd7BbvKQer55IUImJhkv1qwN@qMt zz$S1M&Nlw0twa*!{#7YWTw5j{{tLCezRz+>@;#M{^w_G*J4+O=MNO8$G3beC^Gbn$IZ&?1A^Lp+{d9-NNS8yyn1(P*?H|mHw zP>TlD`1OKo+u~hwGZcR!c7H#ld>_|lH79ZEdAv7)Lpf6I(M;t)S70JUHgI;JP(sK% z-;0t4ML-K|yhq7dM3ymUV6J>-{)WQGw&kN~Xzb!RHb)RQ!=A(`)I}FV0vLTJE|fDs zpo*X%(1` zT(SgG<27$&vFcQDONhdcE$QJdaTcdBsdiBz@mi;`Q0ZV%+;xb%NU&VKVX+qz<57jn z^0hkBtaNoD3h4y9aRRgxu~HYi1v`m6q5%wk>b`g1M+#K)gI~XK-!%o5fD83$T#7LF zJ&uRObYhUGdh-y&p!D$6z)e1?g|)8}*)6~-#5l-HfK=izUmx@uRmk2tqT{Ed+hi3Y zp*i;p3$c8K=3+JZ*jJqZ;a<^}o3Zp)sA0V>uEbWo6|>G2ZUwca_Mehtid}~3)O@ro z)qD1F?&%-FozX$i;n2k|oOw)eJ_F$BLD;8P!QoIl*WxNHy{(?H``+WPslZ3vX*h1{H#R6pd$%;>Wo2->hNzZwi7lR2RMqG|z@0nk z7OAYXo_ai_Dfap(gc|Z6SQ5w@vaXp zFn^T8Rum3d3?r;fe50$MQNIeDH{1Tgi?2rH(Dsc@qNUU}HXZJl6amRG!Ps|lDBelP zTGiA5nB;fPSg$5qR!5F2IKe-ngd{ngMV zO`@6N$eQ7IKB#MSNVOhijmKCCMdRCF-@ve^%w{^KI*N87;m780dVw!k@YFUIV_W61 zmfE*er9{$9&$H%yJ#1(u1JVxAKcP1-Okr5?ySe>p{uyI#`HmC1OeEjq-y7n&|7b9j zL6y?%M?QFuV*NekDh0RgMar*jnU=?prDFQkyggI@8yvlGs(E@45sGyol`74JHakT% z?|nu`;%#sqpY{{&LEgz0T`(@iQ$eDWsx}qZFZTT9-5-Tb=r9s%uuByeKsy^3@!Dcj zEHbcuI=5!1FkMO=#QM;w$)EN+Kb}!!EnrmSA3vo&ZGNHoTmQMK?&-uRY>L@mKJbjvm2kGu2P-i~&Je^xYj6d)i_ML7Lhe->O4 zn+^`>engU&8#SqF*ADIL%5P*qq}l>02tHT!l3(H(!XF=ZfEWRSI{^n|FTHOK6?0_A z)2SH_WOGK>g83$Yz!#PPPabiARseqhc=4JbU(0_YZJ=H*4B-{KY0H<68pBh3tL;jk zEZ67dge(Ab*lN^vQ@8^HH_rCHbN^0+Ro{Lcb2kyjJohttd3h+^`G~)+R5^I8%AMd7 z1*1eEop}Swfr9s=+%G>sr{zaAr?E!2req5iMU~p%Yogsv{H)UL)iW)7FxXkhy<72e zU!9DftvAB`;o4}p<8?aqTqTZ zrRLPQEQ{NC{!G6=^aONovH{ycejnNVPy0qfOxLg^mdOi7#VHTH40I41 zbyBn=kp5*dlJME1(c>0f^e@jAAZ*I!^LCSSxCS&cN|{YUY0?G%G&5GH`R8He_#-=8NPKwH$$BtECB)Z|LiK_nequSO8j)nb z2&3_7g9_H&zU616lx&c^=YJ72vr(b{Zr6wuC6T(a8J^;Caa3hVXPxr#V6jX&bXD3i z^({$Z637ed74k3zN3UB|M@jfag-d%0JxJUU)q6GnP96L-|E)GU@j#G@svY5ngKMwJ-rSidTZrer|?4M@gPu*6g=DM)%MzuY3ue6@0uu=JO?BI?eAXwt=bg1u2_ z3wwZ~xkXPSVq)%s{2-za3v77XwYBMr`Q(ZqiY> z;&SbJcSs1wr8ZYl4YwdkGj~S75?_~pR!(z*N3G)ihml4$aVr_&6QKA>DF?yj0k@mH zlu1yf!XWG+lZdrLR|#!utIIB<3>kBHITAyQu&ktpD<%FGUlZ6$$0FUJH^bfD?p7P; zuIcvEN4ZQ8Yb|%&3yS+#Q9FY_0)F#b z3y}(ov7C>1ZT07`hv^7=Qwt;B!(iOY(YxzEa1F>+OZc+gNYY@49m`SL)qPOh4*>-; zs&>vDi9{xSS=-t zz{9^LDN|jax08h(k5Y6HwZGl^ajnFDbLNqV{pKlBdTsIg6Sm8c?8){R*wJC+y3>d| zYwg$Tb-e-vY5QHA!nfi`)N5-y)Ckp$}G3Ko$BbWf^P zJlk4UyC-C*LVCLBtuzu7=>u#`<}+uEhgHQLi&XL(E_v54G0V;U9>s2jZx)6KI%Yg) z`K%6;I7vhMRFei?YH&obPcd>~?1tb&nFE+s2$yYK-FrdVUxogxV6#<4wR~JzdShUD z3WSp=Yhu4A`gN%wq5xDLw>Mh>R;(F_@y`hqCzoDTo-*fZRJ!+&aq1dO-BB48>m{@qsA!<$_`bb@Rb;hVeaYu<6TVYa=9v8AIbn#4#^Z?e;LJz0mMBOdWLRTJ`h7@~-ro;YR1!&!<_ih*)Gi)|o#LPU9045DL{?7?C@NIOU);zl=9LMu$=Kd_s{VUL&l? zr_O#5OMztkSDX?1*}0^oQz2IU&4(;2pKLM{@Y8p@wK*hg@rh|st8@R>-y={+0lRIN z^dFSPh^){AEqMrp!?coX-B=QOlC)>e+Lxb#PBqd8VuY%%OO|9NHMzi>yQt|~B)Q1D zl~)P*z>Dv9sT99f8$DXwk21PN4hDZ$>U$)@3{?a}x~hBqTDFnd?Aka(m*^wk;o6wz zj_?u@vU$T5q&h24{<4gnS<-{+JZr*BY}K%}_Va7!U-Ve{+*jmUE=RPeMDYU=ewvR* zfxI!ny+(qNNPlG1a2Veiu|N?aL6nQ2S?qX@JDzW39N0)-Q*Lz3Oax32ZEi8br3|bz zn>l5Cmby76okEQO^EM4FK)0sW1Y0|<+0GwU(+1D`&nsGeCV!=?-oyI#&RK;&9x2PD zEuwD6rQ&SD;M{FuxCnIDd{WttV1tJNy`a~|&wj4b`}WF{m+2_-_89r0EE@TDN zdPkT%@Po(5&$q4YR^a@+vk@P zEc}gyjc~&c&XT3MTsd4FR?w6huy}ttUROeGZhRx+*LiHz^y(f5TaQ%b7J3mMGt0%i z(tlhRHb>ix^rWR#%5=`hNIPXTG<8t;eQyvO?b#vv>Rl`6$~rw%;`IlloZ26G@pyfS zAd=Vt9Kq|MYH~TjgR%q-Mu=!UK-Y44&#M=m=5gdS`MsH3K6}-l?Ha{$Qq*yoN8)w zK9p-k9?y;YkbEB^2;;dsM0$8wB@1~aZe3K!x`l6i%n^RKUa{MfSWIK&aXI!BYAQ{O ziJ0{HNb^{hgS`FA?qk9t9;;)o%theoGk&-Er-x*emu&m{J0mF?VWHte<>)F zDLGZ1c-81(I+i06o@NF9F`q2lDc0}u1H-#2xlqm0l6Fo~gUYw2YL7?NvPEEDl#2?= zCKvJjkjdnOo?i)9Q+)t+vr@pH|A3Z-du4{1q@|TFffTI- z@P*4%|K~{m_V+at(yMIu?~bvsZkyejJOiH#u9PBG(cgoWKpID5K+m>O)b!UDm8pgF z&s+gJ-hT?dx?=~nHzc*uTFT)Z3YTTnU!eBb3qW)jNXV0T;rolR`%?-^C7|67aH{S| zolpXux_ag++THX4+8A-Mn0bxmAmD|`Vbv-IyL#f|qrv3XF;5}J)?z!XcXZh*Z zm#-|dK1=IV#ybXX5z7aSV$yGR0Ros6JvyPwD({}Xw^&=i9`%{*=&cjnx#x960wxMF z{Y17rc~7we>-_%IGFxx!+;pUhJ3In}Wc7ntmFeR0V0yB=A&lunstd0Esn z)$Y8sti>x6MYF`#lJXd?5U}j6GYFE7QFB&mg=2=V7>yPfHD$@pMnm0 ztX%eIyGX`d1NsyqPi8tl7-g73dlN@~1CR1=G*R}k#-T=EoyvAwBm3Hlf>sCcXz|sP zAVMP?AX?_{pcRX5(l>hQgApIPkhS8d#mg6!WMKv=5-EK;?MxkWP+;xZy$)kz#YnY% zNdoElPdbMgQ@F!IH1>)HHo`AVaNE8~tCoe1D3oUTrV*d+J0%%z>08nqsa%!&yz>J! zYw+vk&3>9td>_?Rh^Mv;jcbt}xG9^H{)|C?SAxIhjEpoTPyLjt8qGs{w+|@a0WQ*0 z=R9fAY{&nF{)cWDUba+sx@F)K(p0^p!s${V`$=1#{Z7I4U7*lXg`lF;5O>bKZ1=rU zRi=ZW^si_|pPs+UdH04jA}e@@*!F2RX}@kqK9hf3Cb!{NcnfmbdbA@L_N7t!vecvu z5QyGa8_F``rdrBbLbpyR=~R9E+H_8b7E$YVeB7J**>!RMe0cxq)l+RRIH4sVaLgr( zn?u#M&(ed@UY903MQ%nO#3Knd&DnWxLEtrOnNa`R+fE3EFRdqj!$WPRF3E_r?f8LZ+v)i)SlM=0nNN;=Dp_2Kev8<0N)4S<=1&#ZK ze#m@OenSmm+hP*jBp4KjO&1pR?cAwy@p*rmff6O$B;+8l%{A#4Juu6k0=JHyC5krF z#HVhC$!%(YKQ_01eHr6cZi-%&!teJP+LVTsL|P2f&XCmZaqD*O*}gn|TbogemzQ)P zo()cM^QQ%K^>w?FbxS61d-pp~=_Ufrkarq{-8RA`v zNIbiOL%f;xyLs936s$xRYpAz%M(dHzH%$yV$^=6vUWoifk#d;`I(U|>yrGjBZN}QE z7_bdfMw1X+(^IATK9KoSijHQ?gu;A z(YGVSlmWQzHvI2bRyfsHq^Dg2?VL#@?6AJD$`5wA!#X3HZ)zhN!Vn@vy@XT-3iR@n zgnZnK9cTx>$9Zj1SdYc2 zr}=V*cmMd~nvr|ys85D$`gwLK-@IVTUjlDxEWgU%(TGV9!lOIHzCEz_aB`#=*+r#E zqGY1>ZDLH?>|HU81(EO*p%E+dL2tGR`L+LHSa z@_l9;#D0%W^tf@}zC1dXQy6uxow;wRcJ7G`d+y}%PE_7{@6PSxW%b9lpV~Qn&ac6| z&#z6sGblp33!e`JAkrI7F8%$G^;-S|JP$eP^r!3%yB4*4lU3;DzSJyve)S#iA2@U) z`$LJL2*2C`D9e+Lfld0ilQoLY!h#t@W#`xFhL_&?-hY|IA0wTgL-X?aYr0al(A3+kso(% zka;PtT&}~`s%QoKxyQNm<;EwUK}wbm_x_=1sg7c3)}?;;XwB9(yIy)-M6S;9E6sE_p29-qfN<0M5+kN=LG-8n z=FYy&v1LAlkM6eTpX{r*>InBcBRV zKsubJbMxZ{#<>%a{&D29!9G2Ca_pdPZFB7A`o25N`Re}5FkBfBs>@|w4(eaRnAuGIyh)N;qbZDNeaQQX z4uGPZZ-Yi*`GC8c=S27 zqNn?2kB7CoD*gGx11`FlTx_lKz3v~xG z@tAC&V}XJ@zP=6J6Z#+YyZ1u3FqmN@-|_GGpL^F;&Ge$Ri`F7|_ZwtGbbf76WY4*$&9VFj;~Jo&nf@0Q#14*S0S z7vg!mc^Qk>%I{S9(S+g+8bw0J6ePX694OTx0ds8?`uw9%-&AcRPn0{3<1p{1keU>n zy=t$fZIn1=y4EQ&jLI*t{1}}Fd<_oJH>BRbR#$&i4`t(wnQFaFMW@!*KYGz}+QqL8 zNwP28PPH*>CsurKdQqQ#xd!XIWdgi-S3ys2B}OY?X{(6H%7qKAC&tXov#_(okbgZh zN9mO1a9AReaw27XvjeF_=qQ?c(2!+iIH1nxx!ihCG(3Pe(wNXD+wmL)NXaQjF zVnStp1GgdXVNnl?GPJpVkmJf)Oss(9*v2a)3oIvP?sQ!9ovQ9MQG}kUd0^8-joPg# zIU(laIvQ!D2p<~3$&|q**+dZ*ivmNYrAFsByT0U*%7w`R!zf&pyfTsHs$Ipx$;~>R zo@Z?qgTa9(gFxKuA$117@%0Ut_(B9i=7`H_b{JQy!Vglvl?{=DT{8x|g~b9&wBA~e zmcnrft89i)OChz~+AOJ)Xg2pp+mj%Uv3>lNMBr)rE&_U9S9cd9pfwu)8O#|avy&gK zc-`d_t@wn?)H0%RvqrPWm>g}S5XkrV5>~s*VuNtE`|~tf((2vV9GREH(%`QRd`SjKafez;u< z9}>rcuHW6H^f9fx^*p_;Jq$9>Lf0>5h9I*P81gLd!!N)4{iz5Iq0e`@9ZsY z4*Y-><7*IF5>SkJNQ(_Gs$Ij4aR1&^+Uc;&gA`4;bvlX5r@ZUc*PmX>PUb&i%xL`wAq7}#c&a^VO|qY#^C0V%wR9Bzead1e~vHB{&UvnQ@HCg z=)vaUZ`Ze&uiV6DI^7&QZl%Tz^&NXS{&QQes>ylj+t{A90%VixAf^+C*tJc z55T5cySx_@YN%qEZOw32+g~5NB3w_h7qM1vCdT7b*UU~UGuD-zU25S^)k32 z@83Ca+sf%JV;xSSuQH6S!T#jvgt^CNbOsRqnMRw8aN?}b61`o(7v)0{Aw!K77UiJH zv5o-S)z;9%;R^pDzeQSiR$i9TSnH8Pc6;Gv;N+`-(yht}JtV|GRLCn9 z79BOWY^bw3=CoJio=24m7p90!N!{c#I*`%XxS8Gy@M7tJ;op|z9qDdNs>K=&$t*Jt zuJRHof>8Kr9NMl1A5(SG``0sVQc6mBrV~{CMcYj5Slo&`0+U!99#R7H)QOn|bLl{{ zgsF*+8x)3tmEcf_IbpZcF%KAo+c%_dry+m^&#S$Cb`I0&Eif%nq!9 zr?$hTlte1wJ;}09#iay8{gGo}sEW;^g!rET|)5NqzM7D z2-eD9{S#aQ7OhYGBO7iMw{}v21rcL3+BmBP#cjKHSoeIw!=>u27NI<*2U(+&Xye88 z?X{>lz41b9cb^C}7b$I1bwB94(>2uQc`d?jOD zrJ}2}Qh3`jq2$qMZE}CgY$mbw7N?+rmB6l&sM15(?bN}x6|V5zMg|Z*veLX`g)6Jr zo?z?BTC*z^cgc(XqH@iDl!G?5`CAYV0LS{D-*K1y1K|pihFb zv5~@X@8sS-t^IoOJ9mvbw*i$PeY>BLSR$dYAk{fcmudT9PLGHs@F9e2W@EhQ)pg0P z;&|MDPV4dacelBY+t}LWIAHg-%^wx&Gb0m3I6pjM+N>FQX4F=ORh#8{^i5kUU{g!I zxP9Yz-~rN4#k+E}>G+VOU3hmvE0oJf5a26g!>4a6Ri-R!rd6q{!7=5l%&Qr2(nA3` zPyc}Vm5%D)wq?F)RX_x@F)nOpbxxXoZ-dzwmCRn@9FrpylJg^h zuj`qRsIuYOB{CA$#V?<(A0)u8CO`yKOz>_&cG*ZTj=JE$g|U9z7xmxhA=3r|Ok<^S zPD1{8@unPSD=NaasAx0+6OS~^$y66HWtdhs6$#D^u$5eJYpz_h_O6MCQR&oBK&g?O zEL``q8b6Wk`P(CntH-2+nn01-VQ|a@L+#lB?_g1B?$PgU@?%%w14xp6R60lvD?Ops zb;amHWT&)WJbw%4T*n#Ck8*k|EGfIkXIF>tHfNWB&QTOriMwXYJN+t&kh~!y{Fun;u za7H_|gZam~{?@t_vLTd|6T{b7NtB76!FfqxI8D#_EmDX~7UxLS9TmAOAT+CV99doJ zlHyaAqbkCO6irbWBN3RN*;mJG(!yjgz1Rgppv%qb=l0&KJ{~;wC8wkB|KFto%B%x>B3EvsJI`(nD|W z%qEYpFB?$6)2osvuwSM*v|jf=1zTi$OerUc7Bu@It&-zxY7pdxCQPeMoKSVwT&aNsJ!YeEzE z>5#c&P?t}2Ii+S;dYs2PnQNI?O_o&EPjbR&&YgK?2+IEr?8}jMI1dVT*#V84Vx1dY zUM*Cai`I1;VUaI|ZbSPhjBO7EO-hq)u-kX(aLT!8ts>yRf7M@SM4HBTSoZ8b_sFTM zdMgapHIs*n7$V}f(7FxBFdE~Rn*=gqjw_)DrN1)@1BD zdps*&B}OJFJLBg$=eQYM7cJ|jHUYQj*mO(lhR${w+Gp9-L-D!KO$vQgF4M>E4-rY8 zE@3QipEd9L%W*_6IR?&pz&jt0nLsc`8sfN_X9hE5%~))#w0Rj=I)_)~pu=-QoSzP( zQ%aLN_*b1FNo)j)2Ap@1NhjvCbUoA>=0=fs3_eZE!nVzznk`mhs}da0pDpOXG5NTLmfQ0n?Ud9o`L?--bai~j4|_hR6~-{N9uCW0 zjkQbvp(ln-oZ}@}_+;#nK0Pft5ftnS#^8P7B3O17>cyMgxl=4v zmg*3!I2bHbcSapK9Yk(h-&E#@5@fX9!XS0g4@|~V1X5MNhfA7k3o%V6OWm0x_g|8> z)NC8J=WZ!aJ7~0_dugq$ps3xPUt4L`o$b}fx1yX;@}Y@h>+DgNhY$2!RCZ`Xwf+pA zI-ILQ(0`Mw>O>XISfPEtVK`N>rIZVZ@XhQGOA?83Rq71$b8K zMSs+RuQnvvXNzJ}jWvjhCt@euWx^*Ik%Xtt?%ydLx>@~otz&EyZGT#M z{NPCCn_fZmCZ2@s;@Sf)VmNOZ@{LVWM0a6J`7s2&i~ces5bB;ibIll7~nGJZUFCymFW!hdHQ?k6F!`XQ$*-?y1 z7Mu1{I4|mmg$%LN!kJr^dupZlaJ$kexd!f^R)5DGGpbxSP{*Yq$Id{>&xjHjIk-&g zf)`1B=SX9jk!Mj|3k@H>mI#}2SX^hB?yAjtKeDfDx1~akhf{LQA-vjpM-LsD;FQhr zFcWMWnxb+~HP&2a)#d2EWeiV1amsI9wFwp`$Nx(uoT*9fam(6t97`+$4NM3K=|(qH zFVzy&=6IcdY=O*Un@?YQrz(WTI0e-ha>rY1$Eicn_wLswJsDb7wJX?z;0qS$E4R(XZg|sTDaa>gI3x*}n7=!hx#VthJ;W}^t&l`R4lz)nN-Q*;> zAeSQ~Qu4!*4;X7yCmhf`GMBYcy>VqHcHWk zg-ON(9jVJxDvXQGT^-MULXK?Hx%(G!MfB83!*e2a<*RQZxZ*uiMr&!;j>GhWbK9{f zY8ByMjZURP=_`pTiG)yVr=93;^DY4(d`XR1i`Rd+!t8F~GTZR$RYE!5x$H8-5%noi zK*sS!+}I>3)ryxn6#jCvRr^>*nNX(tYjpmUY`K5i96>zU+I&xI`WhnZL2#4h=-=1p z1JPJP4|kEA2!K#({jp7tH1H>M+|Z)zp-eu}**<3{@G$x}2(=AV+Z_K%sd&Rrur_hQ z?1|Ah(o)d=qM`(sWydYk(&T+jP@3+VLrAgl+8%rAEXFu=5>rU-tb{hTh^mwuoJ%VQ zv-yFge{))AKA=K|Q6IsV_+FKl;YgoyOXiB>VY5~@Th50rMWsz69FOwBhxr+rC2d<; zDc+w@WHf3fowFy06uYwWY#NzQZpnLTq0|{JmXr3wc`YYC^(>^5ZDp-O09x7@Cdot0HYl z6k`y7swE>)8NzJRlQbYg9OJcDn3|&W$lQ{8ZE^2mV9siLCTD5;UR1|LTd*XG`Esxh zxrb#}ojwdkAc`^Fz8Uhe*)PX8DM|fm^v1jB3o`$87O~%K{*wRkqYA7HVQ>jl_%7q- z02W)tb0Y@`Zz4IV-V;v9IOdgIPQ%H3!zAxO%b@n;FCb|8qq=iR14XoVS5z(mN}p68 zE%S$Zvrz|CtqjA$DHi~2ya5`(pb>3uYvggFJ}*)NGZ|MrIFDKZTM0KgQ$wPQAXQYA z5v7tOtrpnu8?l*KCGAd7!MhUHwfsPQ^C{L%LBYx#X5gj5i&+VCOpyJXA&Xb6x8xnO~UG~0ZV&_v^?qD{;#jJ2*?8$NvWN6|>>xR!3jf`rA)bAaPW zx|yLqTKmWq$WVaWGJ<_+8sVF^=UizMf)H`5!E&un4vqB^p3Wrj=b6bwmp)y%oLV)m z*HBSj^M25RP{zJf*=@VdnWvr=>6TzVUPSCpqlz#e^a6S8a2pM>E}~Ph=!uaUNTRKNV&a|tT*AR`1&kEvd*t|gzutgW8zLoW6DpboG@4x* z7*zt1c3OEB{qJ~d3cys=IIXyb1<#h5wQOpyqCAn4aQA#P(;~{u=J_*o$6OW_;eXnM z=@D^Oj(%H~@;rA_(F7V#MVUk|zY|WH-NQ$gET^UY&`2dPwFu;a-=iON)hhhjnmHVX zqT%VHg+h<%MOy{7U~|R!B{{K{GAp+;FuhM)x^)~!WC;+OZm<6eKhg?o#J5{AM|(D58f;id1yvZBvd^7_ga# z7W7Qx4iSV`w#lJ1JzPrg11)URY{k;>>5e-im>m{7qhwc@U1csRyroXHni~9ASO;|R z8p7uAhC%cbx`c_Czf_alvYH7G-*~=ojqMe#(~KH6P3Q8H{1yBEmZ9Nz`Ab#rtj}_) zKs>WP5^SYl$rtD)Jyx%^_{5+>twDGi5}2ydP3D6BmU|S>6{+1Qs?@~b-oGlggxz;C z+H7u3i(hxRf)H40 zowkemAh*|V6lJh8bP=?JsYB@u_>Cu-UrfkFZVO$A zi*}&qAfHT~Mto&@E#wf`^_v5U+zwQ9md0Yz)XRgA(3tEE11gE%>F&o?r=X%i+gqA7 z3`jaVv+XGJL{9~`Bo{*lo~!!Fl}4jl`naQ7*T`&_c5>T@L%YjkoleBmMd?{)gk21-2rqm~K{2V|8#~pfm6%*!0UDVCAySaK$ub`VGJj=NGq#~&GXB#- z(9v!B5}INR)L?{5LdJ(x#9^r^eiI;Rj+!-_NUnSm2mzR9W{F&aTFx6BV2_JLiVKn) zh;UERikIf&gU3Y4qA71Gd9~I^Lqm-0dH>H{Ok|bBW zHb-SRVgHHktXVLtWtEwfuqSGmtkr5XDj=p2R8_j-LSVzr$#n8ox^0wNS6)~Dxl}FB zxFD+{`;dARk5d7Ja3i|0R7ql{>&tf0FtI<#Ea9Fh4wbEzS0dQS`Jm}+2ZuiPhq+YNs13e_DQ!Sod&E z{M3X3rJZ9qQ@c?y5|J4+h_eYwHi|W?KR4AmYLJ#C!!M!}j3WX=R2QFA(Vrow7?`|= z1y{QXdNtbeT{)X}6cH9T)!J80`~H>|4;!m>(pTHzAQj1wvsn{}Bcv&h{)w`T$<$p6 zh614xBIpYgMhB0`RmiQ|urfBw#a;Eo&7cOHZZUDCdBgYYK(*-@cAOmjT8B+JjhWww zW4)mCUFn+eiqES0M<3|+y{`D2n6Mz)+zQ`Cni6rfwr*-0_|XRhr8q=atSDmr}- z{Tp0&%5LOgypsoEjQNs8)DORGS^Mr?V;sQYAf8^F4*dN zrGb#_Sjng^m<#~C6}npeKrjnBcnhJ^vA5B!@SNm}j#ou# zz~=x5uoj6XSr;ykL5uIR(jvXBQd#TjWNG^ke^PllcYPLsX^c9@ z^u1xya8Nu?p$)+6HYHe0)u9{+ZI+3U={S@DX?P7~ zEQbDf*?`uOb9%I*%Tzps+US``zEN<0+V1J#I(k`;*0t->(V z)?lzicX&|0rQ!)QE=)Wu{>bd`w?Il0kx6c}JNe6`&g8g+vP3LZf_T;|HT~>5>zFz^ z*H1%^?i$IaRK|g(DSAq?q$e_w2LVU(mvOz_>oKN%t~wFHWPJh8koGpyyCXn zd&>WHu%MNyBn>0507DgH7Sg1te(eZ%N`tgMnMln?82tA*GT3Fkp+JUb;GPz}`Xq)! zw<1+Lv-2enJ0yI<>%Di3?nYw!0z~JSrSfP~FVcp;%&A8;5ki;o=H`PiF_Iy%Ay-G! zBtNy3&+c@v)YW@M@gTiTyKCesmKGx+YciEZ`swk^{cfMXTc&I>^EegIvQnWj8NG~N zH}hNpr?R?A4E|KETk(53>v3V>@vAMKFa~Q%Hurw9%BMpHU4W13IGq!kw7^T6d(`&a z3_&4I__nW)65~}@DTqbrxW&{qnhNwYUN;EumrMD) zc6T?J>haGbG@!_ba;$MZvYA$o8ToZ>lYE`Sx_#l<<9)}lb4c*`m`dJ%PCqtb35P)m z`Kz^>g>$&EnpN*Q&r^|r!k|#7U$0|(YP}PbidM3ZK|x~PAEMetkL;`&AQ7MAxsI!yzXAFq z<2sxeCjn`0*U|@Bb10{dp|-z4$Nlb6fs#+qLt3 zIeU9DTN6z975{y>^Kp5w+V^=%==X%wC!+ZM^1ky`=O60!g47c7%_RE0a|7?^^PhLT z*f#kMs}eND$8(*rhUp4eH@khD6!RPB927rF%H0;1ykW8Wq@?xe<++x`s~&IrJtPTu zWyPz$OTru^vg$KFS-hUq2>7p@NfJC6Mo#c3#A^v?|G8u~`N*i@cLER+myL}-l8(ID za^H#eAfB&npFb9F^dDgn7MG6Mfz=Tb_`e)n`#-x2e(i_%!Lo;BJo~?7*7?GZ^?gj& zecfame11Lmz0LN$6oyG62!4EYvN1orCfc5LtgkJyjuw=j5c|Ss-`Ng@y+jOs`4;KD zNw&Hn+zzQbl|3of2SCP)Wm5>G3OacWbG%EA$6Hk^PkM~wH&C3!n$n1B%;T zjBtY-!DOfsVf z7)PN)`kvIoDGb_*Q&T2+CZXL*xJ*?r`!@bWnFsKgr=kRsOluNSE9&&TR+Re0SRT~t z;k3dGQIW4bU$({TH&_>&TuexLz}p<732Zby*oK%z?-cPrTV}+We`ZXWv+!(O{^R1u z5VZH$1^sAX6WH}_9JE^3eJXvc<#jyxr;;mhK>o~*{qxDqApUXwLYFCfd*Bdj z@VPfOR`(5)lDU8sZ-C2=gB=?GHgxd(RA=Y%4kyL7m;ZrkwdS9k|MIBV_xXfrk+`gVB5^uC$sW9OX!U%C)Ht~9t!KmH>9Liz4$ zeTDfN+2QMLcJJ@&xdIo6d&u{@UnKPZm<;SiO~o(J>?h$oSjLBL1ge*^w3_RdKmn7L z2FH9_jpRrJsDxDS=Ow*3rp-__^NCZSbgp~`X) zX2ZtyeSTbwRueIIqJU79<4(AF_iCK4eEF^sH8w2UUpPN};YlP>w7#rcowG$dCR?AI z4mG1}FxjRQI%<~U;KE3t!Pp%vfLoAYnF$ExBg-)t5yAsbm=)+H+W0d^n-}Xj%OX_n%(%jj+%|4}Ip{8Nt_IUjGH-{frUv~N^&O^S)@ z%ih4g*wl7o1U>!Zt$0JY+4Y;Mm1F(L{!gQ;foOIy!gxp_j3h7$)F^^^?bn9Hj47?X zY@}Ojegmr=-*XvC;-%`*?5JFQB837=xbE*i!MPKb@wlR+A^i?^gA@gDJGHGpxgH;j zg|Q(2VS@y#FUN=?H#%}ILEUtrL*ngx2;;470V^1G$*#WDkU>+O@VC*omEG*X6M=@J zku_Oh*6lmkD~`&JSHI?K*hIf2&^T#P-4u(xC6j~HQir7Y)M_@BKFvDXf;ZjyV8AauEN*i0_fLb?O8% zIzRRe3LU}-< z`aK_M9=6X{nfiOm^*3UZND@|GqbS!U8{}LDzNU%nBBIV9S`2Owe7~F!1thPrLv{%w zm+43xs2^wR&q_Az_r}~zqVNUr@6pQ(!#GBXNdw~N@0V)9kF5jBV)wbvS>u=W>wjiM z|Cdt-zYncV2Pi?lo2kC<_xvwQ_Za_=q4>UU_wSo(gYOsr&(FSZ@LB>2)gn8SI6*!l zkLXAB%gZhAx>hv*ld3}%PcL}NcI6coMoxzgRgmms`ypCu*UMlmlk-~hU{tR z)Ab0DKZyLm++nx!Mhhm*_bjXGR#Ax`j~B#am5X|%wB&id`UoU{=Udv|g~o?**VvAc z%!U;xaL|wOhtElxI`8Vb8H=>giX^}u#$sdd$1tf$(J7Ld^U9YlRx~UOI!{}6W>jF zLb!@@Wd!WYGu-n6;fg-vp2vxy|2DVquB<7f3KF!dp?FcPY-*BlnUpPvki#pE{n6tX zl|V`7PKyEGdgjhK|7}ntVvgY(X-;7Q$ntnghym;i8*)wjMRbox*rBfg|H4w8f{(O= z=Sk=nS`04l+pnIkwU+cRtIRMKtR!34uqEU70)Mu?BejjBU$E5cTdP{*Fn7o)_TPD* zq3xwGXPI_E)v-V%0lq7JKRF!1?AtGgtJzkDQR72C`^Alz2RN4%u5W?Rq?sG0D7_XI z?b!Yv{jprZr5zk%62D?imOiB5)Vkp4MY>D+Mc_7YMDQ7nj8*0scSg!@@z|P7p<=to z`{D#?@We5NUj_~Y1qUxnODvE`|@fod5$vM;L14pS`zu3)@+E*3WUKY5fzjKv4h`vqQY#YM2c1%^O7g}?ulh(1z_es0gE!yj9ivk*)G2RqBI?Vrg{a*M8hbd zo^Pq*>;APnN2LOfUXqU`F*Bv=O6ZeLT589qqTZu2A?Hy|Q0@kG!z+|8R4#L%#wifi zkC1=ChQ3C~f>sNW`^Q0sOe)N9;=19Dfi95PWLSf6rk3zRhr%qL7b#OV5;~RWCKc*t zVD&SImv(Z>qN9M^-yUAap{!h|X3Ay1kOZ45Q>45!&HSqC+O zZVZ(Y4Tx#TGhe))w&AyJKd~ATW~L|Vj(O&bwdCTO4q%@_ASvFZwtAyyEx$&5;#OG3 ze9E0wAP8EQDd_qE@W=dA4FY629RQZ`98Bb0IFGNUz*ZNmx@d847TQ!f6E!46YlT)j z5H4#Ka|)GlSumR)1-{Lw9u)CE{o2NY+HkRo_|-j@NK`M3WX^_1;w|W-=-r(1LcEbp zwTm)m1vXiMd{rY-^H=;s5nT@zDn`wrPrG?$`Wy8uFm8CwMnTMKS#JX@@7Ff>jGEa5 zrmsalW8$zseUh%^W*}N($An(%cK@`~W~{XZsvc;u`D8M{rj}DMIW_Y#{<75AgpoT_ zXyMf7|!7k9B8lenX5t6A1o z3`g<#pD%(+#yMCIO&yt(h)%uyl_COLpU2;1tUgYPam0dXO}N)`2v%91XnvQ`4r3aI zeWf|W=qHA?_|^oLEF!3)aiS}Rwkj=-Q_cohFA{KD0AG9fLJxH@=Vi&R>r5M6J}U8f z=zJZ7a_j(AmS*^_3`1Igb7+WKxRb?F46G-cdu(-j*lR6q)wnNxGZ|+dm z?Z`iIP(gmmc597pnFgwp@t!MDjZlZ3)oj>Ln_{|DsrL+t2<0{|Eg{AEV0pPA(TKAfAs62+ZmKqk zRlqYdG?zN-A7KiUP_xq3w}+pdK*v6g5^YP#t__;Y-Tup42^aQiew1VQ@wwMu(S3yl zaOggN)Z4gjCV!i1;;ohceik@rb|io2HOMAUSp3J#@%R0nQ%=dtpq};xC-z|V_KxQHMlwJDjm&D!%PVU1EH>p})A0p+jL^Rp- z$Zs4BEp=@d4mn&yS8f9C?3k|c;O#1-ls<*G%N3hnd5lB$aVDvMPap^8j=|{zTF+)e zL+!HQ@EmjUZB@!7?I1SLUL*qK>qK$-jR(p{rgz%{^yb}C!A3%q%Y&&WmL+BD`BWqQ zA_E9t+!l%r1au7)@J4R%Dp}JD+C^S1vR(` zv9wPGnWPa0r$)=pmabti7U)8u?BXOwQ!434hMxvfE7UG?G+zqH`CikE_S;KE*}*}f zPINs862UY_gk%8J6EODGa=2JnaPA|7wbnkWpDR^a8_e_!ZtX7zE)eZ45tprmp8fMp=)|$^B^Yl#)`4Il*)vE=pIT;apo?>TjaO)?ZDY~xE|}) z@Gs|R@@VK9iIDcFkB|&g+3*PN_}utxhsGe#%DsYNc_fkjaoS4XK%7rzo0z9;%S=0! zrM^ul1ZQI&S`%*4VgYQpm~qAaqPgXAhp0!!3i~8aUYH_d@%p23KTRT zS1)r{Y=B{A<$nsD#ndW@RT%T@1-cajISUCKjjXrWUA1mD>`%ri(sf+3%W?G5Vm5#8 znz@d7$F2_M4STnT#QSw?%~foN+G!WTjQb~-GKy>Iz1UiQt&0FDNrE4Wdw|^CqwY;m z`5&k74!Q?N2df*FT;jv12KH<@WxYrp<2t-(iJ`8x@tr!cEIu_RgwQ^9_sU(&anhug zM!3CBO6*0o$k4_yWMfoae11@pp%f4@1LwbUlr768?d&*h1^{6Ig9N)uBh8i$K=9TZ zMD)D0_yx+e3iZ3UG?Xr`k82-D&M1eE4oIyEdzeLfDG%Sv)CR}Oh5B9q9NyXR?h4ow@`Y^cUU#c)FexuFZLz zD9h=u;)=*ZWBYE0dWz>>+y&ORocEv1AiMM7ayLJiPJ7OBu%vU!;U1K+m5H;rh=gZ) z))&@&7KVL4(T(VGhx3?Tvd%k#ZU{J44j-cJ6n_;!!obS*_@lY|# zO+M}M-j*z2V-L>%g`SJ##>3IrzBLC4IP5IjatC{_@P!I5&FmK&hk8XP^#hY{yejP{ z4puSx#t!lA28@2GaTN3fyuaD(N~PC%-FLWqeaQ`V_IYEUcP*9M;4Q7~(S+;TCK@qz zv~LdiLBB-gl4sTjWcI93)u3WHd?c0@t%%i0{l%w{#~!8?k;z*UF>)J?t$$VfN#VbV zHiAb?8{;LfN~zEp<0=oMs;lW7xdbx+tpl?W#2fIS|rIL2=7LFhZQA#$|Qn>ZbQ zJ|7xp!M$`0CEiw~_;rf{FwI#4jmQ&#e3v#hy3?g>d)0isdjLNiR5iSMXxX%?BV}Da zHQT1_(zNdxXg@VUX4$nw;KCjx63`*XufK+yJ~uYgGNfiMC@AX3S7l6;A=alCuNvh! z7U&*L+_(nkf;3GmM!l@b+sutewRIQ9tPf&WA#8c>!!jOgx5^uwm3)h^)+FYjl_i~J zl)xHm11ypVPMH1UrUoRK{~VEs^$=C@ovSS&)9v-_CEoe{4yT11*lVdZHl$JH)3yz@ ziQpb(mpD)cJy9g@UXe^^ym1z4igGvV$u+?-jFE#Djn${B5M_tV`dOlhM>=U$z80pl z%SYXM3hS&yw~;Za&|oPV?Gh!q+rg!fB>r4bnQMxzqKTMP`qz^3zW`}KmcPk@ zKec$0EEGzdznx^kI>5qrlEv?%pCpU-M>}a2-$!>l&0@G*Jf~Rv3fC|G~4LW zJ!ux&NXRG6VskDei)L&m$zm^iI!U%MFz_H*P=cQTk}TT%x|3|f?X?^v+Z2#;kSyXg zXFo|6?NUyXZIJTqBw0+Z){|_K*I z6+vSRM;O%LOx>qDJbJ(bRY*wy_|qwLvwTSY3#^Tm6zCpkdFG2>Y6_x*c*l_I2{I6{a_aEHDJY2ZK~4a#;&;U}%?=n^66P?TVj;v^XKT$ALZi*xUz?qYYg{Ws`~ zgMkt5_GWYm7D^MDMUs8;qJ16fyZxM9?!hPCgy$bucGxkih+Zqg$dUbySVCY!0&MDR zXI}NE!ZwcJ6U6lL4v#qILLq}oeub$=Fe3z2h(*GUvWfIkQ-&ptAZEokvKK# zY`D@tsQ?}E0QhQ>jd~sP`$6I2$LMz<*AfQ@)T%T(KD_Nq#LzoLGF(6Lwqik{ zH>O-~bjnCwk%9=#c%uUtgl42Y3Icl0SKi&MK`}4t_cFK*(Qs@wA63>MoBw*g`8LEv zJ-!=1iD7QMO}of4GC-RqCURZGx!84!n~d0+#NV&)zgtxh8NX9LBHP)FVm$r4n4rlc z6i!aGH$c;!q9N=@lOayW7Uc5)W6so{+k37la>{Uhw<`hgn*YI&L=}VmL z9RE9eG7gY=X{a#5S0k~k8)l(*u);>dE9NYIt3`lNKzwfHrHvY%T~aF}0}9<(GVy?= zQ1j;drrg2nl0Sk*$}3G7^p|jr5F=fXwv-tORtMbDLwN)f=e>GpmS$5UIhexmr|gUC zbTrwYBVPBvS8VK&b@SKw?|+<7*>8^P|L@4zZ!gmKK-%{}+GE9x%+mPFjjKK8`ET*x z|9oM#`~2r$T?;JuA^xQVKz{Qo z^*>WQdUwA0!H|NecM&SJ_sF8{^F^qwAjgBVUkoX!1 z6o>?aMcJ+|zdmtU+oKVnl};MS0}L)>yZ-nhqB1v@x5+P^L4f#E_K440Op0PufbDH7 zSlYP9tl))vP)dddgLcMAS$?+1*O(c(*V)bhB)-Sg;DuYz44HXjctnF&Z~guCd5h{% zln+^G9@Ya-1=}4q`So|M(HcjDH8pA&^s&zE_WSD|rv%W#w6_C64A)4W z&ztKXTsF#UQQ`NxhX(M4)%Rb30S@anEX8fR{r>vA#w8#~Au5spxXN(}TEL^XxCBHC zH9eg1^71pDUm_;3#Zit>Bi(insNnN!#02KZ!PpMt``4dI5cdF$D2Gt-$t=IWZt))? z7`jYK=F+TT65>g*YHhJuCc^1!1d?}Q`}#Xym~x}or65sQ1o>zhTz%W^cfK$bfdVTa z7qrWD0dRASX!#wxyO_!)_l!beD>sp}QICSH8fTz_JeKEQyT`&!(i<_WC(ZVW%p}q$ z2BT8%IOEr+UkZNMEgJBdfxfAIqeeEkp%7O>1YuMGe!?z7M?3UH88}jB zI5Ty9+}Va$%(Xj?equT_CHL}Vd^B`wm@B~~OVp(eZJLxY{lw=-1GZ|E832xb#sMmr z0k-GKsE`m0&p(p6x}1ndDOT@YvlHvv49uqET?LOk2pnxcUa zFpc1f1{_<~aS7DH@f`kW@y6+$b;bTPR?Mf;MiFSjpXcE`K$nnX(3rl548D%@l*^NRYk$v0uo>WMo zA2MKvre9{51bAlm7^i;k3g~(ZIb>rK4%o zu-_GxF+rPd((aSO4TE7yj2yr{k!2_l#YBG{NS)5ktV=T@-bk`kZ_s^)+a2vHL;l1j z7geC@G~@C8K?@pq7MZJ30}u`os1Y|>AF(PwKo&>3--@_g6WAYTRwkJ(H@z3W@lAgVMpSkJzyRJL8I>{Kc48s750E1g#* z6Iw4`Ky`~=-nC*pKUF0ojJu9X%FWV(zoz>g?Oea6K<}@*a()g&2LO2mQyLH+&6CMW ziFrhqUYD;baib2t8B12EeAI+k#p-Kn|Jk!EdFK-ACT3(bP*jTUa+tW3E0MuLzoxby zEB4eykIk5Q&tu{Re7%gZz3<=BxvO|51qsX@D^WnaMfXT76dml|UI=C(h$q{q5d>AT zyG>678JinxmMg{5z26W{ihXh?g4%OLUAI$WW=Y+z-wP2eMDk?YhJy%PC43ENNH_qU zu@PUnfSlc9JPK|Z2zL!x;hzN$z&RcD0W25jCrW`EQOnh&z+t*@A&{d{^W}C7=&4MT ziQM~;m?fyy?I;99j>pg&WMvIT-6Bo{tBpXR;t4>VxiTR|4;da@&O*ix7Kk(_)I_V! z^6YoeG%v@??0osp0nx3<4pH)nLa{L_ap0b=nB)Qlc1#q+V$5=7@(wI}acAjHtz7R$ z%gR7Cr|K-d+hGaHSZd6>4 z@SBiwMiS*DrySf-c$pUE^d`y)q8z9>o##rFgQ0?Qf>REJO=R+(mS!{!r})wgMo%Dx zPn0u?C?`7QfJ1hA5{yZ zW&?(h`zd`YkGGzu7-obz&r@C%qknJ#TH)KtCD85{F2d*QNxHaYVeiE<$;4yl08BiLCx<}0TsR2Yv+o>6Dbyzi!ut%NIXD!Cn%lv^urrWO zJ9~q9D2|i;VWz2^?6IOo%7uNxV!}h=?3MP6cCz1fr?%V5@xEPG(n(__og7!v$$2H6 zTvyVu_Ch*JX*o#;Q4d$rL0rp~bV^-G2T>Cj(otEmlXPItyOK_>E9orLqscO_q=V?- zE9thx$o63a>gz$A)?(og7!v zf&2AJIytYTlgmmvxviuFh=eQYEIYN`R*sq=V>C>wgO%>x_}HSG+L{{|@5aOH>(p~S zQHFQpubN6#nhpl>{59+4^?kC5oAop*rvRA`@!ir}gBueOYT9nbS8~~)fN=z-kFQua zv+nQ+5D(?uFucCc4_*iKq&riM$NF1Y+xhZnrq|RnwGi@?y`8-c72Dd3e6LZNU1%2{ zNL0J~@2%+hzW+Y__jqex7Gj;~ld_GG`H0m^l4lI`XHCk-R~G)d4&1ow&WkGsPnvDc zHAxAVHYWfbh0gupiGnf#U3c=HOp^YQAD zZ9E_ECvZ7ocy}t#z_ZBcBV;>$@b37P6Th#+zAgs`P!c%P6teG&TlSDd5%S~hK&=N( z!l1Rit&1<0rYL2J7vH2d^GOSYiZ~9xUpQh zvEhxY>O4C)r?02T>{yxKgLYMA>zF*{6zPa}Ux+N*OmC@5O|2|T_F(F0)LM}U5m^DU zP-rAwCw#nmt|$rv`(82I1?{xm=CuWP7xU>H^Dh)$?(B+xctuJX{{hpp033pX}DTmG0hbE7v|N?HMX2 zC@D8f2?`zqIg0!YD1|M%q;Y7Q; z{i%D-b5GlCa-_@acqAK=7Ejp)P3#YgKeX7S1=x48>+?nJ?weB_?108I?4?hqyX<5} zX6vLCdUw5@)nuNRHR%(uc2tu^|8U!ETCDw$FxQxIg6_~I!>vXVA_Zl1>lC2PL@&66 zl3!%J-Kw5X{yw#3ydVAjs&@156+gq?q-+VzWr3iscv;D6D>};+0fY$nwUCcTos&23 z>vd~Lnc1fcnf9bSDZUx0Nrjc{3i|%tIqR9!D6XDGsgw_}6jbpvt%e*gG-XzekD)|M z_f9)!2bv!RM0cJV+L@;;3>=rm#ynj!&~mrqWK&bqVf>1Dj-sxXJQe ztwMWOt9HFHy4tl5mwMsYryo6Bp^3BXjBn7E!mIe+f6-NW*YbkjeL4K0M9Y;N?!J6j zlosFolM$z;Ix)SBCb3A6nF@#_g1p>)^I&*&ctOs>tTRNJDb5N@j5dvF1Y%=O8l9y} z$8@7#-TZQ+BLNPIFu6$Nis1vyczcgBAm2bf#;8*Xd%0^S3>S@*SjgWf$=gjci-?O@ z`=?jr>iB=M*5_3GX=KDFRQEmP7e?|)R}|v{o`N_~WzaxJRt7>CL-hD^R?Zt@qhk>Q z6`cBQs**W>hua;gl!Z~la?(RBi~9WTv?u5qJiGGJb8;}{C;IpyaA4qv>&xz?CD1~z zq>w#7Pe@YU{L+u)#2OT-us??I9FD2vCa+9N4A8Do>jPIFJcKm&m7;72;k>a~G(%s_ zq+e_ErxTl5Zcb+LGdLWvZr9{!?w{2_W_~ z>2WSTKF8Z;*t>HZ|J+v})YBElh<&CNy)m7tuf)@xc(g=3(AT&X9ca)b%)!|~Kwy^& zY4=PkOEAeFJJTM`shoyAc@&|caDby9`Q@+SFx#zLdY3NWmCYP5SVy;$H=6-D!yAs^ z6*?eIGB3tNO6W96WwBKBhx;8bA=iMIZ4H-E%sfW}t-#d+^=#8JQUb`z^NT-?aG(?M^ULuNV&oArfgp6KXvp-%w=WMflIQ|0y73`~`k)4N z@pk)G`|>*GafK~Kmhxyypvj$>rXOee(8lMqVzx3X=ILwCLvXCoFI+xijw0+Devc#- z14+~{x-E~t7EseIW~}`Y!L%(HqAqr-KWW0&5;%($$zy1e}Qyus1JKE_9f9vvQKm&GS2m8$s0%nOz+O|L7`EjS(K zh#)b>@OH=e0Or&k7?<+kz@t@c+=QVYrVY#@(bh7E^NPffSiktguLbdTQyf^bwyj4{ z(Afb4`?=!B3L1tAFc4xniij6BR z7b}dQG1$ioGZ=)chk!dMsfc(paj~n@=j$Y@a>CK(!A5fmDzuFy1d)g~8CzKV+4IHM zf`6+%?S=-QNN4cP1zz^^3SGPL=)yw_=>(Lh%a0(46A>2|N1?I+5vX=ILJ%q@>qkMi z;Eugu>GHgm3(W355s!x^QypqoXENB4gw)CvqnGP-0ky>{WZcfc86bZg^P?%#YGZ^U zpcG(EB+k(F?biaQyD`}pI#WU98WR~#RNBugK<*|R?*o#k$g6Yw##s0yRjqgu$7Bv> zMRRVqpFKzvHw9*_mS57RpK(I?@17u_jJ66OunPTKhyyvcZT*=ps4UGGk+ifBbHSm% zwL)CJ>+f{`ag`7bJCgfs5MKhk_5&WBEqr` z@gW5L0mzaobp83VBsAxyUouQ&S(1XhTB*y#-Ai=-Ln*UIxAkW-fhtf2JM0X4gMl?O zV%)Bq+wFH|v~=d@Id0CiasEPbRBSm?z$nqD?qM`6Z?~VFd_8rufi|+N4UKSobG!Y% z4+JV0cADu`N8|j3DIUu6giI%+0pQbMm}SGBuD^3h8i6K=bI1t2#uxA$gB+LNU!PYz zWobl69A@69LS=D}WY|gc&{?V2fz1DW_w{*2QQl?!w0SpjU|8^sv(%ah=Wc2ffQ0jcacY#-%<#&&5 zzCxVBzC0Xet!}rUT{fHmsuGnn=Q2-jyZ!Fhnkxb;f+1yJ54_2(zw?DF!mAFsPJl4% z*5A3LD?}_1e&{`hmynBk{hiv>6+Km4IXQIPOuzK@c6;u1hiR3zDX_po5Y8J+>E{hc zRq7+nyIG8N{oP+Ufm;1CfW;>dKN@YjJ;|%*6+l#gqC4lHn!Wt4YwZ<5G~*uPPV=mb z?fEm=(goj?cMJIq+LWRF`m=B272lLWu6mp*!tygo{RXFsJZq@d2%7c_#`*i}4)eM( zQ~?%x;Im@eZ-}UO)Kg4w$OQ^8%jVFL4|?W#<;y!XW9J3@22%NXLq*jBN5|ZRdwFT+ zTN?|!ypIpw;Yxul-<-X&Jq6ks9Q(4mpD`#XV|^bVT<}h%0+VKfya|9=ic@%}`k)-t zVKm+^*Y`Q)1AobTTtN244#cFf7R-rCFa z{J@G)iZh$lUn4aH|9LmwL>-^xy59A5|J;Ics;odlZ|eQ3K#3+qRK~d}?4#WgQh8Om zL!?e!RAD9a+$e{S@AVW0M~^Id6?8 zmZ}IOImWdF{`&q-+*hbrUAOPBZUW>?k`8^} zGoHRA{!mXKCul5Q@W3>fMw7Rbx8rtu-jDSH3tMGK!Li{B zXs1hidEU?6f+O3V4S~8h;^vW$;PM{DC+Izgit5Mid>!9A5o4j~44LC>TLI{oNrvYW zuNxSxlu$GYPU%*_N?5;2gJk4|0JxVq=WTuawb%D?Fw2dJGr+qTF5=N^)Z5H8EUXuT z9N<~D^=01A4!BKOK_+_k(5?a#FM(zojhRXIoXjw@^F_BdAM=B?+17%|26$~Stf?{S z5pSN);zqNgidOoK5Gg#>gh$S%HUrIEgI*?F6X$k)l{UKr^%OQb3Sr_B1-dp0F~$g+ z)phBDCl%RQSeDDnG{aw@S?$M0w=)n$TFjn*U5H51_;aV*68@&Z8fKTb@wF2Zc4IEK z5kEhPDP4Z_IXKkpMpOO}wrq=>LkCDL;@;_mDvZ6sVB*Z%_1)L!6$%$SfS`M}3*%!3 zQ*3}0rqsyE;$`rVP1+ac6GIl6HG+A&60uh7bs|0EH*Gc3XjVgP2~5tK(%(;{tZQsR-Q^%4>4jS36&h z*<~rt38Ht>9V`2FM~#&_gJppmSA3Z;;ba8OHEA$9q)=2J`~{iy^9{%qWy|C%k5ong z_}Xa}>(qV}J`N*VLSDr3I`?-4f*njQf}pqU`p-18=MO)h=gT_1D;6yBg$1+{nxhi~DgeCy zth4~A%}!-&dEKwO2bQd>LX)6_Id)w>5n=;#t)OR_&=S4cMoTRF#YbXUZOkYijQcU^OVe|1rf z%`eUlCrLYt6*K$|3Pwt8yS>iu-QZ&z9gd1*A z4^aMxox3J(l~#)Rf^aa6C^N$Trf>U#TwAm;w1Qw1`x&{m+uUx?`v+FY*||q+@lZgd5rWnaP4f^o zKU3@L{N4oX9P<4hp76k>HhGL43}^GL0)b9HWzw~?{%$H{0>=<$AV2*BI-Q?d6yy8M0)L5FaqJ7^m`s}QoX-`;ci|> z5z>@HL|G1aff0Etm=*!}m~P7%E^oh92wr7EV*W7YN6#WYKyN>(A1jgW} zPPh)Yly~9R$~%3&`ubckdN(D=3c$J&JLdYc`w~wuS*4|eA0gxFfcH9n=O(ZCt)18u zop>rq8q^f`o4XVMe*o4$x$*V&*Bd%)3Bv0^{w{?!f{0Yi!lPK&8$%1yb_0ez0D=$P z*bJ8gPD5s7MP~Io!g11?keWIxx}7g?pJNkz>lfmmDHO?+e%+Zm1C+-&hoXnMP7C%c z6mY6q@F8&>8fUV9l#hQoUtfS~h5P`7R$Py%@D7D5cL%cN<6r#o-Dkdo-ZDR@D|~`* zEt8?u2;igVWinkKtJs-~c|pJZe8BFWtUdC-W&zr+61$M zc+R1PYPgRuia{{5RBub9Xh|bq}lUT8WqY$%^ zM8kOi@JbOZ!OdvhL+#ny^=)qA4GS#A_W))9K1JY-2l3I@|wmzQ~(FTllzaD#au=`x`38L^IE>hUlB`0H~8 zB;J@@;Aez>VffipQl`^dgAl$*BU=w7w9DJHdfw2E8DY*Cnj)uhk6ztm%Bc(~7d_DT z`ZCsO!6=qgLu?M6ZbhMbI^JdU?e_TVj)|YUcQ2F?U)w8a_^>L4oU*hMV zkxD;dES2^F^m&$j7|g`s^YExP+%AeepFJWQN$2*nmHtUP08F#Rqlaz61EzivC^#j-S5 zN_qbqRv*jEw2nf!fw#1dq{L&E$9t|#Ed+Bj0JhcD<{6*Ly5qWWp;TN0ZH>eWQ7)Ub z-A4M_Q%?455ro&A3`iL!@yHQbQ%II9k>(Au@OnHbj(&OXwda}~Ni>x`rfYghIMYkk zl#zR02rik?b01FQ2$}61_mmSlq;82L_v{eh0|QYvDm=~fKu0q!YA^4<_FNNB6tUaP zmzdHuu_PSXA#3i)JwXH)A$ANWIyJiN11WO;FYi-Bxo429X(Gid`LbY=zCWjOOxkvP z+i&1Y7Rg(xi12S(RNi`_e*fT#Prss{@AE<)Yh*aVi$x?T@OGZ8#_sM>C%I?qbj*Y~s? z;K@VE7xtb4 zT>*`t9x&PrSOW+3=NUW+pLNps27hmgUj<5G5_&oGAGBE;KGE~6c2=7JU{SziL^~gP zo~dDpE=#pF+~luoI+eH|Y*$Tp{~V_iRdgF|4xiuyF)4U2NVy_PyR9{rh+qVfL<5?S zaVnGBbi7HA96AT*00l80`<~giZ2If-mP7ZXsYH?fx-JwiB92f(WNK1FI8N`j=FB~% zi|t3BuRB&4_$yVn;enh@l6C2xqWQX0PbJw9hF&O40>5PU#G|>V^d%*_1sv3>(nXPh z#=|$Z9G~xwpm7qycI*DN=b&ca$KU~7Cv(GP_spij@yhH=n@vD08J)#@^O}) zo+$ak#h}h9Zqyv^!_?+U$V+S<#Jc?slNVtnB4O|*^ju;{MS|W>g1S_P0};MrAc{kD z=wiSfG*K3TxySiC5N{#i3G5B4xTkVBA=b=hBBE7HLXU(MsC#!pHV(%jYC@#l(Mm?) za3W>pTdE_gc0)|YEX02%othFt-aS>A7}a)z^Poh)StD)L2^1V{V?}v~qXnJ;E6PvD z83jYCEG;MON{GJX97<@qtwptC<681UG?-R5wF3-Az?q9vRY1@-COg5e3vVopSH{i; zmP#GR&R33o9E1_8l#ZQlz&(ePm7)vQ)Y1z9x&iiFLoaVa$lyUfggi{)dlJI9P-G4Q z4HscsM=T+dS+bBQ0K*GM9BYk`4UHo}E|RMcrn`7~03fGA2_=e0C9=5em|_*cb0#VX zAts1dj8sOBjTbLs{&o`oW%sw+#9p7b!3g^f)HZ~iSRMEpIu`E)A?WA+!BUz8&te`@ zaT^6Xqw>frNfcXzdXCDYnH5V0(}$#IJF!$L#7K#}hoXSjiMAuZd2ez9R zlBVZr*;q1nRVbxv@L~E5io*@Up@7AMc*({OAl?{jmx#z8s7e=JhzDX0yPLBdUm4`Z zddZa#w!CG-u3ZR>&FdKQ1++~WvbHi2lK{9y6%XkIX9=t3Sj#6BY`2ZUHEx;hldFYP zJTOHWe3Yt(DsLhDP~MUF!J;{tc^4BtgyeTV zaAicm@U9=J=S~tXh$jg55F&?|T|*dU4Av*0+%0!|?4j_uXFVAt$yj}&jnlDAUSh+V z`|t+u3b8t^nu;|UpFTueU{wgSW>wtEZYKimoit7Rn683?a>3{VQQ=UGC+fDtPa~p9 zSoVX4xkgQ%0;797WfDdJoEF-?krOI9LExF0w#M)LyUh`W@REQYLNMeuatCdeAx_dNMd{fNe0 zaH6b?R2ZK#h&K}`j-DKN^eM3(a4D{Vc0ZpqRDXD%j99_mqDIu}>Loiv5I?A$H+imq;pSR&ZsbEgEXF6cK zkP|&we*qEDomk_6_VLMNfdTIw(F~(d=W$yd0yktK60E7}7?W?}E=;t-;sp|L*C0~n zPyvOCXeFWJVzVGy1?-zS8W!+S0JnEOy(mo3&#Vnz6+wu>c49MCBEq4ax{!P!5`hYo zcR1L}JnboXSVRPj9QKR?7}p0wkibI=>1-g)j6i@Gs(qX(DULx57%H?01gKi{Xjg|c z#=4^!9CkSQ&%J8qATxfBD@FhFAP{O1(yo7w2*`y9{$RNvdIIl8wS{ZWG~dDU;Y6{L zp2fGPP!6%q$QZBH@y0OtqQa-8NL6Aj_^NA16_HPx(-)%OZdCR9T-Wl+P#nl>2E$`E zjpiL3szxwtIQTOQWx!TI>=9(sBPyUvz6~YY6BM!ONGC+-VC_0Fm@yj?6qOE5q98a5L5!gc1ZR**MBA9ZMQ?D$iDvFWWfn`y z&80Q+Bm{Jcps_lMVbUSQtCT86+>dwz8+mf{z#BnGGh{eqy%7Zc9)v3!^qC>@oF@_q z608|JbOWp-(Qh7c=Se<$g>aY3#bO0MhD;BwJe;Y02XE}FHHEs8EeF5EnSBKGQi=bk0ZFPL`5RI zuH=(-l1xcJw!#qTFt1c-Cl+o*2AAm=#*} zj^bi}QCN=v25%57*SE2DZc04j~&oHnY>n^VvMJG13RK@?~EuY+t)CN&ev(4 zy@4N9se~E9Aai?10x}k(vk?+8Ev~P>K5yd@+nj0-c_`=tA~q=zl<)mtzyI_I-Xb(j z*m@DSMnEZS`)#gk-}`cFQJ-osuRO|6(-aXGTyMUv>auE2IYtzko-?g&T`{wC=q)>U z_Q=h;(u-fdlESU%iNezil539}ZJZSF^hVm{OxPth>kZ#&aP3n;kQbs9_Ha>6&Pb%@ zECmMI7%krS9bYKo$-G;nvH)s{~+0DkzWtZ+CK-RJfs1{kuJzroH~Rsuq3mL zVVwvrO(y-WOHC!zb0(@a@TCGzF-S&uQ!tZY7ngxiD_t7W*Ma4oC+`do+o+{+A}vl_|%4c{p zSgfW9%pKQ^&|No1&mD@(!Lu*%kny*}5`JP8;^Kx7z`rp^rqU-!!6OkIHEljZS> zl09aW?aTE~EKC%Y(}>s^r@)xuE6SQ2Q;>bw&qnfsZP|ujU8~8o6b-}|V04AlGu(Xz zM>2}}ApkA<%HFZmj=8;rr4}=bd=^2P(e5&ElpNyhig@H=8y$nN93AIbjbC|O`%j`sXeqauvDS-LnG>?;( zSrTJ!ei?JWF4U7S5T!>Ub&IOCA z6hh*|9a5_o|4CZY)Vvzc6=ZH%GiC`~MlG!A63qB^#X80=my6EPxK z#3J+xnDvDR-&9f%>Mu-ZU;wC7N88*G$>4Nht0^ZMF&9{uHaY`hdCcs!pBwj(wtK>k zXE=9oz0%W}YYWqos-7Zl0+SzvKnHx9Oax4wTG9HRd-Y*}G|`h(SPuu5r7DDc;?sZt z8*5n>78l1-_dfh=HjZ7d^Qy>_w~VQID=6Y4MuhBJTG|A6{Qv7K7G6+4ax`;6N)w`F>2trI-YBhS;N}g#$CEFV$RE# z5!P+eZ^b+%)(;|}(BmBhahV*046nm^k{+t##1VbI?6`5j-S9AZp_NesaqOHnJ^oW= zl32DSNuv-ZoI9>_@p4C9awr$ov{A7bR&(&5rGPlBN)xP;L*cV~o|Np!U0vmgz?!EQ zJyA?UI;w`L`a@P_DCE5;J%lw;aMy$6NDA_)(?dsw*B27{44~4o*YAmpDN;=*f+G6w zVedWa{oqJ%tX&tUmo!tba!EeAAw;9HS4TpS?Ne!3UIHb#8pM(`qsycZrJf~Fh6tx5 zxkM%d>7jkHQlHleTIp=NZM@&vj>YkBs`&q6=her6*Y<^++EgDRF682g3$9DLxsEhYFK*G)mgZ39?XQ}m{B=F59|bJW7`_%O{`4WlE!XNuA1=Ko$+IzJgJD zVeyJc%@4ZMI?boS7Z{EhFEFG^V+w&sLdi~@tkf903NnFO$;S42QB8837*qUFZJzqp z{NqC<-&$4WKaW#nbtOK3!$9@;Znhr-=H6RZ zp{ycQO!lUyaka(FN$7aHsn!qOutyC@UwDSON>OHfotHPHAZQw_Y9be}5eX}aHjW^2 z)oT}FfBS{#e4ne+Ciji4 z0bZeGmFg87+7ZL9JEz-g<+8F{S6my~s*N^2s;g9dd9O>iGit#t+&1(MdP_y~DpBwTSSkDX0)yer3Tz7O|=B!*maS>^u^nidJK)yOw zC&a1x2!Y{Mv!midlH=YwMPLBk-2en?kx{@b!O~R84W9T8o3xUXCQ4s33?VAE71_CT z+^?v+DyOY7CzI)}@QX9n30?)(;YHLDy%5ZMnNYhKQP9bRCs0jTMXj?=)ug+<$qO+N z!GKskdMT91g78M>T?k7L=!4TE5*)~qpa<6_QyTp~ZiTAQ#Si~AV=)Np#8{5F$97bz zR~->}u(&hK3&!552==HF!-K&Vm11nN+!R9&D37?NOabY<7EdIg}y%aoSd$+`3AAPLOWmIeW@lgVXK>f5#L~} zkv;2Jn&S=Ld3~DzCJSaWbh+sfAiu${}UV~zXDI@kYquuL1oA*nEAT zAH0r8ZkOiD`jkQ_@uXs)_x{)K<8|G4;#5h~;%aYXM*rJ<*WO>Bw*{BihB%zqSodO5 zNl0F@_qM?60zMgM*d3*^({ZDmL7_xHz6P;Q$l$bsR6j%yhLO_Qq6;8!@cJ@?@&U-iE2YIH+n< zH2oVM`n7k4uQU$^?;m?SGxJCi!(?bOEe_Jmz=kvrOychMLatSmhK+kZRjTNhhdZD* z9ny@trDL%)2TW#)vNUaF!BCBt!G>s_{Rp0RK-UM;B}m9Y`qqj&zTGBA8{Bm`Pgb)j zJ3_0Ic5_PTvaBj!qfvDs2u0QRXm+PP{y{|C-FZe;1_Xk|gu(bh1mnYgJk=h4FKB9( zq^GIJ!wTN@bwL^ncbvcP$Ap#9f+~|H6;Wo1yrQ-$aXO$lF1s6*WontIZ8TMfREaPi zxDcw)bhC1&S+Sh$NUl(W7t&76pI722yPtZWZMa=niL+=rjw1~zz~Mz*{V^WFe|w>4 zQjHR3XlY?voC9`eLa7tESLONyGkrdeogyKVaGb6ptURaY3GfZ|p#93+?A zPx&!85j~4L?$vsDTW?-IHznQHoAg+o_$+4-IYNrM4es@8k*48xmooSE7bY(8a#Cg3 zQTsu+ATOmQ>SPTuB{0b$QszZWSwOrW^XIHIsJ>sN;MkSTOl8kCN$6Nn&EYqzlUTNO z$=p+N4qDbgLM88$LbhDeBJkFqi%upMaf*e~w3Z0!&2#RgPFqym*Lct}hx{ATP7d0l zFb~?~MG&5~;kXF-%aCj&SrK7TJV5WOmU;SMv; zfonZJ6yfN&^fk!#g;L)`EIxV$i#OF>6DYGw0CwlMSf;SV-FP9S;u4jBg*7xg^6;^no0mc+F#sS*!g*P0u_4^n9o!Py&(htoIie38sTj`1H>7M}f zA`12O{nzKc_5=z)aD+^5-QFr?fElTV^JL8T^7>2A|1vsd!iv9Do*1&11{h3OGV)eg zV|kw`{MP{?yH>atQJ9WYx{BX-m@9c3z}mr+wG1fuhio5tKawto-b;gA`{#mPSNy4} zrMk|^j}u)#&#tduR(D-JRiACHo<|wAWIdYVHuue3x@P=|Fg`>cvR2oFoF2?)f;>d3 za+{BL>RG5mws>8zWvGGIzW0Zd0jm8Ud-qT-}unRx)|g z;LQ>Y)hp1?AsdNLY&|#od3gzUpWFiBz1@?k*{(#K$W10TnE8^o)y!TO<}5?vkR)PF z*=eJ@_$S!Ktw_q!HwSZmy=g4u_OVE~WYs~3f*qOI-JSC!l|hVN@d!b+;8almVj1*c%zukI&eXgHZR(^BEkO(bB=IEg4TO?p}u^@_~K37?^V=(#+*C8hE44oa+ zN0?DXHWJun>pI|0yGfm-oH}aJ#`kIpQ_s%S8I@@ z*5Plr?wQ+htvB-&$P3>uej8M>JMx?`y{t;~_*sa;u5t#sNpf)qDAQ1i#4>-Jf~MHF zD!kRYd41l#uEpkY95M)JL8ftX5WYmXiOQ;~-6@fa*CfNUnGa{8wSk_3``Ot9NhSL|+_UkQ;cvJ8IiPC?Pqw9k z2a$4gCaNGBejvJ$Bzm!;quh`-JNxagdjH9x5pdCXt8KJ&?+bK(U*plOEC>oEW~uy& z@#6Dj`fzah`cx@|ZD_lK+k8Yk#jD{=->_Ttq@{Zw&+&cXb&&BynE-(2vCo%TQ*YIi zMC`a@a5`CvD-={_Gw0-$S)@s<{zr?)`7K_xZtFd8T{$ zrMz1gnx9S?F%CJlypIpwD=OU!CRI6#@w@Q6vk+8Z>)CFvd*0eo0O_rsQP+vVP7+@? zIJ@YMSAKn;GrrX?x|Ju&LR(;MoFN!(-6@?tEw8^E&b_&;A~PT2Px}!p^Ei@BmoKUq zh4yp+lR#|0O6a%hM@#n{&-MFHwzD_{1vgM8vM7M;w+!bX zP3#ljKQ{Quyg(l-R2Dbz`u(Rv zaj8vp$qQBC1qz@R-NM%W_)bR_N{nbB@>f!SI-YK%O1gTk&S zHeDi4T?Be?lS=XW2+5s#&_y+&>PKWRV}IB&=i@ek?bbg9!nK1Z1p-wNznp{PtCXq$ z`re9*Rd;blPu;DqGO3;b+xs<*XKtCmcI*H3d8<~Y0Y&j!8i^buGP-f`tyWo0?)r#I zfk1+W+k^-SRz1Kj3J7T(|90!1r+yrWoiHXg;$|-ySs^E=@sg5rYt$W1R^mcw8!Hl#RFkj)(hUY2+I0xSy;? z6KR~pC&oEO42|%K17kap4S;ms=-Dzdjsf4e_PpI{+Q}Y{l4?9&m=5Fd+0J3goR0nw zi7MbTUOdrm0)S(74%(GhjY*k{b{JLgRdukx5d3%4M?*FSW#goI2N=0sz-Jg748>I+ z$7E;sH3{&3Ef6S2 zIVqznsSBUWY=$`HwLwujMt0JvL)=DSkWL!5=|JPp!J}TUr4E;=dD0WIjhRjE`4&jr zrkgV=F12zll^(8|ytG~<@>L5*jupKkoepr8y{daqW@F-FWl#lT|I}Ndo6hrtLFIHo zHU?=jASf%WwRAqtOw=MA6=aQ9Ixi|=Cva#QQvq(37?-&*ee*gTg*p<{yDD`F*&v`Z z!VNJK0#pUmudx(gR7@q(;YpDmHy#t;930s)(e2jrO9eB6((4;BCbUmTR%KRgVs00| zrvSo0KoJ63CC}MNq$vV50jPc`Lv%6(v}vE%{L&aJ&!7nJ>=BwhwNR6Y(U#Y}(UB~j(?7{US`$8*BO z4TK3|&4)b31iq?VBEd5)RW6@`91y8j#<7x0_`7E!(~{L#K&mJh5P%0mkc6ypI4?`Z zxp?!7&jE8Jlo-FVSIoQ=&;%B-a_v}H_ z6h;zQ3&G{ny@2SGZ9vSx-ODJ#qLKl4jZkLGY`0tgMDuFURXV`kz-*dA@H+t%9kdC6 z8x5C0d=R(q%-<`hyGfHq)~^6Iy7EsEK>(ErgoO%R2%Cn4BpnmerV`6pk-fmY2?U@T zOfW!tYsJ+KtO4n;xDrBO;t-;i1t4Yxhp$>KOiW^%XOjh33BA^63}sy*oSw#*q>d|V ziE1N_k~y!Sy%tsX4oDb7kW;bhcM`+BzU#7j#JIkWAJZKITmqKj6f!t#ai}iAP{E$y z>DgGEq+$om)5qe)NKQQ!&RQi?v+BXDC15pMY!0IMqpuD!>cbv#+^C*(;@0wc#y_*L ziV(b*oYEQP!}qVNzujhs>2}reV;#`q6NoIl6jfaysGh_SY$HYv?gX4B#`jWVCNCgF zC5tIc>Q7Apw8YehrqWg8_FBgFNlbEzt|CZGv|}N+t7?l?BWssnY@Ilz#M9#O=sv!n zbnds3yUYAA;blNi?jS@70vvkN4q*bY#o)q8`b>lZiHPVSE2u&s+*AeP18uGd&#VxOu+pZ5wlPa_7jGZK3&Yz!JYF}@jv8L| z---2CS<->uBYUg_d}bS(8HUU2OHo!Nlwab!6x~O#{N5gfPHgn=@K}?XH=4-tnMAC? zd)ee=`^nFlAl-=HLH-1j$b&^OX4VHm@Cfe-Ji)y9LWoe-5io>RSO=?rbcO+;wq4}< zbVA}m2T+bcLo&gG;+D!mqf-$P`i0nr$WiJKsu(O#Sg2AqW=V6qG~9669~6v17|3v8 z3GI*YOI_rI^8g2Iaq_FG8XKxV4{Zc?al{oifu=xaLT@H}L{(OWp}kd>UKWq5c^&@K zYl}Q8FR2V_XSiI2qQ*K3%pK?NjoV4^YgSKgFj=yEBuX#i&XEo{CxA%JxBAo4JfMdY zTeP|?S0(2xNc*6A)*a9W%4V=#VlNbCnR;a10e08b-)_@;dC5YQf-WB%J%escftdY0ULrKl@1-E<4AS0t0Gd zC%7wcX)<$2m{G%(4vfeg1PVcFNMyG3AP5);kBK?AO5fLsF-rR!%abAg#-osMO}LK& zZv4OqdB%}L*b;{p2-|Y4*ZpMmHPz%MVj;9|t_o{tKE75c{OH>6LR}wE2#H2wY(pt= zC;*<&h}UbDx{L@)tP@ByPr*tUgCO`7<7pBz@0lEqb@SR`_+Df9(NaR(16Yitn95od zA%}HGm^?H4!*!g4QmzRZvDSl0nP8OMzB<#2iJMu!~^!E8f}>(Zp>L}fG4X=J~{1Cyp= z3LsbuL_=0I3=D06m}Rw*&!R;z!qO+k%#vMi@l?gx%vrb0org%A@MZWo|i zF7Du*6ikz5!OmDc0=Olw5P#0j!#mF5Jof@hEE_~SrqFp&Whm3`SyUC0{?IOiZ_U(; zM|b;qkqscyeqVS`fu5SV)5~nHYJ6{hT7uLKAGs(DAU23bBqpeKE#pkjDg>Yx0 z8`PaUtdiWsg3%s&y2!T>RC^q@AO9WjV?|K~^bJMbC=rjHg<=Q<$f2d<)R4*|PYDBY zP>n4!s*BiGEUep75~Z+$9|HT`m&Pj=ZUAY!Ei|2R*U74Xm4hUJC43LSrGeL&wO*v~ zv*hMj$8-0j0icUW8w3p2VzDw;&ni%jHK;n(SX=n2 zxz=6xSr(}1YOC5|XLcBF^-+~2=`B#;KkJFoHBG!kq0A8un7Rkas5N&@7p`@RzEfRW zL6FugENX1k$nwiKZEWY@iz-GVv2pkr#_bq{Fnwo>Ha;=Du#$!`^|8~DQ`vUg7BXVp zykQC+S;$<`t?R=p1%V;r!j-&MjAP`fy}ZxdVAb}ek&g}P5?yL(6u1+OXizAR<`;na z_&Y-Q(KEQGGdrYvqk6H{=GCn)-*_@dcU-!tI1zjQZ0xVsLTJx+e!T)>IWA-K<`@4S zjhOA69UBRjjQKdarf2S)otj^8mG*aZuh#I;KOkSJ$d>EyT03VK{oQ>5k1nvfd;gbp z|78@Se68o#v8qSE`mQ&>`1d@(r^_yoC=Uwr2wo-?9(82EE-6XrORp$uiZ$H$u^LV+irFV*x>-V3E>7E3IBRr{Bbm|15Vw=}gFon#* z&zax@1i_=bJ2xFXN4@oMM%D+XxLd}*-TG&|(zOGH(!#2T>#76-BOZVg#u9e?U=*mE z`!m5OSZN|^eF*5sj5`R!EcCzB%i}is?bbP2?B(ln?*gL-Cy@f7tBwh4brBVuiPeAx zi;P!u6C}ZPl7n3`C z(S}V)u$9;MU#fST#5S8aQIIkbRF#<`N}je*lXuYAK_X{b-e<}^J%gxe-gTH*N*zvV zFqg#8bi#Gg=qFGEbSD#4a-Xe&#hbvs=#``eDY>SG8&lHfX;EU4TAAw`6~8zg-{xk>%VuukRKTO?`s~o8GGPd9bKX~Aq@SS0C zK#(<^13~bLEUJ_R!T|A|m3zjky|e+AnZK?a+0u3JPudSKcNF#!azd5)#BUG0+QfXl$uOW z$d!O?3{j>1^h&~r!MYQHssNgU$Q~?C^T2k|m5%E;+)#{&$+}2qT^N{R*_g@&6G#-4 zH8t8sm~VQuF8jLOR_^t=4*sbci29uf?5yNgXeSGl{jPDtQ%6U9Wz`HAs1>a41gr2Q zS*h`9vezanHLz_M!vHHdjpk_&9%=L(^Zx7pud1@Ss3-tIKo~SR&AEu!3TC)1i@vSX z+JpU$v1r^;7W2aUWjp*e!u)ST?i0U1;w(4$dkXvqxQ4lZWGLE@23A%N-lGxExo)@q zUn*4zrHWcIv(p&M1&0ao*t7gGENx3HRqB^C*em8BE5N}BTQ#g?e{Kp9X1s;MMJg+; z2Ock!Sjmj+R-q&?i=p@rRvO1Wrik}W#t?w!xKoVm>&$lH>M-1j?iTKb`!k?sLhLPb zqix|j9AT5fI*n{arhIot1;_2YD6bg)YUH&OUp-OzrrDBk@32%3-byR&iNq0ku#P6I zIWR84I*)55^OBo5HSQ3C#%C@B%*%5WS>3Y6hr0;Q6ttu|b-;PXD%*K@eG-QuCkQ1q zuSnvISp7;rIWN%x7DL!b;M-+kCa@obrVcSzf*AmFY|tD_!AbOj@=$doLL9QZ1?vgn zY|yqQVy}Hq!)~-NbPxxZvylhH>FJ+GyKT?w^EP1>1E>zuUX#4hS>Z&3 zHqB0SU6K#NhhPT7HM%Ptxytv5TQgTI0RV^-1TB|IX z8YnTTPJzGU-jWpQOBq%CRx~6;boZ|?P|`e{b5T;xTaTs5qDoeSZ;fwzw8x57LN(Nk~7?B5+piS8I?7>HM zQgEWpApY8f=A1vg4o#I4oUn(yI8Jwp`^So!jMzPUeyKcaY5wVT^OQdaN= z!V$SVg)wDb(Q#?@fIk#xTTB(JorEs3`*v{&5@rcI)5amd*~8`@qAR<-g_C zW-{2ORW~rPXaiAjWssUees4TpRb>uvrlXS|jDI*4)eYq51h!lMe!k8QM9+-w0h1_V zHn5ZSrnu)SOnaEonEOx}dCc*2G108yG(FC8S!`#2eII_@Zk=;9<75B&cpirbou}R0 zKZJ`fYA709^{kmDmJJXx*Pg2G&7HbjOFHXK(Rmzv^})w&?VY2!d|qcG3p1Q@i81D4 z>Vm#U41hJ^Tis)%D>+?l47n%bAdJG1oUc)rf?;zijpsW0ZS9?-Nm_b@2K&+7WlB+Z z*jeJ7-@Eseuk&^HP~d%3`eB-6lOoJ=d__4(5Id}c$kom202dn13p(HT0b+Mpo+&9$ z2b&EghiQ{VyG<6=m30BTccyl<-QMT5J*YSXrRJ0FXBb&rsN!Z8;wf{RauFzzH~FgL zF0Y^Z*hQYB?LwCF9_`w8sl44f=V(|L(&eU`5l*oRGXMeRUFE?DVV8mHjJO_G6hF4^!wUbI}W?j7uMy(ua5 z5c})+w_E=-|6V(IMuqU4k`-<2-Y$8YV2BUdh5^)zWNmVk9+G|kosz#jZWGvU{c}Lq z4iwl(KZ*-iya3_qvKMZ{I(Nye4MSlFNp6h?u7q8(^C~}1$-j<&yLC?jQrxSA=aY3w zTRCJaOf6}gq8IHtPT|(_QOS#fWICBrli`h`px?sZ{ zYxYyHg8autvNND7osxeY|90!%ckApx+Yd!`m#jFyW1f%WV}1#^uk&dQ*b;A@!HRZ)@Kg z%Puu>8Pt7am#VNha^qa;GJH9mat#}ag>$V>QiYT}J8stK{?dOm8 zvtu~2d+fKJT!ZU&e89+$?V7f@+s+?v$M5eTiDD_Z=5($%6d7^95Hug8-Qqf2#tw`5 z5$Z4RxPWN`O0pc3!I&2CMH_%TsIoPcZ&U2BsPZf5dEH=MyZ#mu0t(tx46I2)jXq$r zNI6J!I26LsNlZ!pTtdG#HWd>hNdNG8cx>qBZ$cR=h zyptn!iv%4#UchyeJIWWXP}1#Y^dGRK2cKOfdS*((Vg$S#%Q-mL z^vZ=IVo+|@#`LpcsUPN`TBpEcw0K+q#i zlZe>JKVCGe#SpI7iM!1iO@?QPgtISa92LuPF-b*Xj+apU3N>UZSB&~@l^DuG(RJqr zWhWTq6$HJv&wKmzQ-#ieA2*N9NivruL-m4UQ6(HE%H);@RXKk~Oc0OS44qN<$}t|$ z;&N10v%TMc?d9p^z#*+tC5R1z3krW&!z~TSFq^YKI_mP&a70=fJr{74qX@G% z3z$y=a~)+Xc9JAZIa5Z5TICui0rE;c!qY+yrTe#LHDQ%OrU{-p;@%b@piob-Kd%r2 z-A7a!2bL@%5?-3ky@+d`LnHx>1ZNd;h$xsTif!;#^(M9$`$bJy(a~nKq#g@#V=!2x zsNA*CS8kzTvb@&7Yk#2EtageBz<|3eYy=#T3Ls-c7)K}|eJB6fBBGr%R0<_>dM748 zc4}B3whx*O*8y$QGAu$6OG8~9T-VR;x1Od*WD> zkrLf}Ce=pU{Rx=);x_ZnoiWrar+VjaYe9pItaxiJ-hROQz;AgJ-;5l1B0jC0qI`0@ z$Y{WcIq#aSnl=6YF=zI3j>5-VL<0~g0miRg2jm@QkD}(TN7`InpWLbDIAlXrAOJ); zs^K;!Oo`}mqfFR*dYouqc~qT`!G$fGjT9iuP0scesPxzeAZfSans9r4h3!__tv%v< zb2M8$U{d?4VBAO!`IYb|B(z}Sz+Dkki)39IDY00Wz#-PyR&_iTGH}Gb%+sVaqqBuK z+@R$3=61;Al6u~S1a2<>`qNOcHc*x2%M(P`@$AG zUV@gM6A9a`=p&u#DVT?T*3+R7Rljcbcj**BYK6HO2A&5E`eoeWl>*(hQA)Wf&>eOZ z5)h5Fhqk;tecaoxAFE@P!|EM&8v*ulaUkuk5gx}$nmRj@P%JORWU7&f>dg0J++Cgq zCHd*bJ2HmyG8|Lh;Cgy$mdj%`ImQ|$t6%|&3?{l49Bi{lo&EYLxXblWJPkU7&x1PjDd1?cKGA{Z%rX=i@3qSyFjQYaRQCw7^BLYLC==- zYh|I#pbx&@8?d8>7i)P}+?(``92#Ct_3NAXHIDcxz}Csi&n}DI2V|b}brs6Mg+Gn! zl*$a{hx?fkfkGAvt$NHVdOqhG zM`nN?Wru{yP*TPyzTJO}(h?`#X*gbSD)_RK!E3d~ z8t$C%?~}2-E>HKf+1lx$40igic!iMXlkN$HVXdOpwlRoTz|0(SX}9~mdt*B*Ymoy+ zaX<=A_wN1_dP#mI{CDP!1pRN7*!%l~y(7ENYhyHfFR83EoMYG>W>UE}4{c?H*2~k) zaTrTJT}|ZPa=3IAg3q^29+z=c2gPQAf5zqMexPpCsT#6}A>$#}N)EGSV^XAxV+%#3 zYAG~8+PEeXT<9InlJJX6iW}5GGn=L(1tC?pu(!-&^33jE9w(&Rp?dKPw(N?>fZGd<*?(Dh1?`85bI!$)!=rw9#pYpk}T_(qLnrm*R>gmhdcIJ3dg6D;U*L^;Wz z>z)Dfhp=g7pT>ed;@T`xcoS8}qem_sq}#G#4K&m5B#UXCV5mg0nAE}G43YrSu!oLu zp7~Uf6HT{UF=mlNmsUmF`ptHgc2phdAKvZ_?(Xrn5|t<@_Ix}93jtt$AE8c?Otw_l z;h*b9^Pw9*2|H?}Hm2cBCSTfDJCr8I^6z5m0EMlP3IiXt5sRK{Vr*6EvD4{gn>^do zufzH>V>)klu{X-Y4!jze@9Aw$k(m{>AKvesPJAqZf;n*@a6T9v+3YZ!o*01l9~%Gi z)OZ@SmcwG5Ky0G>0EAd3_Di?%sm(rH%LT#`dFWumy1$Vz7}#e58ET z4y535dw_>h$Up*@X(6qt5f=G)TIt0npFn0=H&ra^o5VHO>kS7fYzeW1E5~!>NZsz|fgubeM{NL#TF`Qj z!1tseb-XH-gn}1gpojY-hj;S>m8_RCRwg|c(MeVsB*a=Lvz6e_pIdAuF?OS11IYOm`{x_z8(&}MdgyaMex z-5Tfd{s2IMRg4c1z=VKsd|&Ew7NL;dw#-lDc09Yl{TNd5XIetrAu z^!pFrefQ<7fB*Kw$M>&Je|q=hAHRI{Z$EtZtAG0b-N$dgNZS{G`L~Zhe)!${FVerZ zy8Y|g#;;%f=D+@@|DvByzx(pl*CcT@36h#oy=x!}hfje-DJdj0iFb0LQWgaJAYfo# z8Esc&_6pP>u92m3Iv)C!-*K(%Kjq)*zo&ZqqmTdOs=xioyOb4>f`f+tty{a57s%*1 zC9~+gI{o_{+NhwyjuTKyKI; z$SG+j4HP}stz*7YuH)IdDf@Mfm5S~C1k(`k_1oKip{dOWh0+$IT?I=*$&Gl>D6?zN z?F4}Csuv|RA9z_A0lB33Wq)-hXI7~M&~IH|@e7ryiW%fqZtu&Z{7hxO{z>H?YX0y| zP4VEPK6R@Ag>Xr*CmLlJTeh8X!Xq6LLInK05rxnshL0T+*;{ra#92-lin4}ss z8~{rW5Hjr=@uekV7t;AV+||;@UZnGj%aZI)n_KTHSdP4#F73#n`HYn~2w z+1@qzbq|?8ZkLm}`*N+Fn`kWjv%Jb%Hfn;W>GGoNO<#_hRWZx9$_UaF)0o#o-3pAU zseqB`3gUeEV5e2P9N@C5;3k$LJ5o>r8rFw?oIrOA$G*bn`MI-kQ!l0?u2;~pEEA@;VOIvLq5us`6SQ@yMGT|4}<{`=frDB?hF2N9Cv>S;dyla|qsD!@X0GFRK- zj45yy9;k~+lHZj{q91X68(pS}!0|fyUzvpp445Wwq#PlaJ1_#Q(jp?DNfScV}RxX~AS#5W} z4rj5*SIpf5Q_V?qpF2Epg6dX^f{aV@8i&)Xu2lLC8&_vW>!>e^ND>QizEQ4nk5{LI0uCYlz8|o? zfn%uRZSD$YsGH)ilm*FC5E>f~@nH>z%0QwI=uVd^*=Wevwf3v*1I# z1mF71(Jhq}%-Pa0o8i!#^H_+yzRXx(_7lUUOSu#y{&nD)htqZ$6&> zD%`o{_yR`FJHCo)#(S_uwI=${_yV4KmPtN zKm6&-S3msakfyi+{u*MHCAuXEt(!`@o@$9A0jbnRcid+-1I#mB#X z|NcL}`|kU1-}&75FMs~<@yGq}_~ZK@{>S(4zIp%O{`@aL?vM8uj`+NE_i63!)B3Cb z$6Mq#`o#V3AMVe{53Td-SC8|iqqwJi%44_VMVN#)7+P>>OzGEnIAg5OaqJvU5}Ts% zXa~ne$Lx%)qxg5Wx6hr_6K0B;kC(~EtjZp93o_2Va>3A{y@bm3S zTh+g}zoT-3KeSuJH8Liy?bi0S_u6P}-%PJ9*08dpxf&<*Yil*Ep}(i88oJZB+5m^T z)kbF8wKiJguC)>6*0na`DY&am{=AO+%^#k2{{6(6h=N$>9SJYl&5uNge z_9vr|k@FFsVmHzTg{wgdg=G?S#8g+G4J|=3*mChL&UL9lJ?gu;${e75*=;ub(xZdh!Mm%w@vm zF1h@1DI5ocLWYCU0~E}~Cw`pmASt`O{O>v( z9c}uBI4$=>$fQ*vI4$|ws=$fstzngC*t;9IKD6zh-hKSx!+-or_@ez_)lNF;?)&=b z3#EGIytjpjcXmUkI{;!WHetE`@og>rQgo4T{}ccQ5$q*jr$u8DM9b?YBd6m1QwC3BmL@gSMzQu zVl7$Fx;S(|*-06W6&)|rl7^a@fQr;D?(aw@H~U(ce0<6l;%b_VpI^6X`A3=gP61#A z9oF*&bi=b-R4t?iwc`+w1p99F_7e#ktQa#nYice0HY(Rob3{LHJJ~YP=?DO^YS-7@ zEUkp#n#qPsEcPW-V3$P>l}MyWbPrL#VFfmsI)~OfRXrp^_4^4wc8MbBqc+?yhy!~O zCH!U;`_@AuG2@vewi$|tMvJA;S3D_SOHWJE@h>LT>iEIV47y zbA_KUM_AO3xX`9lKdtlnD4;VpaEHUcy%+mY<@SELL!kWz(|gX21&dGc183x}`@&Q5uCF3{$o zrz$rNE|(Zf0&8ZERJw3jH@5bWBNjhYcU*SFa~7)xjsD-jy3qYm0w$|xpL=iab%+HI|GxUMzQpy_!KZc*lOx@lgUPm_JDRg~ zIdk@>X!<9kKp5^3)6dD6h%8>{%Qc{+)oV*0kl{*4X*hybdip`>(rhdD;JPXvA+I50 z>gC#vTrS5|#^YlbL7}aGreq$b5rXN}oaQ}{Ci#%drS{%MQJ`+#1jziV#hX}xBj!3^*t~-zj1^Ic zl@*+4*<}My>a{gJzkE_cfm#!!hMv1AQf`XZf|5d;lYMausaOn)SYPz5IRd1B5}Wx; z5-fu!%UvHsHW)S|`Wku*m?cVwfOROeu2Zp+aL=(MZmzn_mg$!u0uDR zJCmKpT)RcY2F-EP==(>(&8VJv*orG3@K}Yttvaf5Cuw2Dk@fR%OrRnQfOtu$pGbS< zh)O9(0qK~{zC_|9g8cyw;k5_;R}w6}9*(FI_hrY~I(jsAZVO?3YAr}}pidqM9QoGO zU>kPuZX+9|&4_b#a(od(a%3~zT{{E?fXl?c$*a@NUdNRR2~q@?%> zy@=+~)(Z07|5~c~wlx(<#csD2Y}x9?{zWXm7OxBc@9m)y3Yzd9*!QbwcJN@&ak%NC zC(O=a+2rnUt!KF|)AJQioweP?C?!)&#zCV2r_x6apT!WK&kbHzWjX_co`O zCJtSZjoL`fFpHxiTsragI4Z;0gR+Qstb{=6W-)drFCj=ue9=kG5~_lqo?$;$1hT(Tb1wk208X3W-4VYmf zec?gZtq>R?k#z$HD6Ze@5y-dRkQ6q&u7bZ%#MZ0wXhEDBS8qWP;9r#%VDcL;>Emv5 zXsi<>UJB(%GA%K@=%QFoN6-U)^#i-m@KK0i7y5}?bKRZHHvRXxC$oxOrwq)@KHNel zbiS@8Cq$Tz*m<{o7bVVF!H$dP1@jIOD$3h5$!m+mT66D~BRLM0J>Hfr>S~i|nG8$l zo*+P1q*{<@#&-=aG3DzOvu-M{1H!><`)ioTf&_Jb9}&q9l1?Y6_c)D};2f}Z=tM7N ziE~QT+f50xdUbgiSZiqw17npjG(y@axP8#*D{ukux{h*G&7Pdoij*q%d8BXq`XCDP z<@I1JSu?(+nbn}zW3rkTu$y7kLP*+dQz%1`mD9eWYE{)@}N9pR%sgN9CDs(?{hxuhXYnSm8QnOd7D2y zv{jDzqw=iR`GcNYzs(=5#Xa5TkIdeZZ}X=+@!>judN$4BF@JRbY_|!d=j(OH1XA_4 zbell%q>bAI>Q=bBP9R9)?j{h#ndLTttOs(PKRtPKJm!!3cI4aqIe1KC{yeRX2Du;n9THu{ij6HB0NaT3kbqp{ z?$>FYRu99WPNS9{;@*5z$;>j>eMigqQLMs&+YuF?Su9+xc3ffF_zF0C_7)VUHMa?+Trx_$d z?4kuZhv%)karNUj^`U9N1CV91l@f-SeE!`OYAFaJj=KIsA05;*Gu`rGIV>Gmn1ahi zps~Q0S;6eUmzn?Z_%&)Zuf=tH_Wz+_nI9>u@?oCNgX*by6})4_Ib0i6auC7>VQwui z{sni{y5l{fP@Hd~NDqu2j~qK!$Q{o_0LF{WmZWkI4^5>G;^pW z?0hlDg*6SIMd3j^;b7BaonQRC;O|H&4oef4LEqviH4hHa8=c4HXgp^*UmhRvJm6LM;xFI7 z`{u*P{TQla>ND&qo7B5R0_)=0Jq~YeyDvD!>srjlk4h#)qH&Lp`rL{D<4nzuCY#~- z?#nR|y@p>7awwmWF86o-(o27`tmS2HnC*4imgz;p(1L?ij1kM0R%ocyr004gQg4!2Z4+2?WtxaG<~0t z4K+MW(=?ddYDQ3G%R-UWF51f0!rcln<791CG`kjO#c%!+%V5h9JKct5IE%d+h~A*t znZZ|pK&(xS;;(JSwP)v9+wuSSIiJ}WMad^}a_-jW_1|L2+^y3h`%DV)djH;WC2hyQ z&qYK?5>UVX*7$q9_bBVR*MB#jcfA+E!{O)p-{7IpdY{+I0A0wwQ6V17(>$OaJ> zj`*q062s`=_qEhPqOEUqW@%@I>63J~hb-+z-)_?N9vt1&on;KGlBaxD#YV}9hU-{S zWcC;Tt~8AzM{99dptrPNFP}x`!}4nUzA=kKOGRbV%q;p;c@G0+L^Lw}>cwf}mPHfk7T#CQcBBFd!$5He z1atf4>Gl^-IayF8Pt~SycW$VVtGAnigkn4^q$5rhHo3J5Dr4CfZ;Q@ZT8^{jRx}@# zus}L$9{es%+}ucCFEDWGa(dE%*=)3|#!W79t@?>!l_RrNqfm$3c6zEeY9j#6<-e)u z&JP@hq|A>{7@zxxDe8uj@_@*l97=p}!!MM1ibva0ZcqZ?R%(1IZpa>SMP0uCL6N&} zeta`=V6pNWvD2K-heoL`TgXUv;A=d_GK2Tkf2)om#H+Ti$gOmsB!u)yqak?{!5XE% zXY25&Ionv5r`ul+7*99 zje8SlDqGPJ(L4ZqDfxIRLwOupyV|5wp0CY`DM?O7O zUkoRWtu%`W5Q^naP)+4dMws}z_61(E5QG`hrYB`JCo)qz9L|}nW8h23&1PZ1$uw>7 zg5)e8Z+EiHzLcq)6x6R;a|ZW!+QUQ}dVZt58t4_hpIK6^h@|>WGG!m?4@sV5+k!BP z$%Dw#ULl>ep@f0-IKwMn%y!=0KiTZ(_qV?|6u^;ZX5o~*CBWET71kH<4Nm&i^4o+L zN~;_TKoPa7z*$LUEqFk)iDj29`-CdcdW#KQt}TtJy(!rZ0PIZBFENT2pnzGu3W%37 zpF#6a7N-ih1O;8n19Znj^_fJBje?TPUcU@jmJ6`5RMxE29z9sFrd)NZ&s5s3R+$wG z8VjK1xKz%aRVisI==vnxLak!kWP#i?6taAR)3Z>i^o|i~YlR3tH}XZah`}(XNxTY+ zT+ZqARQ>&Xk~Lr1O+D)?^~X#|QTFdyfS)v%+jE%o|MC8phC&w3COKJL=0S$qzwKoQ z-evMA=u0yBk_n{QG52yqz&fKm+4pkBKFEnCI;{!_He+3oy)E-V90RlOSL@iDWEA0D zB)NO**hu@_-XA8jXE&)D{HROY%icZuS&rXj;lZb>?Fm)6zmN>{XELb zx)tzGAt+xD5Bz3ccs(!5uw3bV4VpyznW)Wvn&f)t-&bDbD~8E$>h*Hb>=N{uu3nDLSNL1C#;7MFGhv1hDp8y&1llVRa&< z_GpZ1070vOpaRc__kHu^(SShcRs(85`~o0glUqQM9|aGlzXUCxVcp!VB5n6neH{*! z$5lKz)#&m^$K2GilS~1V3dWw=)Y}+}G8_?WI*@UN-wW7L6Yge$YSSRdym)#tJQK`l zR_p_uDrnBVtms>SBzxVj&&*6U~5HBj*EsMT5Ji*<%`aq z*=W-R0~X3a&D|l2r^owW+z-SvHb=mv-O z#m+f$ByMPPlOKKy@a9_Vg&7R6#(ZX-S>90Kt$(Wh{yB<1IFm@J2p9Ih7)7fy2oj@8 zzC-N~yNw1UQm4ptdAj`K55V^+0UWBQKG!DS8LZ-u^rQhY^61>~Q z@jed$c>$UGVSjn}_mXbX%^F3nPkX9nn?A8!AJF@OfSP9I1Cs2_@tQws*nHhdh>aV9wm zwYi*OvhC3NswXN=7b6nJduNnvGlE*vr?Iq_U$+Kj6naP~pA3^y zs>ea*aS1Z0huY&eut!NKlr0YGa!3i}48xPE*Ey)?(d`%5_Xy7STlfunr3?uzV6(!( zzu-6+9!DCzb%kGI;W%hUQv+2h91U7H2JkcF8r7NMme>N`A{P>(m-+NmeFg&b!|K_( zO#@bz9R(BUcpt8x^6F=d1RqYJ`F^N92Y>FSJh zhN4#hYCx60IfasfPEv|ykwy4Wcf{~KKSeG(Ean=&R~XR})WdpRGB6bol4>&n&}{Gn ztF~Q(UMb8``?8@~n2y?KjWTKRX_R3=E4&b^kF=-I1>CSbi}aKbm)&4#g%W$@&_LYl zGqozU(_{5vRn2bu{@N&u>gvnI(xcq@nKEIfOjkLOc6ay7IHL-(NBlku?1^-9=1ECy zmO#ap=JyG9rE;QG23ZoPs=$w3g3jo-RD_^9atfZ{LEnaH2lu56rdJpa zNAu-!;K&>mAx}SPux(lk`2D1@xVCQKc0Dx+`h{}p(90vqrTx5v*x`3PI_>rz{^7Ub(z-(W;vp6-5m z6bw9mNV#n^8~Z*ISIm|{FikbB$Xq%pAGifdyo1>TM?;Qwo^Cjpc2&`RRGE)ov!PG? z-6ZQww;a#kXE*GPf=2nvs#_WjJS{+oRCT9VAOV7c=tKRntBI~P)myC33hk10AdHlb zIbLlDcF2GSYvbrfS69LKugn7{K#J|SCh`=plZKUj8$RHv%i;S|xpMvH$EzneR*QpA zj~6scr?9Y<+aSpB!|pyrSiR!r1z<&x`c9$1HZ zY}SIh**eq$%L*2>Us_;?S2S6NtN2TYl)SlqUBuK-OnsUtFo{`Y0*vDj^}!Vja5+# z7PhP?P4{_KkDn{VkN1;@7PgHE@lgGcv2EU)F%R{^l6b&Ucv6RU9QZ>^ZbTF*p|Xo8iR|)qiV1%CzZS+Op-} zF{~FFO&i|+Vp+>W@JWXKB7JEw#Fab>soEl=TIB(e2-$PuZWwn z?``)ZiY~jq5qnT_+dvws)|MwPUd9=|EDGoak z$C8IFU!LxNF~AHjK_d#9c1xbJbO>Yu$QIMtUolnntU|&FdQX?LLb3_jGs-#(S=5T# zyGul5C6!#yl)E_=vpN72mNKgLnV^M0A=G{IqpbL_JT%os+0P*_%IykSK2}~nWCf6$ z0U-F0Gmu6EGj!;eL!?+OL?<>mKo)?JVR(TE;j#f8%Ak=8gv;d{=q`#WP`Uu}XvoU7 zK88Hq+^rlDSZyXAjxCwWe&6iuj*-ZM$~xw%b|C|xu=!K%6)zuT+OQ7own0V}VHuwy zPm=hd>j(jlOayun;+A8#U!LxN(Q}l|&?VD*-%B&t?X{N`&nq14MiC!R!;7MmM-he9 z)VZ&oIT(rvcFH-{a3*Lfz%VrzCpj4b6PcgAp~3g<&zEUVSWd^0yq7aXv>Y6Z__8Xx z$yw%=h-(#|?D9Wo4^Oa;Zb|-z`|2BCBCoOn9s2@D`Ab|de*gPqh{Kw5gnE3LS< zswW$3foZLFUN!rL^)-*R-#-W2)y=tYeMAR3p%$8*=t0lEfA5xy+%5Ycp?UV-E>HKr zxFE=S-X}OTmu;W2+MD;q5LUI6yt(X~<$ZZ+Q}y+iGL7Z%n%2%L?*l@fmwlX{#80es z#R3+CvOYD+UsX^F?Of6G$=B=9)y%q2hys;|78p@j?{B#%Uv-7;S<)E=7bTKvMc)@% zY1Yk->8VTzewO8@(`+9Xv5iQ_S8%X7*IBVxEfWGB%WnjWvW$8WD0JN~SK0nN?Z

D>BDJI`J| z>#xLcuGc~Mf9rOcFv2N$R9v1$*~`(5raa{&zq_JU!sIHbyOAN3#Jf80i$es_zIZp8 zJ6TqV^+h+!nD3@M2F=hBe@*s0scilxm%mCwf3J=`OYLU}jHh}HdF&OTNv`KW+$$;PQfJpZj^~*N zN5AX!&4dYA_ET1ynIb0lsIJ^^<-Tmn8DFmm1cs&`CwT(Wt!{72XsO?7Q;>X!+Uj<8 z|M;3SWnojUUt7#oaBYn;;&=W3iw|=BXw9<^KI^Wv)6uKZ8!7HTdQBX&ifdUL`gUD4 zDCOGw_2|{%Ub`P@FOSJ9hslK2Nl;jFTpf&{#^x1Sue*<4n@mIzyn5)J+!9)i=Tk ztti957fcw>SwY#5Rw2_HsvYN&k##SJOYUa^k?z9NCzbYg=3*9|XSB?PFV zBQl|Gh)m7Iqa&K2EaMa^E*DbuttcRH-8oYC$(-gyXZHOo6^CHDw;r7S%5>3* za+xtiWit5IbiQM;R)Q?Un*4jG-|vUrOC!{ZPl`)r!T8Rs%Q|T(h$jTE;#)eBU(0(< z<&pRGmj*q>05P&p^Rv7@8cqs$w_*QQm0c(e`HItM3gqGPS4a(~{kCRe|Lb+Y86vu* zJqfXM!VLRcF2Zx~#z9tZ>^mVUQ;Gv<-paM21C*i^q}uM4AVF+5pOi1O@1)A75I#M3 z0@i0#sT7j6OHZ;6dYK5Wvi&3q2B5&PpRy47+IPl`Uuu85!t)BZbjuiPi|qVAN<9iZ|8Gb-h51s&KNu<*anHp^!;@D-x(W!bDrh z{!%2(O?9buzC}Zx<%1Bc?`UWF2WPqU7hLZ1TK-D8QF8TG_Pg676-@SG81>4hVsIN!Oz)ey#z2& znbH>leir)gS^#yjlv$e{LR0`$iga4p@HD7w&L?qGa5BpdhT{j$AfM4UhDhn8gBm_n z%^SsAtRW5;ec8=-0wVAOZa^G_@R=@Zh)6sS0?h`8O4g!Bl9LwkdeH#w__sg+o;Bng z?+~1Szh4F>4k{C%2`|?w@eqY4FWNo_;%SQV>2PSEGwg+}6a2M~He?$*o8j;j@4h_R zY0<9iGc9%;QIuL3MHaYxt)75 zo6-JMnIg5A3rSu(Oo<$K@83Q*qXgui7KPoIAs?y}axw0W49H>I5NXYDwaV&!9Ci6QK>SKLIy-Ap5FM@0?WBZWxmyZ;&VAk1Q7{`4yp8%M{+^YaT8-r0+o__-Y9Q~n z=_%si%OGL*@%1MDo~!v{0KiT?T)Y@&)Kf`^+)R0{@+SVCE0R5O$%?9Le;L7=VQj{3 z`YBmYC?_~+w*Dsmo~vQCC#7e!se`{PvPpV|VioEQWxNz}?(&=XdlueZTa(Eg_xCA- zbJ=OTcg0B~Ea^B5<7j&mf6vHSDC(M#(7;z9ghYWhYkwZXlNC5{rcwBNmJeYCYFK{I zC5e&_=yy}dL+GgFtc>02dlP@paxDmVFe|@sA`x z(72wJ`8dH0>*%7^ydNKL{O1#f)V?N2P_tJxyv-k(Xw*bshRL>f_ue4tFr~L3#?mk9 zclD1J?R~90YcL5~tn%Is$UG}r)|{wB%DJLrLRi#%QL4VARvY{byZHm>-tgPy|Itw} zyLQU?7c(v{on}zA?$2^CG#m|#QMrb-rwE*ijP$18^>q~GN7N1`k9x(;Js}&LORw+v zTC`;)jaDI&(urYAl2*55!uC8@A{p5^POH&sw1`3+6y^cmlRo*SY zo@QPJ)Y5R-?3SmT-2^t})7Za#yIr63t<11)hBk$xsY+ z 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

!gCaB|`XZ8D_sfBUmRfCr0A~v60vAx!!iS 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

    @Xh0^ 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≫+}c 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ΠXe84%4 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%0D-^#RI2)BpKsjjB>wYC? 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

    xw%n(;Hr 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

    ZkU-vhw=vN-2A4 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 SFMaT1EeJt$UI$U&*Z%|2y;M>F delta 1096307 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%0A&UGBjr-h}5LS9aJjtB77J!pM>Rj#xrqLjr8- zY-e8er@}Ul;1k63@(zzU=0YKV{o)=_RqT}T6z@N4II!#2$2!)3cMtw#5Cb}b;Rb#* zup`_}soj()egaEJmMe5Bm?VK4R+uNb*bH=L8cXKSRWS$CbroN6L{g9&Wz4IB7wnNZ zHR^1*(m$yH9q|D8YLbn59rOD^;o`^Wdf?yF= zL7_LMTyJ#BNL`VCf(XrcqXQU(W~4m|0(#C@-rcN0F)!-(GPn)VaBMaoRn{Pz|9Zap zHpE0dz8gP@VQ#!lyT~#!K$|8ea$Ur^*maAWjM$pQ->>h#TU8Jlzf(RU+u4j_JpH_w zpvfZ?PENEpK+~O~A?!z!Ax_8TET8vc1q1P3yhpths=#r7k37la>{Uhw<`hgn*YI&L z=}VmL9RE9eG7gY=X{a#5S0k~k8)l(*u);>dE9NYIt3`lNKzwfHrHvY%T~aF}0}9<( zGVy?=Q1j;drrg2nl0Sk*$}3G7^p|jr5F=fXwv-tORtMbDLwN)f=e>GpmS$5UIhexm zr|gUCbTrw2pCexPzgKMRk#+Oe`0sz5P}y&e>;Lb_*>5k>_dweBK-y!)jLg#b%Z;l& z=J{{&-~W7Jw)_0&U*o^OjDX5-q!|78h_2k1xc^)H_dO=;8!=(uJdNL%>Yu+<-$OC) zp_t!1h5zG3AAVErevi9bwYjg6{`WQdFR#(}P{sd$f`0owa`9gjx%f@q`aO^_U64lp z8vlKdYy2M9_-7Q?_>KG2_aMjbL5_b3L5|--CHWrl_&wtBd&J}Sh{yl>h{s(EEchY* zr365J^D6Z}Q#|CiZ8zV;BmX~#M;^DQfd9TnOMZ`*{4yZ-nhqB1v@x5+P^L4f#E_K440 zOp0PufbDH7SlYP9tl))vP)dddgLcMAS$?+1*O(c(*V)bhB)-Sg;DuYz44HXjctnF& zZ~guCd5h{%ln+^G9@Ya-1=}4q`So|M(HcjDH8pA&^s&zE_WSD|rv%V{ z!nC&oK@8VOp3j@>A6z!dYf<6%x`zhvh1K_8fB_EcHY~+$yZ!$9yv8LUNFgec0JzF= z30lCTx3~mE3pG8Q@$&LBo?jv+u*Ff1P$S)T52)btYs3WR$idhS1za%cVYYbJ71V`qu8Y&QCI}|Xc}C7 z+wFJ0Fcg6TD=U=xd_KD0S(kBL^Qtvq9*QZ|!e%LJ<@R@yAPjReWLYL%f7S3(4TVN?Nr z!Y)EbJM=^uI8tXgGj)C3*@jrmwL6Y}VmdS>_wrC!Olc*3a%?FQ0+K%sFh9^W6BZ;_V) zw>;GFsEnVBaAow~SQml&iwSps#mPZuitMcqlFy|x>m0&p(p6x}1ndDOT@YvlHvv49 zuqET?LOk2pnxcUaFpc1f1{_<~aS7DH@f`kW@wh?TXy?uTEC6Hh&MzTL~P!O@(+!M-nbgwTyFuo#&m-kbK4K#LF)el0c3>whvImWP{Mn}F2cV9Ao5WYo3 zwM03b5%j_mJussqLZWnkk4R5SJRrL7AO+!LMCR>EDhY{pgRf{3*TKl~$-WCqWk?xi zJIdLOLL-rV+xMPSNTDAxV27q(W|#zcX7?DXp|#1ro9EPC9(+FBa6rZqKKy<~Wef~C z3+!07ZmK#dUsWAN*^c_~_JhJWPT2sWtG=*N;-Xe4tgpSEDpcBkzX!G+FWt5#=WJCy zE(E;cw8Kx)z`anVqiNKz-xZZHL7Q&U?vug|gJDXH9Kb!1WhfBEM1LJfozBjzOEV(g zNU~IK(0zv69qlSZ{=_C1RiNrLNu{sQF>r`>6Frwg9 zf%!KoW&$zz(AMLBx&gb6nNE4K>PwKo&>3--@_g6WAYTRwkJ(H@z3W@lAgVMpSkJzy zRJL8I>{Kc48s750E1g#*6Iw4`Ky`~=-nC*pKUF0ojJu9X%FWV(zoz>g?Oea6K<}@* za()g&2LO2mQyLH+&6CMWiFrhqUYD;baib2t8B12EeAI-0SjFmVYX8}@D|zP<>n3Jo zG*DEE?sAy8lq-?JLBFQ9A1n6MMUTyxdCz0w1$@1XvAyr#(z&a6Cj|-29V<~lyhZm& zEEFB=-d+f1A&4j2s1XEJvb#-B1R0wfYnCg;(!JjhPKteUCxY5@L|wO2VrEI*uipz1 zEJX5T+lGUG2wWw64QNO>0G+WBU%7ys-D5loZW#!74O!uz1rNYE9rXb$7w9KSfg4fF z)ug~-x^N+oqfztab`0pLOp}S+`;eF=sMYN#1VoO<&>LiB4MyD}P6MlrK%wFZK%KcV zAw>@v9$d~s#ts&UG$+(VtIqQ5chEF1$II+|`Og7=(XGf1QSymGu`w!f;GV9SMXt6VF}7uYRtRi*%8O(m3E?-4VR}^COFOH z%frHns@W6Bkt;Mcrj0<{g5@HO1&MTAp3Xc9v}1}|4yKL3R>9?=iZ4@SBiwMiS*DrySf-c$pUE^d`y)q8z9>o##rFgQ0?Q zf>REJO=R+(mS!{!r})wgMo%DxPn0u?C?`7QfJ1p~Cs#DJBqMYWGGlnRqJLNFc8H6Rv zGDD_7SE8JmL^;8i2X-j+uH}I~=UkkWGn*(UI^|3yKp|Ry%cBeev_&}xlLeEWPC1wc zsADj0N|aNba$r{$gBRs2TeaO*j%EXfkozfpDv!6Grx<30I?q#H6{CM}0b1eP$tBQ# z?iVh?=j%zjxMgAT`=Q6J%oLr2OEGI{o?Hy~EW54lOb)kp@=)i2xRtefvdF4SrZbuC zHa%HXF5^+id@biu!~8=(k0L{kijFBh=7O9X0Xya8grmvCW9I-&Jd7uYK)YNx2->p% zazKs0?;J)c)F%hR`wXEuI24AO+rhxFGmuU@e|v*@D2|i;VWz2^?6IOo%7uNxV!}h= z?3MP6cCz1fr?%V5@xEPG(n(__og7!v$$2H6TvyVu_Ch*JX*o#;Q4d$rL0rp~bV^-G z2T>Cj(otEmlXPItyOK_>E9orLqscO_q=V?-E9t+95WJyC{tOY zjgk3?)k~6R4D@GB%Ewn0{<;p_xa-b~D+W)RZO%1G370k}03C(S{osj$G67w8fAZE$ z_k9=3$1sr$MHjzJzD(gQE)5qtTt@4Jd>n-5(&P;%GU9~o^0@v?i)W2mY_y~QoYlq} zu-)BaJ@h=&)zD7*or~QWt)^4qzYn1ph*&!F@#>LnJRk2Ta5-UkcPh`ov&iTpWIKKE z?)a4xzpul-E(Zrt5;)TovhRyqfA)|>5%S~hK&=N(!l1Rit&1<0rYL2J7vH2d^GOSY ziZ~9xUpQhvEhxY>O4C)r?02T>{yxKgLYMA z>zF*{6zPa}Ux+N*OmC@5O|2|T_F(F0)LM}U5m^DUP-rAwCw#nmt|$rvfBRlB+Xd~k z-R8FISjTvtOrYiJ$fdwT%hjnAJ7NMu12|$eJhj#JWu}YPBH)#&Lc5p_+|g+Bh$|#i zVK&|#YN~K?V^C1x0j$&=$Zt4QIY;(_Z(O?MjF%^lNekj{*}X){4GyAo3$)Jo`e|(?p*147L-fSz^J}d1RDkdle0rgy2Pit;0=vsrPX2Nt& zZTRjKyKW50vN^lXG<0JtwN|ni{%V^ye8IpLu29Q1+|wbIQY2a5N{?se8N92WCi zTy9S)NOeaNXwtysf+O$_s;%#9*@uF(rY{B`Z%W}rySx3Vd(LxDf7@+xq|57gBpZ?z zPuT@c><^1SwAiEt*mtt)^F{6Mn^PR@fW|ZIrBA23>|{n}>!cNWcfFm}WS*Bb=@YPa zRFg&jaNBHJto@KM*O+mF?$9N}tws_e1!Z*W6rjySFSvw~Uu3-9s-92&KDA}MAN~ER zcJuEQKf~UnYzfU}e}SN`cv;D6D>};+0fY$nwUCcTos&23>vd~Lnc1fcnf9bSDZUx0 zNrjc{3i|%tIqR9!D6XDGsgw_}6jbpvt%e*gG-XzekD)|M_f9)!2bv!RM0cJV+L@;; z3>=rm#ynj!&~mrqWK&bFmcpy}-ha_mdDrrS-+ej!p+w7-9PYk+Sd(Zg@<~?|;{u+7I8bHKKu1;vLKs8z_;Oaxe;Z<>V-W%soce95k~x2e+a0Nt zg;B$D(nBqa`uy&+C+HeHyYkX=axmp5`uHJmVBm-A%kHHm&_b`IkUc+7NK)SX(vRfC z8WgFpKZfuej;Z7(uS`k|(5_MI16LkAgf#b+qHGA^ys=p{Lto9LUu*NH6PsCXPG<2l zI2^I$e}y(vt`~vW*mq;BCCj+NZ5ow^kVuKegUfMELhn_{6UfL2^dVfMIJVnn??(E4 zNo1)mmj&z8+z?a2$az?P5p!be-*R+AYvuMtT6zbMRfq4G+dmZJ(UEjqWzI|<`#$}; z*CwaW$U&MrHT{ez4A{9zE(o&dLM59X=#TwHe|6#NasE?n<_RG7H0g0JK0e3WX4t!P z8~@x_AJo$o#)y5U6}>T?s;|V;op`iFJkZy;6&+~MB+S9tK|o-a3TgLDD@!oRA3M_? z&8eJ*J$V$Np>TksANl34;V|2+TY8r+-<8cAFjz;olQ)|IIl~){;1xO`O)@XWL`vv1 ze@SJrRP=}Y9WNo*fS7F!mr=|-M+2?E)dhrO1NtqyID@|%wzIO^wL6jN5S1+d_`J-X zlkw&kpTz6)hS(XI83g1fMzS;poIVKLhkFt-D;Sdl_vwQ6`T7bJC~^fAqz-FAp=4=mIUe@gau#paymEcKcTQ@;c^m zg)K#v@@Pt+$(@*{A7}c|#^1)qJaIDcUTs~rsBJ3J|k0ccXNz^d9Eswtz zP}41Dto;$ev@IBXtA#OWX3Zuhy zm}8gT!_2s>wYt3g`n!al}FhaMdsWtYV#D3z-C#>@+rElsa0(k(b0=7=CM#_)E> z_yFeA9T=DL;J~9*Y}|yQAEph=BGJ||i1UiXkXXO?!>9e^Aib0R#KF z;>QXah6*qcX2!PuOeOCEPP<9tAplBpxG=Xv>?;V95K%;ij{fy^&hd(kD=il*jG!^t z#|twUgsX>uJ1D7$cr$UatJCM}B&u@4(dNNMa|$Z7jU@z;h&CBpSp3=Z#n*y=t3K_9 z2A@c0@XZBY_VWr|yYcA4e?trD1eB=Dk06K>5f>Lnp|SuGsCG9(5Gp3?M?tsXj=f;% z^1PM{%MRRVq zpFKzvHw9*_mS57RpK(I?@17u_jJ66OunPTKhyyvcZT*=ps4UGGk+ifBbHSm%wL)CJ z>+f{`ag`7bJCgfs5MKhk_5&WBEqr`@gW5L z0mzaobp83VBsAxye_t|8WLc7eyjrQt#NA7D{zECVN4NE7GJz^k20QEwdV_&AGh*DX zo7?SoX0&wX=Q(c9wQ>GJa#U_~z7GT{ z76?6wRB_&b3 zpD$AmG>mN88|Wy;P_FGo+!FXGm+a128l2J=e9n^+r$NY778`Z=F!!--T4Fs zw@FLS!njIIwm;r|Es(d&1y?vGlL9Vyw4YZTTY}ose`*+UKeqRfGRWZ}5HzB_d+!h- zwt(OsSxAnLOBbgb{)Pf<=$rxeUz3Z0Js~e8Z`XH8)9rD>?!w0SpjU|8^sv(%ah=Wc2ffQ0jcacY#-%<#&&5 zzCxVBf4)2%X02|wpItVb0ICv|H0Lr;ZoB>N*P1H=D}o_qUk|*=t-teyE5fS|xlVvE z?AG78q$@-$5Ps-AhL@0wdi|Z+)D=BdTsb*(+)Tgp_I7*jb%$w{wkfc{LJ-ayOzGzh zM^)-0&AVBQb^YC6IDuOIGJwS=4?h}hyFJOPf9DlIRDhy8=b)Os{H|;56+txP9^y{( ztc&gWGuhGw-;{R?`3>5Xq5b-^Z{ro;ltHd~oGQZdGfDjhr;0plsMZLY_6x@O`|A$# zx-nD%7JA^bV%u+ssCU#;OmN5r3NXv&(2);%=6U7IJ2YeG1^fn5`FTS{)dEMy+=P31 ze`)7i8waA6P~t}J|JFVq_E%3tQaw#4ByXX&_I7)m@82LtqZ~MP%*nXk z+RO9&z=~0dGn>_4BQ*s7c{kof9iQa7f8O@AVe`Av$ zI5}^PCzh%RBss>l1pfN|PTW_hSYQY~1mxcIeNrTDdK|E@h!Nb9cXB^o=jppb&29qZ zOp*?L-!q=RB>qrOAmmW*P__QS1B+I8pY+tiGFEQwyseLO#cyD+G`@-AB`0O`qPQDc zaXRvo+r*al{eugdEN-4$(asn-f3}CWv-laEoxmm;+wFa~{hV;LIyK}8OqSD`Vo*!= zEx=im?m@t;<@Nm#l!s%)`XQ)VQHr>0J8!q={R1axEMD-yG?+${x0AQyc6;8B^#Ti9 zWk|uX;R|S|OM7|V&)tF}+no)8x;NtHk&oc=9>piSieexWaNbaxR*KSZGHQ-*Y|NS%Z-UMz`GbO;?Zl= z+srjAtQUeD;90iyW!}#YxJ_9>CVKYJt^yM;fo2gh$S%HUrIEgI*?F6X$k)l{UKr^%OQb3Sr_B z1-dp0F~$g+)phBDCl%RQSeDDnG{aw@S?$M0w=)n$TFjn*U5H51_;aV*68@&Z8fKTb z@wF2Zc4IEK5kEhPDP4Z_IXKkpMpOO}wrq=>LkCDL;@;_mDvZ6se_-Ow+x6Yo=M@SU zJAj~jwhQB922*T+6{gh4$>L@3kWJbb<`r7tg21c0Oc0E(K6U;`_4YvZ^; zlqudD!G%kAJe929hmvCVcd5x9P{JEaLI67$AFT0<|G8ZsdVK|fAuuYG$j6{q*kg>d zR>uDFT-^{DF3`y0e-SoVjG1!g{EZCd0=X;}SPKtIq0$Oeg9qS33pt`-JAptz26}z@ zFxIzy*}&k-)PaqMvA!KEa{-cedu$!+G!T+)P58`4kKDZUc~Y`_jd(?9ZW8QKep>}3Np6y{(E7&jXRDk zIoARC`UN2q1lMY;FtHKQu_a>K3Ds|Z^tFJ>;wLH)bS6TDzCx&eUXfQfB7*Ulc1B5G zexqK~FJw`ef5!xCbjy;E*KNPz#A;h$Xs&)vGV7xeiX%l|_9D2x5?x##uk+j;5Vg9T zV^47xr@T3Tq_gAzz1;{C4Y@!NPMGx0AGt_jUot!@vd#q0#iK~cI~LuZ{cI9EtF23tADaCBG1 zhmd1je;;>UbAf+#QH{+n&JHI@JBt-F{0$05N^QHn&hOpeV;dcgiew?rU_>`ml1M8U z@`k%2+TPG-WlXrh&jJrn{)e5rCT^8hiur!C;OJSNw6+-{Ha{VT+*o(H@0Q_^BQPtf|T#L$W$8=Zao8M(IG+-}eN2Uf`0 zf4N6%@lZgd5rWnaP4f^oKU3@L{N4oX9P<4hp76k>HhGL43}^GL0)b9HWzw~?{% z$H{0>=<$AV2*BI-Q?p}i5g*JkS zRLsJoSlAmw3(|H2hCKj+58T)cmjg~iW@JTX^*h3G(wdN(IxD)JFK?e?6MX9z;-4uL z$&`NGnK}cM$2fn4uvas z2eRekU;OdiXTF2pGC!v)e1dQ-lcCiJ;G^edGF>05*qMuYLBIWc$Hv8)YRwA`5t(2k z4R+h+*t4*Qz!TNpuyuJX+Bvf?#|(%{$LE_+?Tb6~ua9$6R!m*Q%j$P3f8BFWtUdC-W&zr+61$Mc+R1PYPgRuia{{5RBub9Xh|bq}lUT8WqY$%^M8kOi@JbOZ!OdvhL+#ny^=)qA4G=An7uo@ENg=U+VEM{`l*21ti{>T;OMfeqs38R8pqXT7wY2e@G)+4)@i{gmQ+J*4xMgAp?W&rW%TX#`0I{|tf&!F zZ(&xgxo>xn;m;dL@unaxo9#fT0t1r?*Mx#algF&{RN@0e*u&TNU!U(N$QZF~l7*h+ zmV{^r7nw)BLaBouf5QNP<$Wie6NXsz>)x0Hsehrb&jNfQeVKq>j7<=E< zyuSN7!|jhy`S^v^v#!DQagUH+;^&`{NC6ghf!T^V5N(lmd4!)MMuTaW3!XC3XlpK0DMQtriuPy){d)MSoot^e_Jjo3SBs}$|PXD#-^h{tWkwZ zz#_+VcwDSJV`eb@E+}$7@fN>sJLJW(G+0V`{~J~x%gnTnLb!pqw2q|2W0uEzu1zfj zb29+8)z#)1pUS%9x^baYTmx;5#0ya_o3!0V`r1=Y_G}S^*PIMU87A?_5m{46mMoFx z4YKfhe>^CTetGY;=b9WzG?hK3YkEmI(@WNrk$YYUE}7ADA5P;4ne80+loL9nZiyrJ z>=57s15r0BJk9h#M>8&JFYmwhToX?evD?g-n9?<|BplfxYwpNBK?D~eb_^#vHM;Br zDRTZV?^8p$XOOIEBE>8DvS5o8dL?d8={}spyPf*fyzYZW*Y7U7$oEwP7Np}I5E7xtb4T>*`t9x&PrSOW+3=NUW+pLNps z27hmgUj<5G5_&oGAGBE;KGE~6c2=7JU{SziL^~gPo~dDpE=#pF+~luoI+eH|Y*$Tp z{~V_iRdgF|4xiuyF)4U2NVy_PyR9{rh+qVfL<5?SaVnGBbi7HA96AT*e*gtBAN!u! zw`}_B^Oi&Rq^U%a{<Q%@z?5QbhTOai}T_r#;Qr}QNyx&<86s?tS~fyTo(wj7`Dj-YW8!glNawdbH_ z-^btqT_^~PuLa?=AW*YKe~pgYj2h??7N!7ACU)|1mY$v{`NGAZ&M9ux9PY!^=1Is) zY#zkA{SK2CVI?AA@Fw(JVn{`T-cN$MREGl*zG5JXLv-k3z#TME7J<3P`8yDAA>aw@ z4Xe1PayTK@%w{5@RZK#UgcYcJcS1G}$02G$q}|a(NjjLqv9 z@&&X_8M3xAe-V=axJ4BY=>%s9tL9kCClzeBjlnf;neCISg;YE+MHzgQs)s6XEDNuq z8G`_M{(LTMXI`2L)lRfSYik>9k8N$<4EyidpP#;4>aXq3BfSsf=}`&xgsp|`!xQca zbIb6pCwIRN>iiV~7$!tpzv-d^A)HX&k@&%)IhlDEe-l20bApABce%I_JfAGMopdqqkB7L z5=H==e-_%lkrOI9LExF0w#M)LyUh`W@REQYLNMeuateSswnWKj7o1vR?*0bEn(O+Z=%o@R0+OG|G}?NwrbsOv-7a7b2v}NIW;d*tos!& zx=bjB!i@VHYFhwCZs1-(%vdG~cj(9%9ke7L#2E$`EjpiL3szxwt zIQTOQWx!TI>=9(sBPyUvz6~YYe-jk3=}0F;=wR(SF_dYbs%#H z{wkIZ#IJ-CjVSuAqU%J`0-_)|3PFsa3jA^uQZINHb(OWW5mt{T_rX8}ykW@|-6Ue+d$-89Q_X ztRvBH9&zVMK6{05m&(Or1wMvM53M|$seK6Mx6*73u(b1t30$p5Kak{Z-D?f*ryxpk zVqK<2?mBh6p+>?$OYqb(xb0vX1b;6~_`w-##AYpBhXOLd;iZowxUED*BD=2SlXa3z zNkF#35a=+kRA?s_ZbS&@e*>y+U~v@H>4q{khTnw?+VC^S$2<58>ukc|R9Tu#7{${NA8-V=!AfRz4-uce3x^gNNwCv$;WG{H(9?r}TyK~&*SXOi9~BLl6TO!R`8S!+QS&BK(pxWlq}scu!r7O_M5&6&{G(G ziO}2eRh*sc`!9!>Ixu?{B%yI{ERP+~KAF5$p<;}uc>_D5e{AoJC@9<4Fo@3AX`a1- zA62P@8NncPdq)B?7NfHf5-}~VufINT;}P4OY7coR=mH`(DG`+K{a?TT^a$P}G)>rg z5w}J_DQx>~u4~`>a%)kaYA~-n%1_f25f@xS?NdRJ7orsQa8XUpNTlX0 z1qRv}E#CJXUnt_qyj!HQ0BV7|Qo4fwAlYb!tZY7ngxiD_t7W*Ma4oC+`do+o+{+A}vl_|lJK`QLE_RS2`d{fA8f6+V%7)C&37?Y;X4F_NM%HvF3fa8

    *Sdp$r`h@e#=5N0J^z83$uSlzm^vmuR7Fzw4h)X6{Vf!}3v~-_ zZD38?pcnBhjUeM@`zO#>29;$ZSC*kK%-yQ(Cg%VY3rbQ~C|By=KF+b!39BX;wcaNn zRDpie_1l6a)iTI<JXBNO}i~ zN!Za)5z~8}5Zy}J(H-Nd=M{@FqIc@Okh5b#$vDx_Sp`R5#=2YDOGeA}qd$0>tJhGt z;0qwM*RYStF%~e`gH}pYDZPYEj)h@SY~Bo>HGrB#wBsf_L87^a0Tkq`h}UTz*R0e{ zC3v2?AyB*@0Y`9f7`5IN*cZnDa?uj4)#AcNw!IpNyd5DYL$&rxH)@r zD%-J_0O{p_lT?&f6jgB-^jZjsWdaO|bX20&QTSd~Db;=~i2t%fRm%bZXH~qYSPO$Cp$TQC!lU>B{oe|Re!?aWy z=bKV<+Kwd`-F;IgGJcf>{iYO#L}?Jhpw>%?&(oOFJC6;!vrhf4u*UA%&-i!DjBsKy zDs`oGNYR?JjJl*71V(-#o$^SK*5&7wQV|l2CoE+LgOYVZ&#zR>(KXsqJUO`$wk~}S z6~gm>WWAc#O7^U<5{-OUDQupXW4Z#ZFyH zf6<8pBNfeE0M_n?!isi-$V4s@FHs}S8Lkb{0n^%UQ8E>Re=$ zocr=dwN`iaaI)Nu^2XkaV(X5+8w1*~9-cIRXE|(xc4oc|Xb0EY=_9;Ro0ZB$L&@GI zoK@YmB8VS#;aS&Q@$36<)-D~7KBLu)6&*XMVM#tnk%l2Yb)2A0D0Rr@_ zud6tX%_A@ASz#g$IeyJ{fbJwDNe*y-d!DCPQ`*R+MNU6iG4Hq+Fr}5aU29zxYgb8l zrZOO1JG$RhOno~L(Y_1HK}qCY2_%{$j`09gbi^~#?cj`%&?OKDiKm5i04m?nKbPU` zGuto}*G&QuD!8!tWjSEqr9yQYltPS&oC)msTLAUsJ8O};=d`6nx+UmxMFTs3uGBo! z`d)`j3fJAy2j>WxtScO#8HkM^F*a#RM`koc{BT5Mu|qUyPh}~Q1i>AEiN816YEryN z{~5}3VPJi2-M-Ay%LyfmR=$$c+yz@9ov_OWl?!` zE`3`8T)oGgh31Yg0#gb|M4wE5q&Bex6X;3IE-qY3T3c+bp=<>#lhnzm(0WAqIqA)L zd>hH?^QRk48P9rmt{Y7Q8PBSlf4Fla<5_d}fS%hqxU?sl-4_zg5wyFb-(^-O@ysA! z;+ZENQq3vPvZ(tJ812$cRA(e;IPgY!8Fv?^l~}U7C`Hfld$M*NYJ&-XY~8+0*2{Ty z9xZbH9#PkD%~JAk`N9{V<0QGJxZ$LXPN>Rsd0HY}M2}qG!$`OiVZ8B;Q}y2Go1ACD znwbPj&Slo@9P1Rq-B6Q_4Jo?^lyq5KO6fM3rbUW|=8R|LPt~GP+H7VuC?FZn^g0P= zDPvqw2JoTk!%-5Zy!kzU>0m(M=>2ZZ3j*h?f*p)j`{=9&HHR|~Dm;vA+je=jyO1)A zvNw5t>{g<=q2qD{~dRI4_TtY5-cy_QwkqG^(*Ze(<&NVPWz>p>MkpBKWWce zlovo2VB3f%yLZxmp2hE}0mQ4b@nTE+GFdO@RX!O!s#vCd?~0@nlZ0ZPPm}jdU7uKS zJ9*F4)Ujxau&CssGL#F$OUpSZV`S;%JyU%{823CcOOxL3#0+=&$uc$FQy~`eO?{jy4**@$XAcjTcldSv)7LtQy1;P!ldfvA@mQjV&2!tJ+=X0Fq z_V98}7$a(IaUXeA$a!;@mBWa9g-Ikw!VJMka-Ma!J*)DFyCD6BO)hu?Z)XQo{I_GD z&Ridq8adC146uVg2T*bz6EdDf@|A_rMJs5Y{UR0r*H ze57hGv8PFTO;nd%>_wZ}VPkjzMG8idH;JejD6!Z!l4zJLu{qe)HpsLG{sI6LybOfb z0`O|T-+^~d$n8WMbMWcy3*RkV%Uu7x=)qT8oYjGsIocawCrFIBrs%HGgf|6YSGWy_{6iXJupFExzPC zBb?2#+smFw9pM2~Y{OMTMcp9*zlwy4$$s*GiL9XAd1xfFoLy3a>NCJbZvMir#NLBI&vhlEcSFSeqHC+o%|+DYPZMGE`iksWe} zOz^$lpWJ3L97ZAoIn9x5KC3_xsWb9ZVmO)R!5Rnhw*bunt&$ll%#DN(4BLU)g_$dV zOgAyH#F)X#!5q-{?HC9y*_fn?{W4oGL9kP30rQTu6Me+8fRlX14ueaPV4{3{q=utq zTTKX-755r+)6c@Za=(jxgbaF>fd&@G{VLTCcNj*Pm}O50SsWQiosR}I`f9<<1Pw`tCdc^My|7Fj40ceJbq}E{4ZKitZ9sy%s=sx)o=`dTY1>) z8jjwfaHWpGybwI_b0OK8_+Xt;t{wV`3drtVw??wF?zgqVob8OtwO|C+Tpf808rn`? zH?JVuS#je<&avnMfJsNHa;^Yi{E7sw3eAy{;Vc z0oYpskcSO77#Jwq5Yw1aBF!Lw=cM>ieHeZud5X&@4?a)SYq~0n$2Pt@BCnC{tQr5w zWQ0>sH9pkVBimUwepE|V#O*dG=xwC-4*V%5O}4XUe3~i@4$F+YY^R?A{v|O}!^>p2 zyb27IXd`=go!^zbqWOK@sG@vlejktXu03Wvo^=Zs>CT$r__To_F|mq&l{@g4bZ5Y0 zTwL{ht-c;^{xuBuVnDPr+ZP4!|QGixAKt<(K{k+a^oVy5fS)l2>uCSBM`((Pg z6S{3Mj@eskf8(@&B2wX;MWA14MeYR$6VNZ}i9(t)kp6U>c&9Ov&4;-;%Ng)9M}j4g zcqMllInFK(?YeWRSqp5e9A3(CmZD6s5=qVsZuNK#q)~n013Av(Yr~hLeVVA(40ZZK zj*5Nfj(q{0rIWP6x6peJ?o=T&qf?{nQjQ>3>USrX2lk4873dScK7rlP*s6L#n;BTQ z;k8I|6`~C$UX9MIF5BFOaXNXQZFTvPs6CPj#oa_sbaU5A3iUAwy3MPGTPISX#m<}# z_;@AZ2EA+KuO!DAeUH4IfrNzw??i%AmTk;Vg0@#oXHs{HGplFCmV2y65)?Q)Q@Vh1 zrSH3iHd*$6C9>%bS0{o^jgBAGH!B<5)kDRU;|%HPEUlFsX8{i7GuXmq zNZ_%|U{}lFQVCM8w4nl@>59S`hPvBU$;Gs;d4;mzHHQ~gckl?)s>EOC`5xzY4O5+v z2J^J0bIdPaEv1|ccM%t>k0ra$q9MguHxSo6NTEZ2#>Q<{PL4D5!_MI)Ex)gp%BI1B z!l4h=8rC6hXv_tRP8=Ev+2nX}PGjk3#hQzmDKP{MmQ7#|NI5%#$?9UVoK+I)c9*Ly z#@5m%UpnzTSuf|+xwFuC9*HOBNYEjE^G>`;#I*n-K6;9*QOgu7+=E+%zIU5>;&Uee z+8wcf&1QEZ8n|1shW5%;B!+F?U?EuXMo{-7`%8& z4m2!f1u4#&8>d;2e;9X{R?~8FoKbd`Q|Zq3a_7Z^6&Fr(q+d9zKxxj5jvaor!#3F> z?Woe6jY~ayWXFoTya*z2WDR~0laMeazKsp1LeU z8`)UyjWlQ7@UL-jV22zhjsc)*oEJcY$F=G~FRX%)8k~E7W@=>CJY+5Djytwm>YpCpxa?PCQ}klks5kvtjZbYNe+}2_Bv9X zHNUSFrc@AqzhJ>qsxw1zZdhofI;(D;J=I8g*0w1*sm?&aB*D|;m}S*_QH~iwavB{i zV0j=IA(KbHjWADkE;Z)bRc;(jHh+`tEC90Dp#o%6l(irw@7oN7yP)OxbnE?pWvemS z<$A>Ie4443lPU?KE!}0{Icp2Wx9V-lcEjZ8Cn0+6J2DCDcdo$*YNc*FQ?Y(uTuN9R z)kV59EsBC60yC&oID+hoS;IqC-!G`SHQIzO;=;9Iov47i&2=O^tA4%P?JWCsp++vi zBx#O5U+e~FqEJmNWF63~b~1K<-5Kp3-NOxT+br9C%>)C;tR4Y**q*!)T;!6whu56S zXMbzuXK6!v!}<-$rS%TSR_~Diy*XKgc0wEe9V@SdUp!xIG!~>*^;#6qll79NDE$ZK=~5#dop8nSr4|!h*9jBm(u*B``rbo3bo}&y zxZ)8gwguLuK3Sv_<}yH)^QpeYAx_z8!M4@M#n-V(Pa5jueP|QeZI&^y!qS!b%n01v zg3M>l`rxz5>?PN&59T^IQlHUz1@BAcwL=|zL`Na@85oolW+^NdldV{s`OL~$-Hobf z)eTp zG91dBwvG3d&leB6Wj>%Ktn4{P$Z-or*d?1&`xGZXvvO99VUj>yGDkHBg1G}#V~D- zrH&WJre~rD4MG)vG?O2Q*VYJmRG`Qc=5-Vq9t@)1XIm-`Kr+9an8_&9300~l1 zDzWKXV+kR+%P1Id+__dmYI^vJH zdO533tp&u(x|Mx}-^z66G7_KxA#p9o&Pl@*JzaxgO+(CT`dJ$Yb~}hGd9&Mn0S1R} zAP9FkUl;(^*Tcz~Y)_YERv&SWw=md|0j>LWBB#iJmYoXcF2NbfW2Hc=zLe~SF1WkQ zB|(BQ;^t(3K&$Rtb{rN)S)n2l6bKK8GFVF(t0SPb(iGb(Ciga~sdxwovZ|vi7Nl&D zamU3~bUxsg0!j~9Igx`Z7MqLF&#Lm~o9RAg=`~MXzD!0S;7Gel{vP`4DfQlJO5TQ04!Hl0svwpImphPDFB&v@T*~fS+|)NQOI1zPj#%`sBkpQY+$ zG*Sw*+5LHPdX?a0)wF^XXy9Mda#Em0_Y|LhBPALWTbFsT_UkYmIExrP1QXkw2(E^0 zQixQvTh1ZOY~!qf=%xV3a%&_DS`ENlvG9_vxf5#!FHbvu&$btLBj93-@6&X>oY@hM zLtRFmieD`Du5Keel8l+1PMkm%G&NPhpfebjhH`YL`P$BkitAOy^634p+()u}Rwsmi zmG4!t~&;9tNwjCNkQg)VOrc>al`3O@!d#-rq_q5 z1&Po!Qp4<=L})7eB5=J=@~-Y{>u~&{Inptlm4M?HzdNt<4D)24&J!Vpt_&k8OMa+Y z7ADCH=pNVIs;reMk)MXksX@=nj{1gw?Zz00WTBh4FSGR$26MwqHqgrliDBFy27*dw zOER=>#qaVBG~}2TjywZTsz=cO#!=W;AuelXxv5dGcU(RUcSS(?=GDd3;_CSi& z_mLNxRT0(D#}5Q2Z7Vvth?TfG;eMe1*8Q_*NF~Rm2IT-+jlo z&f{!yCEUUJo8#U@&Wr47f`dJqTsE%-Fq1E z_Ep%Z7SA$JMl|DOuC`NiV8oKpV&Kk*W=-u`Wn#P|V6v#9oNG(KTqVzcmRH>f*ep9G z>2~da!sREVEUW&U*2VK=y_{E4ZGrTXSXm0^74o<`j~}z@Yw$35+RFhWwQ1Hg(k$kn z1YF^zyPasShvIgc#wC0CHts2P+*3x|Sh&PHdvLerib^oju<>+NtT8zJ!?Qo(U@aY zlQhPri^7HL+t^#IH9mcXo%bF;XJhMb5b;a757f`Nn0#WD~4q)ma>oL z2oYxjGZ7>jt>uh-Fk%$N%b7^lrK%kSei~hpxPb1paslUxy?0o1EMK2Ht_MASPqrQt zk=&ia>C0@roLGsG4YX>+h>{i!BxajEY0-+2qBbCD(VCH@OwX{bVWc_CLDn%cB~Xi(-%$4Im6pZ{$S-D3iic?-P+G+z&DS1dPu*CSb~C(){~omS&_{%#FF9 zO=U$+kryq1tvnpbi*^C$jLnzKvwD6vhl`Es0|D_+8j0$d*QO19|j5kynTDkyHgEwVEcQjjfb;2zK#t8#S4i zjpCb}&dlp3`T-A3<~0m>P`c{Z6`-f&XqdFN0~bk-*8F+$@~t3f+YH0W(P+JxI=Rv4 zos%|yD@a}QI%K5DRKL`mA)Uh{OcQ}JoY8;?CqbH#6HHtiOY=HdKzFF`s4mOXl-y_~ z${XsNG_NYR0#oNAZIzQv$SbPH1pG8vFH=H9!Yy>5N)r|7(NF;E?~xu2tSGD$>Cv+N zsqZ<`qk%Pbm_&Lsu&8CwWe;hrNunxXH1sXy|g0d+;*BR^Uu;`h|Qt^+-Dn^cbc zXgtqd_0Er$ofqexBR?9*TO$iAH`jJ1n32BR?7nZY{9Lj|TGBf{6TRU}I$& zi~MMSQO#)NM+2;?oz9PDoo&76$d6{Hic0rvh(@_V_iZTFg4XjX00@^{-g4weyCM>Q zzf9LlEbN3^0(^H-sh%RtACMgvTCZlT20G5mcMHwD#N2Af>OS{!#J743wnacPh} z8t&X9XN|3IW_M<^EGxY7XUiWE_M>EBqM>n`t9+!Z($AM3z*#q;Ix$*yVw}4YCx$xN z*BKeHb(4!4X|>eyeCn?G(iYqDg5N5Ck#!S7{6NLh_T39^>)|XRTw6xiFD9-|qP!IZ zCzV9LLwQTUWD&&@CTPkN%8QK{$LqUqQH`IKB%P#a<#xp(eww3~Q|T02Xh7THd&-A~ z>?Elx7a5UPM>tWuMZ$|lkcr!rY@Dc>(PFpm8Gbr~a zF6h`_d3$EKCkMF7QfQD2ts4?+Wy$R^g(_J~Mboguk5~pzvY~}126^HY%>)LPD<(d& zp(@7a!abmvr4x7Xa$`BziP+?O!4Yv8gz9Fd5q3(PhcjHaw@Y0s>+Lo<#k#-gAIZgV zt>{>LYY9v(J0;oB!UtRT7m*Ert@wL!qw2?0z2>URiTi|kW$V>|+S_5;hA4|17})N# z-Fd$V1KvTghCwDt=7*!MdhxZkBtr}B?SQ})D{Bk78`RujSkHqTV?ZiW;%wL_=QriZ zKWRi=NG2lB6u;lFWuuxw-iCaK7}FmuJ=+e;{y>wugaZ}@gg#%pJn zwJx4#>m>$O95gfxvky+Pwm8^mkGpmbkcd-lagttv$U1{(4TH>X5=z`vA5O4S9+=k_ z3NoVgz`Vs~O{S)MDrD_{WGFj1(YSetsqH3Ls9BmZu`it``azI-;L2)M@<`V$Nd{`8 zI19USq5*-;(8-BL?=ZhelV;tkZ~tizL`+gNq7#`{0gWEnH=7}9T(ZR73g~JZ5uhfi zQdv8nPFsO+i5OL=PCPGDB{|Uo@-~~08}mBJIre3;UgzV{jb6)tkXO;7BX0B>w%QXP zn2SN8;ugt@#_tL9Gc>CkVYB=j&e0$%+O9#`>byvC?%udCEq5_V#WGy31&+@3 zysB^8h%BX|idcc4ChK)l9%;nX66`)W%3^I8VYc6qBxO`?rN_scmMJ=*2FX&-D{!Zh z6|Jf4G&^KP)4C|OPLLH%@0ad7gqqciqxe=!vZ6JYS0#>r(qtgacw|K@eqS+q%8KUq zCw48eqVc}+qBZiJ>G5iA;k0O{2t#jVMWc7Ny-1_Ryz2ThD&I^iiLvf2$Bhp|`<%8w zh)3fhS`pqVMY_tTDWpWxx0QB_#5x=T6rHe$j1hWzLC(2sNyTO}GWJS+3rq0RM7^Xn zqmwl1;P1144DV+sd;#Zb1SqJlqUlTYi3&M#^W1)VMA0ECGj5og5)tP=dAMph+#Nzw zx{H;EmpyaJU97$Z0;Kdpr|~HyW(sZ?}zBRJ#&yK z?v#mtR61*j$k_8dR^>Cs{ZXH!hRa%HcJ+Jw-bfvC-uKN444vxH+Su>xZln&b(09t- zEJ|H-isaN}xCGWm27gl)ujg=QM)0pA1~qMe7M1kVaDU9rUvK^IV{Y{4zx>@le*f){ zzxno`zWw!Ye)-F9Zol~cyWf8Oo0SV1gJx}iUSiCYUzH)#T@|x&v+$Hlg$9f((pZ%1 zX}~H2tN|19fBfFICt%}FK+k03)_|4uj`%~cNtvAQh~MrGBfxN8w{StoaMPs6J;i{H zc@4-df_!5DW58yK_v;;tFmlyNVz1C2PK{y5!)zg}izu8v*)rX3k66l2E4UpbbNOF? zu{y1>`YnU{vPFVGCeqGqzr4e7L8*h)G_Y{!FtFhWbLA9UB>s*!`rT&oi^DM#$`WG^ z<~20^UM@6dOx%33gG41DmErnSOG@xBv;MQ6GUO}#&nH_AV9M6pR$ijxSX_D$9>=DL z%2*8-4?Dz)2z#{YDTa=_+hGR#EHa{haKeqGRF`vTvz6afLuq(C!+Ey5`c)(R3^OD{ zuXR^_2`{b2MRaik%60rY=8B0v0^^>YFT&`7>i3R~7MxRXe zd zA2=TV`aj$G(Bgckmgm>;z?jE>SOtttF;@OU_0dpD91SUshT(~*URZ?IZGVD`6BQ4f64n7@_ty}6GnoYhevmWs}zF|>vo9l^2yA( zFXyHHfjf!i3<8Aw?p{_GF1S9!Zf&t}*sb%wg!jK+M2K+qfNN(!R0QUKl5y*dz7Azi z78>oaB57PLwGvhul@EJ$`W662?E2~SsJp?NWMR}dXcQ#OTmxZzI z*LXv+*u^;eKq@gTieH#6D|5Vbqa)rYK2LFM?Nhnphvf3SUkW|S?Dv&C>|rpGss@`Z z@840Ctn2%zT6VO5N4;@>kdW)>j=};Ule|bt^5HV-jP4UcDmI?h?V}*tJT2U;H^>%d zr0sB7cYsk|F7ME;a9I1$m41O^NivMbi}AAQ^svt_jTnKl`Kavucb`)6*afb39GPZC z%LE%U`uT76Hk%f(Is(90JB|*=H5{rx1?h&I0d(+=;_)8_4BA$IsL0HWmuemFAN(1= zuTypsO3K;AMlm7ohI|8-k9j^mNKVMtSi82-p?9cgC#nzbT|BG!1mCEqaGu%JC>g@J zM%G=Ai8?jN^$-)b-T4^l&f~>9eH8{w+QW zlnaSHfZrL*fL7ywJn9(*O)KO_&({`PG?C4V<<(uz*WMgn+n|8!xx76J*=Og--h;ze z$x+rGVGnJW@p14 z2@Xznxd=0B@`P*8c0N&Tej;C(3`ziMA~;CAlj9h_fj@=hUCv!Z7P30 zjXpqdoBH2>7kWZw#T`QCPPR-Ag8`bYK|bVRLhj`p+Kot(O1`NFVZ*RB+PbmUuo)OUEjE>97g2J5b*6>N%3w$66pa-TtTWVAv4x%n z_s^uQqVHjEDesoc3=>#jOvuP0Im8Vy2^(qo^Dt!(5uWJwL0Lq{c@mKL~GRQNctqSb%h>M;E-Dk_5V?li4M zz)1wIIi4iY2?coG72x67%fCbt*|GZuMdI<6)di$dw|wh4uW(`T6p%N!5J_n7Fz zSG117XL7i`6EMHS6rRFgmfCVMZ<*#R9Wj1?cUl}w)18yD8a3il*uAq;xHz8UpNl4k zi!I8Gl(2mDFruE~x{MpQPRy{A5wV;CG@|mzp_^*nN@O5zUY(XIahej4ba$#Qh{JT{ zC6rUsBf_+Fm$#;AhH`4!P!V1p-iEOprxzS5(_lAb7O{P~`Q;M!6;Z2@Xu{@dzf|8zfYM=-*DXv?^?(4Uw#F*nWT5_U@Qwp7^;iZ!%R#w^?m!t+Gw z*)_9+lap;*BK~GrD3n6JH{+(^54gAc(SU2Tt_EsRqIcoJ zdi9;5t@|-FJv?Y1Ll;qH*U(mmHa&)(6RlZwB*|4GYHWo4MH)Bqi>(;N=Ek>J2`l6` z1g8`IX25%KTja?Epz8N)<*j%>>6l->_(b1vL{YJKI{?M+pGtC zRe8Cmlif9J(A_3~snS7`)vtR|UCtRcI(YYzbvX9Mh>J4W&0y(?qPG%Wf#_zVDxWY; z;TX8IZnh=i)3SN#&&H#hOkQ^&CkF23fMZcb&6FdjZ;yu+hXHqhQIss+k=T}bC;Rj3 zU$SBK>u-f;`8VlLAGL5@hAOSr#Fub75eC4FhI6LQp&B@U%~`cMNobW*F0kC0{_TaG z94T`9+{e%2{p_~#9~JM30LaswB6`9+yLWHZC`8}OPIWW+*WWs_LF{B&H|U?cS-1;< zf-_;f_egGaisPZH6ME7GuUw8dO}4p!w%sYG7}#)AK)Og{9sVd>m}=%%!?RCOG|Ov` z8;)cE+t&Gis4ZGUJdL+3l7+)lv8$RixB%I$Ijj`=B>b%@BIBKAuv?X0E)*9`u{cFM zD3L2273ySG8=g+Z+oIqB$(@9P^LZHor{bJ;xn6K?=TB-8MIPLJLWaUQhdwlia*4)E zV;s7tW!)6QAasTVe#3-OOocsNc@zX!vj<~@oxWaw%J1%Aty*k>QJLo*=L<<93v+2U zZT00Fd5R_B;D#8JC|gpp?=QSueuS>WZs;Rewvam^`VP+vE9F`iQ%cErbNsZ#gWLkN z-7{$!*yd0Mhh&_xhepEB*;KsUE5YUVn2(4GOPfo_7GIm$-T*D6(@Y`9FIr}!F)(oX z(2~V}M|*aKH-gUxvTGXY`WP77|Mkgkr&dC_S0I8OLO8^{19k#vbQ^Gppc($%5jEGb zVWNz)0>Y#@;?C(AX%@Cz`;8N5;GMAXs_C;uenxX00tZZS911&w0tHB(%l9V9R?4WE zkh5Nqy#^=>FxfUIu{~EDp89$E=4ERO?6OCH;zxU8=xJ^}^_0!#&FnDXa!FuR2h)Bb zg)9jEnaXnzVdrw7+<_rA1WyasvSxzds8MECn}&P1)tYL;T)2SyhV6^*5q9ijwNBqm zorS7GrKEeoQ#ejF6-|Mjq%SCmM9&Dis+pUXC&d2^_nvFQ>kJ?;9%Hqpr{Xb|+hh5E z80%R7*Hp-`>g+*r91qvGg72)@AU&w{%3c`=V3G%Wcu83~LNhQ){)kM)bl6RVFkW2% z2e*J37?#TcedR{?POx8#*NDp3N;mXgkDUPU39obr((sPLk)?KT$aZCH?dWnM@0Ed6 zxPv+=R4f5Y*sO(M+mq}V-Mv4sm;!b z>(EQ&B^$`nL&CKLozn4IE-%z(cMheoGA9Hsm9Xfb7ev+%Yh9j%>1*zP(2eQYn9ERg z*dNB%Xy()jie$k_a;0S8gbnIZHex14Xw(<_CiRTnn`Ov8vVfqezNtyuf3~&t=f$>b8dzt zHMWhMl81fR)SfJ>3DmoC*iw!?q4w+jr2b~#EtxROH6`(V!pN%)Gta*m|+e#&%=d#>8ghq_O>*&-eGwteIJN&6@k}ef#dS z-#KS{Y1q26nB6f<6w@pzLK%jZva2qQwgF01jl97$R&iADMxg?Ld|n5WPi8+^dFWdb zchk<~g<6{4^NndGk(yGnzaFdX=UTQLo)5d>k2hZSby5p;1kzrl#T0^QgR)RB3cL$< zU(e67PCPc&i)Q7ubZTaeuKA%TLLgqaR*Xcy19}NI1(1+SElfk@)AQ4T4b;v)WvIzi z+&An#LrFv=pN%QNlIP=C#?BDGF^4~iiDJ9pLh$C=@o%N+$v5mof=w|WuDSx=on~{U z9tZskaA0VM`m=a_*fFV<$>Upu^x)Hotn>;xanE1Z%5L6`qUK2`($6BQD3kmWpWk%0 z2=h{UM1m!QEH2j4TaUfSf76DqOP2?K^OsX;-zj^jCLcioru2)x>ll_#5J_bg_9yhT zri*-N&wbQXU7aH)1w={ao1Z4Bf1+kBs5*jM=&zTz|L&DHIQnWaj4BlqT8B}fX)TjIDGza`vc(S?}U) zO2sn6{GE!*!27UjDn*?ywSnph!+aTw?c2#i-Tz)MOqc#(m&-d1Q%Bz{)nLg#{LA+M zcc#}bVH7WN!m(?{&P%Ry3`Nb{bt7dC}o=3^v<4XHrSF^^?2=u~#66?oM3}bfcTB;~(T1Zq3 zr%r=CRasiQ+a$b6bGMpgZT4pa zHU1Imm}@*$x*W1pGU+Zy^I*F5qhsw!h6O^MbOEG`s;xikIz=2ce!>=iv0f+H=ce%p zlD0?~t-_EL?JaN`;!d|gE?wCeZ-SCW4^X32ub511%;-W_e;L3Ntx{I@2p){gI3)wd zjPa+DY$K%uu6_b|J9w+#TT{*|^;0H0l{-oaO>;TiQy30~4%)^~9-x0Gn+-p#Y3x%x zNdkN6dbv6R1IA7-A(1vO`%W#opuZg5QctN_vxgFkv<+<3bem-%TI77rn8=)c+9|a+ zRdIUzh5?JJP{K5eT?=85UkvN5269g2^>*McjQ%KA=+5~!kv=IW{xk3&ca`mH`&UH1 zx9@zF$*$=Qj2-bio<{XMj{*z1$uVO^5ot51Y^&Kf) zpb6*WeDt(x)&+ZsUj}|YjN+`%Qf?V9?)1%aJ*F7aCYUaft8Y^*N-3|W`Yij4Uk$*iAZh{) z3Jt5Z$Qu6CI1)Nv^cbn}tc*N~+g+NTqS>spxNdwm(oPzd@hi*!B;>!-+}dMw)_q@` zo+>XZtuxQ8c#M4%T4s&zts+il zna)Qz9%L+{rtFou)cV}fG{fa#k(dQ!$#BV(6E0d+5@{Sk2d~vYF-E2)kf!*0TKqJ# z_}4(iCB~R;UY>NhRoYZNs{O+jSI4em^Y*)P#j;-AA4rcB2}T#IimzTyjI&(JncraS zxS&k03Tba1Vsm3s3v#0{Yeb#9r>_XaO3s68n8{P#f zIO$(PmiPBF&nWI5`=A=)L!UKewwpRUA8|1F!L;{5W^;DOMxo!;oxDx(p&k&B3GRgM z_z?@^&-ksWwKIr91F3?}zae7dT}$V^kb;M_I6sf=+OSe7px39wyQsGhP+021Qh+gZ z{-u4M5VKJbtH45I6Z;;+LV*ClXPoRX;(%M_(7!xr4bNr9Kav`i=;N~lBX#PG{nK3< zQG9)0f6IAGddI*B{w2C=D5>mWMyCL=$-iS+yp**yPu!kAHqx;9Ywnb{Zp=+(Mqo>z zxmfb?tM*_17kQ5d2A6M+OfHeP8v@=BR*#>tht+lo=pt78b*&Sl<3~q;yc|Qy0df3x zF5^D)?z`*vq6;A9(U4nUt%`hM!_v?diBaO#?X^&wSwudm65_IXQ2T}2$=D)MZ##n<1ItnBQZ(b5b~-O<2ZZFV!nBaD?XAosZ5!RPQ3 zw0ySRpDMa5=_pSw?XOa%xw!0-gl}IBJF*6&X{ zx7s>t>a{ALqlz~f>TNAcwRe5t;{gZ)1IpLm2iUiN4N-=`>WBjIo~3F@A|9S24iq{9 z{Oo(QP-Pr>Z373Y5xWNr#v@vJ^Vuk0)HO4-Ora{ruJ~vKH;{MGon4Bh(wX;m|FSHp zWP>}T>*_&tn~IpgRHHY1NQt~}i3EGAOCxvgEoz?+5u1M0?ZE+Dy4JpQtPGn5l z0%h~~=6#OJkZ1Fj!ZUm-3r2?oNhb%XLT;g`(jBDvq0ZS~EL8#md! z|0E3kcn$`8_K9miw(Guxy)_!{_H_z#3d zL`(S38ZV96V$;Fkno=8&RMyp6Kiu<`j*XO!TxS^o&oL$GVNoWE%Tvmc%HC@!JCBtZ}PcsSs)F+?S6J>bp&1^l%Yqy+xg~9_f!5`;> zTEuP#XXB+G|4NPy+V;_Ao>R#z?h}7?Av`4wues2o1(XMu{1Qtp4ukCb!QBz(tvhA( z{Z#J@z~3c`5ZfZ>dNItSTN^`v$YPYxAldJTOmT&VGG{euD#-L5tDElSUzxlJ_rcCv{Ot z=~~VGYs(}3F^bj#uw`AYoXxoPi`&-J$=#|Ppz7-UW%pr152#oJ0SR5{cN04;NSA&_ z8&wpfF*&paHxd1{A^rnzs$>yq5em)U&w5+ZC6>){(mz(#8>hG z&6PL26sxJDu%4DH=pfd<-*$*=+Em-4+o01YhUn@yq`KYBoSs71e3jZbG2dwKNtpHk zaytbwbu>YV-@BV*$sMn5Bws$xrruvl73(UXq7{3R9qSbAtWO#K`DIt3<^JNdOm^~W zPSB!N7~2k$Hq&pwCy?8rpJ!-qTFEMOsJM{7%l0wi)KRfnH-?bgMV*Rl?1$<`lLys-jyT`SmB(ma;$-_0u;DYugGIGimV#B z`}u3&r=}LyG#V@06~sc>-(9|>X-gtkb)vDob>k#*Pq7g2&JZ3=@<*Ug86$%Yn}&M}ysJP; zn+#R9!!#k)p@gDhl_hXWx4+Ied4->?a&ypW{4w+ucB=X0ZdPo2}fbvg_RvIckE(358NimNQ{}$#oJ5Z2?O52+`{)q%sGObmOnN9xsoSGDqd4JE~+CbAJt+` z|N2rqfcdCZfL&4u$dy9Ln+Sp;X4obBX-$H=&91^;)JU{L)BN{EqaDMe{?HbRtXB=u zYkBJ1&M(O0Y){)nYFg(h(B513^!s}DHkl#P8WlcDKxFYL7GZ?CyU^9D&3_fxQwmLa zV>)s7_kuOHI9WoNy%~i@dYKw5sd^D=R*uQbqj%U|!khU7$XkpkO030|{z1t}pdBma zE%!lFy-&7X{L4H)C}6ASGs;#66B%uj5$hDsHqkV~>SAaR(8?Z5-pnjWpS6@0@^3t) z@0jL?Yg)w!m63;VlJ>Hc40Rsc*Svn|vwmG6alTQhkgw!+AMaOdF>`ynTlXznsfC>m zOOeoi)`YI=Kta|;TI3?zT*SP@9QxGIZrD42C_g_)&``=;vog>PMo;Vc+a^o%FUFv@ z*(dWm{$c_@dU*~)ap2CSI2!cui>p7B!ZSR{aQeyn`>;Ze9lXaw5xJvBGBLB`-N|j* z^`5$$&)Nxfq;{8Jw{N*uo1|C>we@aFg3!amVb0wnaF`)B1)AHlIQ~n^ed7E6WUhY> z>+z5!hKbWv2;y{jy?qLZbNhC5>tI@s?y|;hYrW1E!y8&mkZN@H_T=L8c7sJiFdAN~ zoSq2&y@h5_Y8V%C?NnstpKmvBPlq`^op@rlt@jg(3^V2X@7}3{3f(5YK(qD$(w|}* z9`#KC+S2NP*A^4!*19n1{k044m3_g>VLQ#4f`pW2six$t(lHK>WwZ%2_*{=RX%ojP9OJxNfFlWmLUQ4+=LC=+`< zd~v&@a)0l(p6KQ*9Qb&919}&`elX(bYcvO57h4g6+Md~H_p z{{0TAk~MPk%4@tUL~ZRmH-saTKZzg+4*3sXCT(dGh5Yc9 z`1Z9@n<3;|8u{hpp)I<`2~$k+1_iWFeF_DnZnEGr8~76%E9~wFc6uW&ys=N6St%m}9J9*u8+{(VWW#qa&bL5fC^M}mYZJ>u8g`%Q# z^HZ_@b%8=i>J`7Gc9HUZ>;0e!v&PY*#^ z3a#PPI-OxFpnUk=l94sd{YBM~XZ_`{>f_bBU`KMdY!0;0?CJXto}oLkW)kSo{gxsS zTY>z#2}MVh7->{>;L+&6i#UeTm-i((0i^^i(N2dE8p1A`o3qyWQnrfM{BTU!8oRm4 z$$BkhHHvg2A_=fW(SGCsw=_xmdkoi)9fU3oETq!14_bJrW5#@uTgL(ynOj zGRu#gviJFHOcWadJFO!qUkbEjDLU}xf$c~0rn(x?B1#7I z-Lwp&=W&g>y-5!BhLYvgPwaWI**}$)nDEt;Ij3-c{zJeZc$bn%kPapNBS=mn$aSmy z>QyAk&v-;=QR(4c3uJ6v{9{_$L2BJ;II#<%+BH0it>F(NI9KV(UP z2c9|UvwiQaj@_*o2BJWnmebO+$bOo3tC%8v!~77fZ`sf;YqAJVfC*NbztM8>NgkK1 zD#B+Oadh<~W!?(hK+C*Lw^q%I9$)SCaD11_&m*z1u~fYeu8+HJUgCj6b7ODC+wW5|Fa%lC&Cei^#1oK9C=sS2Ri(alA}C0E z*#AJ8WBoL0J_QR+kRbf|TQ1nvj*3#}>I%C}N*M2t55wI$3+rirm+5=Udh=n3nu>lg z@aSSEu(0`x`WDE+YkGfa^IqbM&&UuvXM!(Tz*jzewSNupbV@YF4!^QM2FZ(_@8{li zsP0|`L*&;_SONjTy!Vy9>-voKLe3D$(Z>}&mG?fEHA2osb-JDc?+&$gu~&HM$KTmd zs-f2fyOUE7fm4HSxB{KYlQD)O_0xRRaLOa#Vq4&XhSJi9_dEEN|;nN^TP}r3q!^0UjTjnSkkCT-< zMn7IqGPk-Dv4ROk)~LrqIE<8|X8F_O1Z7?@K0aWCXbg58_am<9v>-)tuLyZA;^+AH znPC&R(+%l?j^jibbitMv=_Vn{Zv6sPlx?-~28p^k>M&d_Fcn(l8%lTqvzTBM_!tW< z_k5UP+{b~qhtdb`hFSlc@TQPa2QyR-J4~P98DZAy3+Pv|Y@N@7WkZ8oC~8_T-n3Y6 z+zg;UHhv=u*SSK^L+#{l+b^o}qBB}+W*aG=#DJK8R&6_Ew3U4w;7i5OV9zYkd4Bh% z8oSX4opZ6FeD}J{P;h^9gDkISQzxX#I_|{ZeG{d}5Eo)VbM6GodAQTin?M>)cEpt* zZBll4)$lik^$W7^E}3QK)`QKwphK6_5)nXrzRCompAgJF)YUPRf0%iz`4381#U;$o z^Ow!-8{ZsSL4QyMIWg(4IwTsERY4`zvk}W^?yjY7ND$OL1H7`>c0fp@~vnX4}&P;Q9w!jFL zRO3|pZ5h^-du#yf8sD_wzWxgBHe(50yfCK9{#B3_%U_|kxI_PhUxA!JHw-RGgnC&} zN6@F@Fj7GlDk594~bx> z>D6`z14-0UpFvZcL@PG0juwmhBiFS4LaFqd`u=^#${-llKtH6IiLX$f#ZI+5DNha2 zk5m(=c*WWqQ$0C;he5GP&wxU~XVY%iC4mtH{Qc*Z*yrCe{MGYmnnLOpP7QH;YpvN8 zrU%$ZB9@660|I3wivUAWsFqM|W5Gmh%RDM!QX(nw9;Weg9Ob%RRY^9onJ)x)v+h|}*kR1WV&mS|V-J<&fsJohn!zEr;y zd-MDKU{!9wB_{xWhgVi_2;VS|3lXBd6m0=7vMsuG`k5ld6aqH-G-b-*W@{C{mKUtz z%;(r2+z;;<4Yd3Zw$9_9tj!fq7$Odsi2l6bm^F@kk_a^?xc%f)m1k;O3}p}Js?vS? zkM8bugO%E^Xy=cmY6u|zTr3R-Vmsrau zE^JGIHcbSD7!vwB}A#!a0J=#wCMRBk*1KF2>2ykCR^JwGAMXq z5P14C7?1!60bqO6>sLPP-9ApRPlAN%peQl2H9zOz1Xr#}2t)<$dzDA>%RT<&#+N%G z^N|KLIEZg|;Com=qTpFpI2SQK!96k3s*>>YHg!MLeqmvh*wNR#+saM#^L~+Sbo>Av z<*gHsj0rZVE`EG%`Eb`V^T4!FA%2!*M9cKW*BrnzyPg%@Usf#23M%1dq50X+u#d2A za1UFKla$)MZ0Lp+OZd=a)Be$?veEz8jO0kRnF0f~uyk?hkvknE*-8scd zp9U4npFw>CPbu|9`GWD)9^H8`z}(1uZo5&{X@61&DvOgo1!=ocfuXf^({&+KE|-V+8P1#`tf>@eb$-aFokZv$KL-ls}^+Bqp?kXbm1f66(3sc%~w?baysP zH&~^Tde3k~C)$lbPrv%KDPl4v+WKqRJC*S54((BX)H3rid4@DsZt zVM-CC{z^(lSi-v73lhnghBtyx!hm}YgJLRVTY<=5*B}GCkZi0!-qfqmijgk{^9t&; zuo+TaN(VSlty()-zmKKi3Qwke4>>KnuY9j(W<2_A(1e@)aM4u(W*mjNOT9Z7G22U7 zryJXO%8HOwWq`l@W7k4`??jQo)f2|Xr~aZ;Pd1GaOrAXH*m43(94#<)H&Z!sW{mg* zk-pmf-fRb|-I1-BhA)FRMzA1u$Av*eA9s3{bGW2+-tYQ*Ln~xezMII}8X(5UEDQxd zFVp#r?;pZ*PhokF{GAAJLXW_Qgov+?tI>l~3wJpW0A_!KrkoiW1T67|?t_0|*1g)S z{GrhJV`|9t*s6&|#5&)dC`-~LPsd;7=6>l>cU(IYfQgi#GdhxJ)4mHGTxeX+mb=!| ztV@Lr1#a|kU*?1>G#^+S_gj)=hs?*q>gB0eHy5%W4(0WkmbDi&G|n{0n^R|8eP_$W z%KEyv4U|1(T`F?&UGs_9#XkR!8-&n?Lf(f>v-LLL{P#KZSZ9QQX9Y@3sKg+(F&kN} zE3~nfF!kkrT{061l{qMh8v5Ma3*x{N$O%vKzvqjbyv!_LUm6zReF$7FijTkiCfGN2 zpIgmV!!~X})N;CEQ0!%}nRo_izE%GA6CmV)v;1WVRqtpxzS<~If?S6tx=njsKoa|t zFnP<__vEJjQu0U?%>s(6e4=(cwA;yH7{3%iMi~4gE1&6~f80>rnS& z#e=FaBAk@@_^<{XA3R#ILImrPKj8%5#E$bS1>-zSi21j$w$5I5mHT}p`48QJe1)e#DZT|zAdlTPr<;i!z{5f1+;A`J6 zQIBnRr?*3M(%k92FV>q}{MP)G7G}BbW^lkECf%K?fq4i#w6<6ZG3eEy)ehuP7;cq6 zXC=nOdL-Lgy^xa=Z6zX@HI!d07TcI@?L?7rG`|wqdCN6gCla?fEFk#pR1D{ziyE(| zUJ95hc~H*#iEC{wX$b%VH}cK_E7Wp~r*#@9ccR5|DaCTG0vR?tS=%s}83$X^!=66~e6%T5R5{$s7vBIC+;s6X{ahQQg|DV4-xdYeQ z?fr=K6Ic;qss`dJOw-CBob)ov=>nZ9suKP2|0IV~kwtpPMIp;TB?IxCj}Y+*uAQT|`F>Yd6*hErz}=9wb!+L(^$ zO3|u_y$j@?(971yVC1D9wy>MEMfw^uU?ef!Rf4Hs7vfXTS1MGO^VkR+%T_SnME`+UR=yO9;H@u>1n0q{_+6y+xo5yH z4`LvHWO=ADz2s5We`a);$ZuL^alB~rVMa6nAXae9gYYv0(K30PyT^J%^*)g4=l3wZdMSw#K*=1z>GaSQH zhO1H0Ob;wG770_|D)_&&Ap@gn3I)miCmD_bi=Mz}sJ*B!M~FhtyXQT4%{YdT=OCFs zvxDE~*cb1`=_fdeZvQ`j0Q%B00__>Zr)5J0|EgR_XRmNxV!;;y-(AT63SEfv#o|AVyR&t*T^RHL{$ zGu6hal8O~q0GbxLAqMXo*VlhKB=ni2vo1nhafF7Iu6_`3d0fQd?D>eNB=c-7%F1v9O~1VJ&s1xl`NR9 z1~Vk5{?NWc8H8RbdpmFjPJOSe(JY~ja|NY!XLq=!?5l7M(L0UfZeU9S?DK@-EN+^_ z*K>})TZhlF0cLgju23D4lf2OBt*iPk#LPf^Mgm&WB}xPEW(QVb58aQX*gk>`>G$;x z6~JM;7@n>(<>Xeu1>ZM>FWzvnd&HRXSB9{sIu|+DOusF55G1}+j{k2$9x;RriSjR@ zXsOV3wTmw=4&!@XGUz@J9p{Yh>P|irCKPYPtlU{FHS=EOkMT+C-VsM}+LZS|(ITp# z4F!)-1D~Po>(a;lSu03heO42jF(_A*V<;vkx?0StN$4p#sCluyS5D*ap-;*ToPhf7 zRa$LfeW@k8K%b6W|NDf-teugzb7;86f6R)m_A1Bv?VtAkp?LvfyvolgnD`2l%8!4} zWGoB_%aY`CNfte z7&s~a6yj$QSSn>uP5P3aJ+4TJv<0XIrsSavwZ7N0dK_7!CpS|gyBm)^u9R{!WsMPU z)9Qkw@#EHM9Y6N)U_zlKpvx41{zSVqXv)B+OTscHN%JKByWj4X47Ebc8#~-9yK1W-hMRGA%YRLSEa-8z-nqnzRST<8RBOA zS_cF}+X{mu9EcDdCM5ILa(g|FiTx})Krr;#!2`%|dDJ}S$viwF>3=I;CFaep&ZyZ< z>i*j@OSRdUJrxQPJIHC1?%td&LGl`MI&qVwO=C@$HI zw9R{^3J4+Ik^o=x!^4cY-3XW*5O@m1aESZjC5WC$)IL5+Ms%2jS*Cppht6Q#yB$^y zh>1OA&@Z#Qv%QS-bB0)Lov?N&BgDD9^VAShTx98rbYrKqG=o3R-?V5mmwYOFAgkmf zzG7fiGb#IceHDRmRJU<-E?y4v4ZYw?W+SB$R3nBp0)TFb=~=q$ftgi z*Y|6J5k0A!Ys}I#CNBF`F{ZTtpq_@C@oyPe zZgDCEy0>-CUbcz9uWaSo-RWSlW=ZK&vpuWvt6BP{$rmQ(1|Av<&_kc?KY0MIOkbjI zlhF$87QEj-NW)y|AO-qq>Lh`%QiA zFXsc+e7GT)qtVx9yI3Drwb&_^3wdSU+pM-7^Md0evhI9*d}QgGdGIYUpJ(m=N2r#^ z+^Fh-mS6U}C$w*gclV6SFY#By6UBccL?nh1!^$5|E2TU<{3@yhM;5?yQ3oIRixyrU zU3?57mf+{gw;e@Z08yO+tdU>RxjwJm51Al5d^9aOgj-Jg<`~v zK-b@YdU_hdMI@uX!bJ=!W0!d|H@#J4TGUB@r1PcFLTw49{-Xagoh*PWaTX$|hyI3> zg-Cv=yPTYdnG{Zp40yJVvvE{BL@caq+3t!IHr4uyGECn_PIeN#DVnbmN1y|}6XvUs z{Hts`Z6$T+-|74+wTKLy7MvI*GKF%mL%0E~Fa`oi&EuoR^OFac2qy03!)h0i_%uj? zvp-lUuWuQ%oX?#L&U=;qio^Z{TevZx0kKDIxw~ZF{ZsMZOhACuNkWR=J|8Zwq*=&8 zDXSc9hE$HMB+W!a;^I)3oZus4_~`^*^^6Ruw()hJ~HMINtCFDd^pr1HOK}$J2?einUm@(j|V53^LB_Gih@@+C8(&9`$}9G94;m~ z)8`@u?ruexV_CROyX!%o0!5j-;-}<^flOpJs9C`xfRs7bgE?FqI zc;UQ_KQ}s3v5{qde(MzHIF%lYJiFw1R_diuSGX-)o|mwkv>gMU4sYoJ8LJ+|zOw=e z5*DQj2Czxzbd^KGyhkGA`GgUa5t{fM^ugZs6kjU^Dz~wVgC8JKCh{Gi`P`YP<80@d zRcpc23@2r+dAto*L>%HYOCSip^G5=RW3Bc?EI_f?$a_5?#kbC^JZm?uf-du;o5MP72JaelbtqqEJ4hx8@xx6MBS z{_XZz3w%{5f(%qgcy(HC`SXeq{&3wW|xTuLl!(U}xj!+Lve^lwPTXJ}^`K|Ug^)9xn_9cWXV9kDr zMfc9G_PU+uYiLFB@r&@U(#+#TbrIY-c}o7Np9GH)F~HdJgVA?BkEfZ7iKNOur(!EB zY;mM&bQ2ipSsq@s3cvg5B;5Q6zAB7LZ9~_L`b=>wYuQ zTp%Ph2BFdmlhN&*FizwN%AtnAL1Q;+c6-#zXO~jW6>awY`*ni6h6#b3f2Ldoj}BOB z02&MqF9ljrGc{CS2nihjoPM*V>DSm{`WwO%VEH2y$1m6UuO{g|h*tpY#jUaWM*^S~wk25+Gu{S$Hz8F48im8tEpxe4YRhh(pjW zyDAezbzF=~N^pZk?egR#q&0|&MDo^=z(ioLp`PmDPRO&)$YLsDg$cSfT^;s(_L3Ns zGA@gL0=4lXbo;VIgs^;J6eSQw7}}-0#r?Ba3Q1T&k0B%7vhv$5K!*-iW(y^obB4cE zNpZxibV>m08az;Goahd3U8`JNBWPxT6imbsslubCRW96G3v zlgH{4(VS;9BlzS$3;0h-2YfeJWWaiKM8W47j_OXhoNT*nxzMt~xI9vz;?m%zFa?+n%` z`v#eVnm&}Dl+oASm=x|t5?Q}#L?y8Npy7Y$Z(TGZMUHzNt9#N;m^`$6B12iMXQW^9 zmL4?teJ~+qSrCSaJ4W$y)OPpmd?p`&maKg;ICjm&fpp9cjuNP>bWKC{&=;4?7&TslOQ*%q`3(W zmBH3rwX-RCIKEU<-rh(2H=ib6mz}SgclY+f!Iz@Xu?6kU0n&Hp4y?(-J$HK>y5Vlt zU!0Lf&h-fS=}Rq|D^UKjgh&V3LC$TuB4awQyKl*9u=H`)|x5x6nM#}oU4{#vmZ)gPJ)`|Jj*KT+u9 zRZXmk!U+G&MQU2ShbV4k1@)Z&rxv-}`2#y8W=!Gu&%e3(CyOZ09AF>T zd+Is5kvMG>I3e)>bX+J@R(HBxuuLYe9?mdO1w7K?3Rg;tum=^YP>ue}taJLXt1Zy; zeV>0}ZR*xx$dQM0A-H6DmFyj#81-)y=#WklnTQb;b67Ft9ifDO?fqtcrYV~=%hmg- z#?{62Z+`EiNc?o&m-(rJmun9=%dJ=Wf3S;VM3%%%$lR9~*04U`g!<6F1XT%Jko#jQ z1p*jPCVe8SlQnMwyV}uhnsLPcsHigFA{b|*rpqxB%fj3QHdq+vXsz z3VnedvaE^izWq3`B(}gO_b=j@aIMSsVMYV>@4A=`?Qklv()0tVH)V5*kr5s@PQY51 z%Ug>4qH~>EwvIq~fsw`xpXLmO$1q=mU9Gj0p~erh$qABZAq=JqG2t*DC2~+!x5qzZ zt4nX`?qAq=#MgVf^U$Mk3m$vKM2o2&2`;2#WO>3=L~1TmI$ewe2Q$q@qWW(oMg0bb z%#REL;ex8+J|rR0$UzV}b+P-hQD zUwh!@z}`}~hF7=G-|K5t2Ti-piT^;xzD8M-r{~1+I%8PjX!6gA*?O;KpuCxg&%TQD@zGE!0CpXX+w>&% zzu(A7$U%zye7xdpZ=4B_m{nQ4f0epv{h-)I`uRxJ56j<#$wLPVboTK1se1pw(i~Rh zpFBn%e#p5hp)?~;LOAUG!SxbPEW!=xqFlS{Y zwSN2cA?JZ|!j59;V*{i{x&aO6tz}dD;LPUZJ3*_df`?|7>x`-Fgk)<48PP?iZl%I4 z!TU)ht0w~#%ZFJeWL%wzx%O2dK{FbGbC`QSFZ8GT1K6XpVH#$X_`z`!C z-6d4`{lh2*oJp*L++GNcUiX?1UBc7(o+0T=;JxH%llvVOAqCU*=XI5IidXi3hyazi zC+GEpE`P95syz=#QSlbommBB)&~MDVxtsL*$VjQL;NAz+ok}H?qa&lF`iL>#zzJ=V zQlRX|3&-5+S9cm{|9UY{_1;K-XfDHni+A;|p`#SWUPZGlLrRW!sR)Bk`a`7`!0>}I zq}uY0rDI@@4&k!frusv-~5lL)^>^#n8;Gol8;8eS3$oK; zc#5_Oe*rPk#{ynqJvB~N;PI_w?t7nQU@7%gr8ujnXa;a%LbrRSo38|6I;`77FX8>y zasIvJJ7x_bBD~q3<=TPIr?)Z2r2MmS1kV1V{`ZI&3mC}XNw2scq@Pkl=U?ej$Wv>d zKcNg-^O@Ntv<7w|Umo17a4_&V=2~Gbs7UrI1J{VYiRHW>A|%)XZ`zld4B0$lq1c)m zTk>P?w;zi)spBPus=D0_Yoe2NbG+F*f+T5-4}NwO>?u2yd+bU>FYqWfwp-2MvZ?5& zzc+_FTnet&;J?)pSyAO`Y_HKnac@sEc zU`)cdZ1zdnY+#dxPobVBU;4Mww!e%=7>q~~R-vGH@M$B*h4uvxBK077QFelSeR(FG z$YoG}-C;OKto(jZ{7n$i6oOlkIEPw4n(jljGTYgDm)#pJ9w+ir<3+%qeC(CnUzLvC z69qTFFt>VdB76av`S=vBlgHGE*AUGZz-Bp+JGK89S7GbZ%A~>;+Dc-Ch82Ic9dI%q zz^A4oPm|*-km>k0>zuJgZ@6NeoG>;i{)zVw@I{`Br60LV~HBiWU4uj&{a04@l5%2OnpiO`rec3wc$PT6q~i4 z7vGzcndI0-w~874vHm;7sug)cJfZ!~{O!}2`xa>DC2p{xieEZ0yEw+0Fq(tg7=w#G zIJa>0-@qPk-w{`n1Y<`D@%mieniQH;Oty+&7&ezA${-Dc@__UOq5=)Q7G(JF;Qc>0Urw-_M{y+1gH`$PY7EA zjn*r7CF7&=LEDZqH@iptHd)bnRiUYo6~pahYoY<|;|!8mky{KNXCAa0RmLTr#ZoxgcySuwP!QHt8 zcY+5eIDz0E+}$0*;u?axJ^0=^`(uCX?wQ#;(^Fkl-LtyZ>(ClQq=uV17jEdjq7=$4 z<+B`z7Ak>QtvFno*X8viMp80+mKL`9_wm2rEO8?1m4UJ$RBo0g8qzA3<3Owpy}2cw zxh9eXU&6dRPEfPpmf$WiXti_5Xf4;jTL1Ru357Jl=^$n*W_zQ;%bf&PX8y`2TlgO{ z&?2aKa^WmOvz@)cm|)x|v*W#fkiH~yxz=AW6cUjjYByL2%aSyfa8<*lNJW}ZJ>q6U zd8NXr#FoRrU!Jk@R@V4~K?At?o1vw~ug{;Eq7FYPv1s?Xpb{xD`M1}hkCn_T1n$_QeKr)Cs$0&gv7Tv3eE^DZya5fhtu4}5SD<;&7Z{x@3?p93@>3l=z`xmZ%8nRPpe~gMTZLqx=3PK4in+DGWl@t+&#+8+1Pz6-PehML*)9*)O&ZnQ$mpi(GDBNtUL2hJSZDT_gZf!0QA%SD zCyty2P^0cQEWpjUzQM=LqW{`ucooFYAYOHl>fhheU@toEkfEnkK~aqdoV`<`JgW1= zE6gz$r3mEg)id4Xnod3?-Thtr8_++4yb%4P!AXcTr@cSnM1$R0-U`+-=~uE&m0StN z*0?@L=qy%iOOpD8$mqa`$4_1CR}kC%JALrV)Gyi|#{%AO%!)+8H{SX_n;L7@AR;AB zh69Hs>vODa=Tj={Wk@bS^cz)jG!>gN(t58>4HuMOX=Yr_iF&zJf1xkCp7_O3-5Z!v zEbV0kRIZ2TN^|9a)&E5y_@@o{cr@Q*Bgn?GwTqRIq6J^Y(Xv|`P0w<4hrE*F_677XEBr>P=*h7PjP1fF58x#JaO7(AEfc&!f6N(aG^hg`AP>2n?d?fKbdYpJL`RO;@ z93gWr<6(4(jhH*P+JFITgvK+7wZTA+;>9sHe7P=EC}>#q-v46=&dY`V6KyHo~P^n;!8<5{ca+KMoSmCDsDk`6gaM408zv+XPae!u+a{L1IpR0inc zi>rqJ{=BaTENzV3P!`1|$^T6pHq_FCqdtetyJVe9{zo1Zp*RYDjxFg4SBLh6g6Z5+ zr{vyz=K|crE@h;PYl$Zb-Jm!e<@V#SE&o;%zwhK1l2LfwS|&947VSFwCfhQo{QRi^ z!aSDUZ&DNi@+hVfWYc38F(}Xwn=pXG#M7c+KY$T|ucJJ8!ruKv#2BkY2sweg%2KF~ zf!FUDtPwIl93&?lQnVX1T2O`-X^Zq7D%Wy0^lINx33FVIkUbVPR0AH1tCIs-0|%qv z#=#pzJCPwEQah3~8{H!wEldh7IcI10js>We&)pkfhPr2Wr>POhCQn8&G}5+?KD%$@ z0P4egMAoZ1m@M!fj)PtZ4qx7}!#|J)J&%8_XG%7g=W1Y9Dwij(vmgG;)wvRxA~K20 zvp{b4bV0=+dWX{I)54v*#265MDt+7EGIg3PR-2k@qEfc!m=Q$m9hv8l)#jPjm7Fwa zPg#V<_t}-~)0L-HTh3=TzUKmDoF219p(uO4O ztOL;`Va4{5{#w2GnUY(3{&;(>FGeBQlY0Mqzi8=<6RdH@VyDxWa7{hs?N`BUgFv_* zv-WNt^G*?zx(fRVJl=Q-$-l_2r25)gy%^5j>=I_dBD zr+E@2aBIVC&qi9bmEpkmOTEq?+0q2xM+VRY&f{bVRX?%eg?0U`$W-TO{^vG@^Xxr_ z_?sx$xQ6J^?|z<>IDD6T@Ff!HVb-%3s9ixe45@+rx4oV6xt@gS^l9-Ws|_1kKEI%=YqN6_{J-LYlF1KVT ztOZYX|3%zImsCWW`-V>M_sDTeE@=uc#=b$tD~W7mM8d8Z2)X>3c03-9@1ndIo$||K zWeQ8*jAXc2ky?8gYECyN;e8{42HDsYYpl}PyeV_NZ9F<%7<(H)|6-n>xD!krV5${6 z@Mh*&Ff(yvS3Y`?5EkK-g7hu=S$qS1?EbAezPf>8=zdD>)o$kEmo|6By|~+k=JOSx zdSRRp&LVg5W9t*HDyAJWkg?pU*zSs(yujP`JG;Sy;eO}W6I%^P+;c!b#)4M4Vq+$O z0RIg%KWxD{`@#EbUijK*AbTCB^ zosvzLfvZL@*#Kr}?cOAa+S7%7_+KoFcj=Nndj{9uswfD?8xuJ@YX~X7TrRtOwXeLT zjn>Spe_WyeRjk=c9IBBb=$)R^&EOjXanZzQDV?g!#|f>0CD=i%6Qm8X3AjI_ zO()|I79zZ&6u%}`j9r2?rvq|xgz&NQBiNQA!J9eO4J28Z!jvcr5$(9Imz=BXud_?F)X&*t;BeV+v^oDj&o zdd}+>%V(FN1KC8kHckFqLOQ+VE2_7KGyS(tl)0h_L$j^S1z!D`2we}PS5QOiUqcS8 zkslLrw*jYrMh%`(M-5&{Q+OF69zWv)+c#P^Hy~0>a62XCbOjc4lhjo;v|S3N4l~Wz zg@|>g@Tq8C{(YH$6U!3Z8rVM~W@_A)X3D3>U%GtuH&x;z#kS58IllUCG176fQ|K<7 zL7IY{snfzK?)@Z&-3qc?b0QnQd@0ORW`2^vTL^4#S-W>w5xN_V3*RZ$qG?;&ubQ>=Da9Ze@S~g*ojv{HN6?P#7#q-e?6!@jXRCob zCdWFVe8hyvkoqH&?v%TIu!2nS-e{SI{GiW%Xu!Hj-u0q!Ns(KjhAR2-h|}c9H+(ib zytaNf!&zxnC4$p@;vFBtOr*;zph*nFFAy1McUxF9)s!xH5m^esap5JPq1DL_zp8}$ zVaCbM68Q&TDj378f!Q-l8%(rG7eEgj2NLn;;m^sV%C^W0dOdCucQ;S~ z!==!ZOU_wr+LxK0rqU28%+q-|Gc#u={PL-IfzE878vm%y7an7@L|hTGV2r-N8uY%J zO?fQwj@vm8CxtpsJ-c1>@zi&6<9kY_7`+d6ee<6MjjA4+K-CO2AizPuRMoL*Xepn~ zM?QUNFTihoZiKO)w*O5hY*j>vFC`g``#&tkY_LxI5Vf(pGZBPyQL`XO5N}4ZK__9( z>ug8)K$vCWiFdQKz}o!22b}f=X|a08L~+T}LpB^M!w>s!t(~hZ*NV??Vw-x(ddIf1 zKZ9a2ZVTR{Ab@>dWa^uC@gVjIOb(CIpzGnrq8BPGU`A#C za_&8npb-x8&>f!f9xtznL2KS~j7kvl`pfIkRQAQ;6VG|kHV|6w##C01ol+QRu5@ou zsALDAL?EqOQd+UR1H>S1advOwfs?@y;Q&>lCir0!AickT0d3(D`5zU z%-_;2s}f|B4_*_*#d>U&2<4%3sVYbExOW#cVJhJiyCu90El5SH3KrGelU1s;xE1`w zur}w~{7?U&ZJ#pCl8_=~!a-FSrA}hO0{5MP>k&4i?Hr)9Ki!>4c3N`Z*v6X5EcXHN z0b_v8TLG(NqgjhLxxz{TUnpHYsj&HzW%#v3FyXMXI1UlppKs8{@1&_G%gRaG0^{hP zx=fnKw1qDqDeetSR0yfC&WAN8+1rL)6Vb)$tB(+Lwq_w~T5~+M-n&`MLQ_d}TH)c% zyz`*vBkymA(XT8ogwyY1!1#`Fy3pim0OZ+kD0ZF26JtG9Q@<9Px5_n}^sB!jm*^Zw z@y7bm|LjrWNQy4K!SHH6WZD-jG{ThX$er>CAZdmeTdW&A$q|CC3H}t{TGrer7vEEA zu1aB%VlSG}T*hl4ev+{BrNvQ~xEaL?fID&JAO072boJx%V~kED%;GUW<7asQhok8) zZH}A>x5Xa!2|Na8d)OP|$bH8c^Z8EYmDQb19}~)o7T`~V^YbpV?GdGF&eeM4Y6lJd zW?{AG0{vz=Irx(`WqmN$?(}EJBlm!}EvAqEy9INP4d=Cov%YasV^>*WcbBb=!_GJU zN{aPgPm8S@v-$%99!QoT;~s$iz)~9L6#Qy)y?K_rzJ@xY!lqqAOGvs_*wOX_WAgd@ zQ8;v8Fs0Wr*=m5-n=*khggMwFdczlPJ!a+~`jzaSZV8ea@!I{t5m{-!P!TT^{;8E{i^)0)NyyMq=f-(Y!I?0_-QJ?pKJ9$nFhx zv)odV8n}-g24?+$3oVhkn!}B~l%0%7DQaJQr@%HSsr;Ya2h&maZO&0KJyOdMZHRM& z^I3=}{bM7voyqI(m1S`KQbY3gG;2A{sr9}8Ke;{k^E1l%x~gIZ9d+kr!Hlt z5)@!Te^mOG1vY$v?@*xD0OQ}dg-0q7uv}Pu@v+O2ocVlmbvGXFM#5KLSw3Ulg)qI1 zQ`y!*u%%jlj2aZ|CQ~P>_Sn&XhOd4xn^m3M8TYRS4hFFio!spD^e358=n6V^T@hhe zQlPteFNH-eIgBa^hg_>J%lOmeZtw+$DcYz8-&9|NR2l&Dg$vvy1xHr-CTnMAIP-X7 zYY35EPvFb8W&g|f3g+&R=H`3pqert0HJD%QvV4UO4QTxD;znU_#n2klxg zsRl&%ePcr%hZ$SRSHm*{w(sGOLj4gx%e9nnNAwnWsG{<*Z{G52H$HW1nlm{^+L(yQ*P zk_K;OWsQ|Kuf@kimj84v8;UE3^+j@&#ke&+ehRv-Kh1|{ zW{}pW;!j*8dsKvt)ZqpNMDm-DeyEf)Rhv=o0_*|v7A18+`g_lTaim!x@&^M_t z6weL>*A=+)GMf8;t*jKe=c7B?URLH4ZK=;{X-p~)|8y@JLlM9%sf^jQq2qT{XU-Ch z!6$Cm&Elcv_!;y4#)6P!qfxk$aX$1O`_ych(UZxWp0A3b_oxwxwo(E`$prQ5M67E_ zf0=F*@H>s-UHurwvsKU90??I5M5tq^BZEr;Lx_eH?>ru~oZVc}hW)L&f>#Hw^6fBb z4Z%~Alx`5CbvnK;THK&EltlL>@95dD_NBAaKW}SgY0M$f4od0yG|xQ{2uRE0JSwlw{ZG|$EG$b8(}~I=UY^t*MrXu# zPRcF0xL4K?yTynYe_B)GMqBOJ^TkDN!o2w3-$99K>Z0Fs0NWxg zOPUkrr{7MbL!LPY2XdOlzkdy^sbJZg;%%J&UB-OOiYRuJsIyw>4;mcLVdFSIwio#w zM~o46K>I25tFY1YOjd?igSZ>7LwZ#354aw3*?QJFZd2(Ux|cmyy=tQN)`l#PNE`C> z8qg?QBf`KL6BM?@Iu5^kmgX(v1JJWb|I=#3OdMSdHqJ~nnzHzkk{VYkz!e8;BC@#z zkFUD1GayTUHE1b<9IL&zUZOxRpo`nkNQI}b*nnsmnYDFGgN%i`Sq&_C3KrsfajHJp zSTk4}Zw=8fAP=110T=zGZx5ggm02Qlok6qAj!mc2Po60klgbG%blEGxfCiBhBs+&O z)1P1s*+)9(>1y-sYhLI_+*6&fN{NIn!C^Oea0(f{>zuTEWMnP5R%eziEbVmbhRrm~nl;FmCca2U_VbWgT=vQw@0msYhzus< z>j)O5O0vfZaWktxscoO&_*BkQQ5&(raH3X zEi*>8elZ=*kT0lb>mR=ilhykj`}Yqp@N%5kRm6v{SEp;|{(0_mRj#~JigzYnGK)Fn zaw^{p`Q8WZv{zWiPX(^hBt+%o%nfBeE3SUDb_n?A_#Z%?co0F^j6hhH0I3##O#bCp zzsPguo2e&D-1R1C7K?~5{`76i2_PiY*7vllX+dikdZ0|yhvAQ47-3Yj`@m*V-?ez$ zoJ1&a1a0dv$HAIJkF-t>(Nrl@{S?98&>xIyyp;|uMnl22+fnkh2X*QMKK zq~NP#KbM-fj`*1nRJ?SuFvOYiQLG&iZ+EBS-to;fG(roju9~qk#FdQa2!ujN(A2jc zAN!#nbaT?NHUm1_&Ri;DO7S!mYIeZ>hiV-Ei&Y^QX9)EPQ~Ek%cekiqSE{*P7y?_q z4$+dwAS;kWSTnKD^TTjJ``XAmZVmU0kR|W+d;$k!@i@iSX=vFK^Ec(yg{LltfJ9O42;M#K|12@Vm|(8vVY6k0!P6(;^1UnpByh&;`OyJ%@Q&b5G%n!o0{)* z`oj>ND7>RWAXG>Y5J5b-MDU10_3GpPJ9Q*F2Dn4`3Uj5n@935{n=gPv$5P{w zt%V}M;u3W?kttyW)Y-MLE6n*%ALNv#4Ghj1Hnf`Dvll!+ncK4v;5(yq#bRWdywT-G zZdK9pJxZN)dN65^JEzhXi>cJ0J%lWcs}`$F<8~rV`jFpJU}pmIRhV=m*H#&

    hZSIn~7tBy}*6f%Px`3Y=7E)D=IX##Vsk-mFd#qzoHy z3VKE274~0&2kyXEf6dAgTFU4ku(AC1@s`7>KN8tUQ4fUA9hI92FZ>$uPTf2G8M_a2 zB7zz>*6|ueZzG_3fl>RX zRm6IMSp~SbT`lfJp1PAwn5sQ)Z@IIX$!)(Y3&>Q41p-cul{%k7TN<2~Ft_om7Ct`4 z>zGFuVl(Odq!2OXmTk=TZSn)sT3&#Rh8V$Zy@_*TOGM`7=hzee)ql6gb zEwQDOD6z};PL|VJCZwwYy;~>ypg{XXq$@aF>>T2N!1!e+E|+-}lRhz#x`8`dB{lMH_Gl4Roc9 ztBETpxJ=vf$>34CML1@SWDKH}V~I$So#y*n?(?yi|4_Rs@)U5P9Xj-UtyGe-&bJ1SU`gj1Oe9fsd>XV+{Uy}40T)(MGM%e3~Y~Cil zzp=}wx7METZWA=Y#FGFFPXCMhmyqaZb8vy@kQWb?`L$~^1QxM+QU@n+Pho+3)NWC6 zoaL+es>U$peh#Nks~s;*%s9V23dj0R_(@2Ww#F=~RKUe^l?tm8gDF+cF$D+JRXrUpsY(}qAV{lfNMm{ONQvyATP+5MZWpye<% z#Uy7h!Ttv)x!U&%E8cPWk~)Ea*gkLj6uIn;pY05jM7$|w?#6R$^Ik$V^kr}a5sP$_b`(d-DHP=}N%0T!1B7S{K9n6H%6IONa?N{PkqCf2+c zuclGZD{r_WJ6G?j3$@UM0H3k+r5L4l&^8Zqgcdp@#JuyO+2wzV7>Kcyx)dkw87NhI zQgw{~W8>*NBkiFFTqjxh%s)MBzrv|Ew=?Iot4;OMCH0DycW-v(`&H;dTEb0!Jh&i0 z%ZvicKy{GS3HkA_?Oo-1Kd$f@-!o>A_9=JCLDQ&{L4m<~pVM>0iGJ6m=E1oHwh+1N z4N78#SENBBawqjoCST99C03WgB!V?gK3S52nLTq6&C{1wj7G)lg4Hp zD@_X_qdO!`%ntLovOe?yvQruAAD(?>NQhc>0z{`!!j*@@JL*r#OoBmNiQf_AyhM3X z9!O%Q2wK!l#22E%UeC#cWeATDx`!A&H8`Rs!2fNN{f6puVrSBhjOm?I!VKpa3q!S0 zrOr)u-eFZE(xrM8@&qK3u}LJ5_*gmbZ_^8?QN$EF@k7J*{8$wpcI`;H4n>vrtNZyz zqrt68 zl6?tC?W&H@m`lXD@)~5(@jPOPf;w*t(p-dV8`Nn+)Mh~y?v{Ecp1MHjw&r7t;Ez1; zn5Fg(@(RInSq4gQCq4FMa$+lcO%i90*`^F5w=us!wJOi(Yc?S*JjB$FmR|pLE%(cW zL_;0f%BG)AQ4FEt-M(MtWExS&(jD5mKTp0$8JgZ#qLYE`?N7#_YRMmXjfEyLD3R_b zS%74-%*J_Ug)$V|7V)V}Ibpu@Fys|Da`JoDlM5_G*#|z!`~+*lZkjcvrFTx>lqQ1G zXb=7EZ4gb+r#TjR)hCo6Qgw=E8MHGo`m(>@v>|a)clBkx26jaF4gz~5S78C5>s(~$*`y$cYvFkg`JQ^=j z#)vW8uOhY28ZTVog{eKmG!pSDSP%nHI;2DQa;^6_pIcXaKJj=(YI@SUQ^mG_?=zFB z;5I_)Qg!pZb5*)ICGuksLsQpgDYP3ijCD&GmMaCg6h-7<#V&se90Oj+)xGxLu!-uw zXJuO^^d}5>De9@VW|CDMPQU!7A5P$`4(^;FG6cDvgnfm^vb}?ctYjaq$AsaSCTGW8 zgl4B_KC;y5W^L`+4kisl4E6bB^$qTv&E3V&^(F6(HOaHmgE}tK83$4Ar}?FkbCstF zB}X-&Kva|XL*PDVrqjZnN5eV-O1LWq&MP`)Fw6CXlWHoW$i}eUc19x6;&N9wCX9%m$Z03cUxA>$#%l*R{6RYCuKW}cbQz}Zy2(}+7XFuQ=FAbprz;nq; z{k_Q%tT+=GvWlDoo(xGpx3M`D%eCq5jj?*^s#>gy(&w z@}Ui8l%`Fi&QXW4y`#8_q#m4TNj~QvTCG#wy4f(FqE@d27-;251Ta@RZymgU!@7{L zuj|dAzkA*)@3t)6con?=!;-;QBlO(J)l0UM3~4Mk-H9H@7Zo<%E7M`e1Soytynqre zxN~_mi`^J!YMRNNZ`u$Y(lo+OM8sE3p?5C-&M9rGa)_lXE|buaEsC2>B)%$uFqc#t zM}1uep+lRCh0ETxa%2QXsZI9-!Q|%VBUbzJx#+{xK7DpQP^(?+L{7NtVeaA(>T=W= zBuev}HH#85Zdl%bCp3+R@V#6CZ;GhsG4~2s@ai3pqbGUMx^V9O)QEAo}{M?hFCg^LgFTFm#q5eZ*E`m^ixC7INFwiVwbT3-p zlt+w0ix@(65n%e%`OY$*u{#W@>z2wI^ow5qoOcrxP!~#j7x9dwbE?>-6)cPKOxlVL zsHd#ZcKg}dj3d(dvAui}1_KxFjhNBCU)r5~Buw+NW97VyWPV-J)=3PF&Y8n@Nlgjjy9@&>7s3<|52RsQ>e z>E!w5Nn}`>^U3%FlNl>XHY>U-5G;aRv`Ck(9Oj$1gw2-r;mwtDv#|_dCUR8`IdnNA zM775{;0osdO!S>=bR%3D7%LPI%UH>!pdGqKDFM9>@w9v?rI^|K9IWi7ZuyZL{>$V@ z=)KzL?Zif@KA1;!3!-df65>X?GaPkSEIYcvsqW!`c_j_?e$q3`q5v9Nbfx=-_aW1y&jf|{kodtxr@ zrER4;?}bnK<0U>`pIlHlX+7`gx6m|K1LLlej%TB>2VnsK`1Rs< zJ7^Gbx;A*KUwo>+_unhkgX>>oZTeNy;^j$K%A2r|ar5KL%ivS`>0O#b;PI zj2~eP9bxfK0r7>CE-fq)mE_ZDjn2~(A5oDM1_ulVUms2k_?0qW>LTuaabIJIFtdCx z&P#gX5Nx>t-&uai7~~&XAY`uFuFDwGgP_8udXP!HZflFZ%-ySsxPy?c>sD}_s{p&5pcLJlhJ|PB|xu6J4dRoN4?kkXH1**6Hb~E$+{Q9`nBED6s zEm@ku7y^G54+JuXtlyCkS=(aJBK4J4zq~ux!6%idUkyfEb=H21`~KRj?J>;69!4xM z8*Xrb3d$V?TQxQz7HLNAbE)bpi2nMUnYUK8L>mcfI^}utiHq+Y!ys5P$!qbR{T6P0 zb6JB<#}Dy~HU!%n+p}5;*(VnL^24T?zJ2P%{v3w31jzhS6s<#g=;zm)XbH|k8|mt( zBq-bJGopIXgj2IYejh3!>#5|_SN+oE(UZ*#+ekw<8%dBbnvRh#@lK{xA>FFt;{8cK zeqA8&Q<zr?C`hIjYvoFd43cmn&@~`5XzsD zJl0Jt2KZ!ej3@G~1{n3L-r8opw8%AVk)Bc;rE8DgM?~t~9{H?v_}trDVFkAS`yF0^ zW=Wc7PVF6DS=wvxr;C8aS_(w)v}>+LG|luA1slNx^0Z(zKheRnI+s3$WniDQFG$^^ z03OV1y3G5c*qt;nwo)Vj6n;08`@CmUrcZL{2lzeTi;8h6-Ilhd&+I*z2r*Vc7#AUR z@%nq?Br4bZjj7`h6lUHa(i9eYq4nKEOZZEh8%RLKqjw{QNY5>tdvom*Z~2o2Kmz5C zU0GCi-A)*iF)9@Q{`8i+l*~@P2}2@t$a(F+#+ZyjnFo9ND)M#=W~E`KMpcT+c>2fm z3LuSiI(RlntC++}8j4E}^!w@omSbDwqHJXlHS;&8XZwR1laGn=f>PLcb3Oq%(qjjH#4fIoF^7#s|tv2 z7BUImY1}hrOobPB0-VMP@tvGQ8y%U2Zwv$QZC_5tz#1+e>5=067h8EfQdJCMAN@wq z#k_tehXtF+nOI>`Y>n8A*e4`7*MYqpd5crzwPMHYOWr=q_d>FC%w52u7@*D<2Nie zdIagM)ELMR4@td!P=R`GaS{G}K-4}So}uF4N#g0U5@B_KFvnaV5$Yo*x>%Kah~sCh zYsPrwI=YV3C!?KltsTfu+{kC?^=BbpaLbcG;BDze5i`jV5~ByG2GRwO8E<5-2zY14RLRII!85 zlJG}pJj>2_zYxov5EXy?n%|Ax3oGI@vN_75G5Naggd!7(Vz#T^bL+Or&|+|X6e&T1 z0?;SA71(!fJzeZ%2KwS1B@X&X`^>Y?dl>NrJh35lr_G^0^v8BnEF;PxbSE7#U=SWf zOBrex5o+ialt?p~=LfN_0bKaqhZIa~L?jCREf&m>xu{|XTLYsAzpOKZ^(acd2cO(W*gm5 z$SWgCzVi9=a*;1$AAn6(hSD1d-`P)bV{A6^1y`*JS?*Yxr}ZzRn9t}qk+)lhsiK9n z=qIqecbVr!9z}4hAD-Lfd$K0n-F%AaxB5_?;8tow^mQ!FB0SyYAw4@;k>kR1*em6P z`RBP!3l0Z;tl^;-^+Gmu)ydlq^dYUHXcRh2T?1OFRcw00n^W8IxP-^2{yo0#H+pp>u?yhG6Q%KD=dZf+TiPk^KaLTN?c0x{vZ@7nT?YH@boRlge}oI? zl}8|SiO?6UdI1ZghS7;6bpzwUp4a)6ADQH3uabLVrI|nAqMn93%rU9IzG3H#>=3pZ z%3!xkDScscy5$6G@o>okgTWOF^yPCjN&d_6-q=}mxlolrivK8VA6~`(H*4ISJ&&Td zvW{u{y}rw;42QQ$l74ysep|f)!{1lWSnyn+&{L(RBM~@|y zFAZ@22S)+r{MxTxLX^w>ayH}tnKFYc#%YlrtQ-FZ8@BU4*ZG{v3!Rx@p`%4(Q-b;V8{UyW&Q${~Jzk(d-OiC}%SsPlUE# zkAb^Qw-06z2kDG#>U7VK1Mg_$xq2*vUQ#wQK7H#I{91Ky*~wVVs^6KDjE$;PmHm#*{oc~#F~yyGD>gXXH4iju?4=1O1bD0my*GwL5ecCPOIkSx{<5!b z%m7pv?(clwYS+8bw~r2z&_P78?vr}3GI)gqy;cC>hBeZ~*u|fR@&-llZEv|RyDl-2 zy_c&W=pR1pKEH=&eR$g12}dIe7T)%!(b&_57aVOFg(gGI{D)!34qu2)DhihEW(PR~HqQz!5AF*{@5Q-K{ z`4fyT8Z^OMs}MtG80Tu{bI}_!&fYkZnNRG)&0OT@m1WJ!KF_3dEM!5E0P=%zX= z$`6ohTo6Tn+UaomFP&_qFKGD20$vx8X2TLDmj9cQ^zYiHKVit3C^1EF9dCXJiU!PH zt!V9l?SBFvSV=yvbPBLyc>>{PuPQ*?tRP#3*GG@?eg{t4AU;K8(YG?Txk0S4aEgQ$ zHhb)qRw{M;A87A|P}LsGj9Wa6dXk2a->M6Lxm>@nOuTC_pb|aa^EIw?eS*ihy_?ze znFqGuy;95;pJPKUuaG#|h7z}{PLEeBUGhtdF?7{7XaEihTf(@6wu#cY1K{T-@x&vuh8F{BP&@@ZswjqF-;JCUjF>DH}O^iujn> zFVt$Qq1-m_xObqcBpBlQac(;eu z1(JId-#@qEtKB-TH3t^&j1bv^rHqj`Nq*}XaX#ZvP45Iy;~navo3X# zcy~q=RgB(MRS%XZ@)n=^hth|lA5e+N%@S(4oybmL7^`?0V6P<@6yhC`tZHns;#hS5 zK4fOJ4Onb<=|>va{T;k&@e$tQb9gvEl03eJAD?gv)cn=0zbRP{j~0F>lwBR4eJ`v< zefv#>bPHkd#%Z9Ei3Lnoy&WB-XfTw8x}ELenE$DU_X$ z`i10>Bxh@vz?JdD#RD3&9xG2#5$N8mWyb?*cx6=ufR9cVn@p2RdW1--tL-|BgVH;% zmbY`w7jdCs6Ie*bZrQiw8G4&+-jlXs*&idhJL`Eeh$fd&x^eG>8Yi6b``pkOKMB;+ zfUNj~R4GAO?sVIBG=*EHwa(Q_@1o*M)7u!fTn?S;zS@f8? zf`KeQzwB6;6sy{n_xy(j*>w$ERA+1T`m^s_Rgvu@OjSqTzAB*vEFz%8$F8J_+)-r5A2Dj2{$eBb~{i5 z%g(y{<@KjyB%U(rA56Dn`mcOBA&U4t5fj2f{H zlTVXM1<_;k9Yav8orA>kk4`pw+p>09-;9a(2tCqCuIzoCQcmGh52hh4fgP=^e>V7K zPG_R33s_-nbkav8JuU=si^Y_ecbk>@E&v=ihx59LOrr)Zx29A69O{P#16fLxF9o#d~B_yTbz(TZH z%kD21_zp9J8GGN?$|*<)X^2YY96q*mCso~&&q7BBQ~Qap4L}yKJv=BC9Xn*ZEC=Xk zShL(rK6L(JJ(_fNwjRSfa3v7Hl3_)+mZf4o}RMm>m1^z*rsi@8lw0` zE5R629wbp))0+p>6)uk#ad^G+gYIsKhbqB0aKJh=n|U2!9tMXFN{i|K#i>k9Tmd$e)=l^)q%tyLK=^iDvSM~}&%ddx(6dCW9T~cs*$r}_Ed@x@D`Kmr8CYUUs za^h+A>B;B>E}yLR*mknCa2*_L`;o~DYydASGlhe_PD$(YQVsvwv&?$;OkIfVdo}c_ zp%NEgH<3t6tZs0g*!vA{zk)IZUEdACY)6Fz@GYqZP^I>_R+rH&_Q(HeZF>g0)pW<< zp=z4(0ue3i(b^!Gww2*}nOOO5KM+X}2W>{Jk>&_HHaFQeES`b40v=gLSuLOGnpuGaaRie|c0? z#%WWIn~1~3HQ5%Wusi0bso3qs(!W5$>c`AVQQ@*k%7~`5fM?L-+8U6G3BV=v|R?(;?ig&c1De1O0+ zCsG#ssp^Gm(`T(J-|PZWjfRCc!$7A~;0(wk#+^E~tnO%6vU*`j$Xi>_s|E!=EzO7C z{CP8PwVz7wcm@0ePXhG-uQAb^<{J^0n7Y24861M_&S#eszCWlQeBAIOcow)Y1Y&UkGA<_)6I_;@zolaw zyXjl|%u3{Iz+m1JP)|!BQLMC|8JF zT@^OXoB{}+uiS~t7u5}K-t_bPheraxqjfY> zT{hfLhy`f-U^XI8MajnGA?OgcB%4iS1|SXB(VCfr}}QBIdbmbDo|0^ zN1B0$0X9npE3J-mDza~DLItu4HnLUpv;+Z!d+k|_C%E@|D zlyPp%XID$3lGpt-;i^-+v{zUT2#scguNwTYYLW;*UQW zzk9$YypDMx`+c&i88QQQfs*87^9elo{woX2Ct_J5_9BtlsF$-jP_eJq%?}AGbeIr; z>@!;J0nP$_?jqz*gewIf*WE@2!T63-}*bUm27~({v3%gS)$1aDsb);BLX)A-J;;+}$le zaCdiicXxNUic_}0`MVhKOa&r2rENhiI#D=01@6yD_HFlI}9T;zsg zqEp{^p{qgjqQA9<-P*M0_micZ;N>;$YYonD+SFxZ;7?I;L`q&O%2n&yHgw<}) zmN=qj@i%a_&O|iu$nLt};)r`(jKBNoHsjf1V(C}1>iNUA8rXe3&|H!@BQ?GHDOC{_ z4Z~i5HyTvHhwPkg(fPLCY;Q7Uv=5w^C*}HP=a)@Ty9%_gdNp0vEg0o7ESqso&)b7* zgXtho=xk2>n??=TF(rh~&GqF{TQaceBXP>JidUN)>YXYHb8hBN}Ngc%c{@*NCrY<^&T@|2}z4C&&um`roPO56) z!Zi8a+cYhj&E1iC+Y;vGYPTUocrXRMu0wFfHp~%j2G145_%YSLwjQmT-AM40}t$elw3gWI4_GgA~^*d)MqIXMM;R!}^w$ zUOUQU=w@wQ(x!ul-8uJuS@lBZI+Y*M&wE{GLuDfz6%3P$4b{B!hUqiH6Md=lp5h0Q zVYfyh97WPM#mc_EX$%-P_!ySnmYL=IX=?aAm$~KCo!?!)q%K#o zyQEfbnS7s=Ps>3@gh!3|TJ-x^Lsoow}6QBbfo=QU4T zaVmvbyyxSCg9%Qk)qxmSfJR2$VEZbux@AqSGHL}u%=5p6J?pifHuC&4Uwq=b6&siVVcipGF$(mdatwGfGJ*L zP0@bH@Ohg11nO{UC?OtjMJ^ju$!i&quj4yf(!!k6=KZ(CmiBrVps=$rHRtQG9=7Gaa$@_oBDoi(qQ6tSkJ?oZH8KO7@x5j=sn))Gx z8$3t4Y8ox!lh|n)|1bKsT`kYrIn(YW`qk18uu5FLsnN()CsH==FLB1ZL%$d$?WT7! z;wK`xbF!Ap@472+rDGlsj-L-*iz%H(FMM8R>?QA-X%=*)`aPnC;M>S}(_s3jk#zax zJHuSckOzWnJ;(o&7}xwcg$g<*C273RyoEGvH{~+M7eDoT7C=; zRb#IVR(-U8hhEmng3p9J(S+@}STGe8!gXT%r`@ zkIHOnkQ;Tu&Tn6xisA|NY20aNJx~ntLTr@2Kc8uf;;*M4w|v3!io_=FwQNAaG~-c} zaP_#m8as}p3rR0q7dH&;=Z-%-`8;Q`Ph|cVL_!~umDw`saH*C^jH;V08p4 zM2RZn|0A4KYajXjzX7k171K>cW6dbqYczHsrl{PuG~$wTnVyW?yJKw=3C-Fuo-5~Z zqbu7$$#-Ix{1EtW;A{0(Y9MWdXZpjNY81IX0ZblO5gXl>my7dsoDZ(;8y5NKZ!SU3 z&n4|=%wKT^`ggXTi}HJQoPHpc!y5Z0i)aLQ+dQgFJcR{eMsL2wH+0V=Dw!!yZA$tS zI?+*Fk{!GE`vG0Q^HR|af<(o!#yz;s-7&@-B%V+Wo?Ehe@9DNd{4N0gSNDJJ&=F*DcPT1F92x|HKZ&Cm0 zqdD(AfKEt-bFL8soHE9r%kO=ghDN6O=_9kyDK;97<;ta{{Mo^8I`$-3*%Agl%m#Q1 z%Yv}NVpn8EW^w%8{w z#UAVcHPyo{yDqL@$-}vk@L8r9^qoPQj*G_1$PefGyCEiCb<@#Po#_0R{nraH7K?IXO7e9 zdQ`QvduXd3v?7ug#|$5vWZJo!|F{~+bs6V)>Ix^>`;Ydm&(tP_nC7$a$;*vXNp``| z$)Eg32Zdpn{P#YsF@^S1ExcB)e|2)JhlP8DUerD)&T<)w%h}2bf+TRg3VGydR{fc_ z3?uC=U5v2khI_zH&qcE748gUS25wUXm$En&AS0V8%(gR6X0_+|_oU_|sB{r_Zk$ji zo|!f1zxL)sp!>aoZ->_88k*z=ugMms74-pn#`klY*~hC{3*}K1KR|cg4{d%+MAAf! z(%u_{8`Iy2)q=NJZN!I7Z=Aut>hLh5Ho;pOJA0~~DrXyQVoVvq_%;5_druW;c8(V* z9JX_M@%Gg1q;&!-{#H!Rt$s+9m`4!x*27Pyg@;%*4X1_wbN1?zFE%?(-ML1ubz=_L zHxTS!_j9-vWmER{qC$Qw9mV~xE*#9+vFA$Jh!umxTTOo)9+itTx|i+C6oR9} zkWo{?QpDo^@M?+S6VC4kQ`vm=uAeVQ#c-pV1kD)<9lyLjlnEGtmwiZB�`g`n@81 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�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 %8xLhnvU9?N&l+<3#qR{YfuCQD&oCW^ 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

    bTo_-SN`N)Vp79tw(UVP(+eFnR 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

    `jCTlPsn|) zTJ>gPKtKtp1DT2<${nCo!%KjN$ex8xq`1ZkQ70H*3k9At19N>w1ovCyLkJ4^kDSjb z&BG>*{Hlu=Mt@kGePUy%vJn1)OC;=B6RR3t7OxlfdrFn4%*tk<04U&X(-$(<2}qCA|}BM1?@LL{_KWC?n)RG1nI_k-VE6D!LZX@AUGhQaa?khGG=!ya+WpsDiu zEkwk!TQq@2lU~D@AxRj#;+rUKc5l(%3T6w4z!4Ca&E_PqFQw=z35KBISolvk<%z6H zn;dw93Ilt|l5A!+m|-LKtndfBbnlgEMFy){O#1aZ>s!8uJ&$KuyiV4a^V)?1D@_g2 zG<#}bf`98!LwOAv6NWe?J2(fuUOYZoNk}{_kQougT({zMB2Yy3u?=BikpS*qg?TsFk%|@PW zKwY}C3I|J=kcs;g;V7oRZyXF@Jis6`T420LOn+w)U%SzCmalyiN*J(|gxEOcDxtY2 zDiLx&qzcNSJmoP6H_(#z(6=9T zI*HKJ&73k^brV&Fa1>>7V&ID%f{Gm!M5h(pD{3rI@p`aD$j?E?v!Uc3n0(DyW&K+0Wfsg@b{-PcTueqmmA zaawV*rS{DuKzUgGb~>$ux2j2_v#j3iDE@m`K^v~!3;`lH+{Z%u2>l?WGX9}Y7C{_<_H3AqFJ@PenZznrVew@ z!W59!&b9Fn@fJ>5$GsZjVD_}Ko(5m+;=%T1tc%yl`f6T52`;rp<(-!)O_JK#qXaTu z>{MM9c$Y|Euq0IyHz;3_dyR^TCVxt5u6h9Ys@MNYqpHR#{%;|HcOOf`z5bVk*4!_) zdm*Dv%SWc7Tiw=aZY}Vo0fYS)jar1s3e;fk-^D}3){92Yk9`?sM=T4L`_a<&!ox=n zN7VV5>vz>-GcPNEShj^t`qB+I37g`Nwm+@t|6)CPDbKj{-)p(*5;6IxYfC~Ru9gT4VU;2{ zTI5ldbv2`8p8hP|3p%JS#BT~OOYpjUO4%EQ_tdx(lkdq~koJ1Y)?cIdyg5(A>zaqmqedcYoPeBTD8L6j8l4 zpgdthOZKPIif4bJiuR@R9t-r8_e<(+I)jWC%>zZdGpG1wK7~XkXKokja_VpP@udpU zx>WLAhXvY`?8kLmV0Fp@bb*t(cHw31B!n^=S@wRDW{Z4Tl-^(bZav3u?^{ zm0nGAGwz*M;t}Lteigt@Y4S z+-A0amFA+wD+0HK2#5B$Du;piYO^vf3e z(;OG{Pb_ItZ~77a6ml@=MfR1Bx~H zfK;#`pTSC&W8j9lTgK97(>M2j#cqLuTwYvFe)|jrB;pa?TXkVs=kA2zc|x^$Rv%NQIo zX=B{!TaKEp<_ATUG02)G z1@mwu>SMvBcHn7IiFGZ_*<@$!K3nK!hUHqkdg7f;FtW!-JnasXkO$W>T%1i9g@$kl znt!F%Ui@|-ux6CmbxP#&@is|cS~K!z)+l(_0SP6N)Ke&c zo>WvAoY4>U$^}hZ{c$fh+$D0zmZv1Xd2O`51B04L~=h&Ie#|@r{Jj;nsDv|vKky+u33^nas4 zP8Kn^xr{5$kb-O4-zAJf`((7{Vh+S(%i}po`qFi=IAPsV_Z=oWZF?e|$aQLQ=KM~q z4kbgCE6HJiofmH}VWb3TEvk5x3W4P7sNOLuia8}w)h~M-IVWNbKqK3E`i{v_zG=d! zwAa;J;3-i(QDwyz?$LyS=-<>M?4#B%;%d%;*&n@d}M7e~Fa)%^x zMETryjWfUWCaSzq$q^5&EZGJzotGnQ0!I;^Um331W1Zh^h3e2WqDt@5N`DB@lE+^L z87Zf6AL~K@eKShh5tE`Vz6`w8Smmue{KIf;e{jDcSrmQE;1SBbCVAYAge^Cckb&8n z1TAn|o!YtT_4sG8nrkdmG}-M4`seo0l#7OLiMtqOL91M4qiIMQF^-q^3^VBKWPLfW zJwbImo&)v_)Cm8j9nqAVEyIu0mTk5Cy)%}lx%W*F`0!io%VT?lv0~Fh zixQ9sChf+ZAFhw;xVSTFczS%dgzKpD6Qz{9x3J4<$n_bb-u_UWEp6&gK0BzGC@c1yiN-*uewUuxD^s!y?L!sGkJl$BIp&4V%M>Re$$z&(=@@A4{8U z$(bzML!QQWh5AR9pyPdW7oU5Cr(53AHJFV$f=R><4iDjzX7B)dC;ni2%|Fk@H z1Dz{oCt+*L?cgnuq<>MD^Y{oQ`*I#rD@ciVG_?||qK4Z=Uo~bqs#ko&hm7#zcaP}$ zSRM77GCWwsyw1Jkv~ER0dyhy`_p5epS99CTDn!>Th1A}n?``R}TQ|ttj&*Gea_d!3 zF%}K#N)c>s%l`2;PhUXqIpLdfZ6VxD_?v_VG4TUrs7J zh_LJgcz|RqE3Pol#0@#X={8EyR91rojG;VCE4n>Kcqz7UtO1`X+D2X9`7jV+7}T%^ zJLHi#rs-fqH#fM?QXwM~Cq?^nRt?w5=;9=?(-rIKOMhxErui5OxjX$cR|0+4=&=%2@W1=5CPb( z$M26re2Z0uy5TuTz{O0gYq2f&@x06?V(cC~Y~Q9?E?up}wqU`Z>cA(fOg_T+hi8IK zqyVJz#sc=xB{MkJ*1_xc=%70Dw?r&-4%7H)h<`=r?0JLTNCe;!hvk0l{nX) z$7iE{o~$o5VA5&TaPj!vu%QxNnCdRrP=AMBZ;8K@cUv|LOvlEe2-5{KJW~5PwR70TE0ezcgYzd)M<%(dtz}(P%M(omBv!4}Y!Q z!|vdq#d3)J#((?lb&#~;Yr?S#P@lwzMNGu$d|kK z+VU_Td(s4U zIw!Yd$Jc{wP*(8FXCikR@t+L!n&)m*9^J9`wwBY$*#-G<3p zxNNKC?M+A#6lv8@ENB>^=knI#nBim9JIn5PYTD^p6!Q+2O6K=ma?$kMw>>g6lc*X| zr<>~w7QwNc$E+6?aGb}}4{shzQDZ(??9OM4QBM3?tHFu)_u6{;ju{N%qKzSLe9ga1 z(me{O44f-0i86d><_@*CGk<|^%-n4$v-_}b`?+KmBU}Bpyvf_JpnlBtxSnvaQAu8h z&){{czSMtN&stt+lFgjh1Qrsa$Bx`|d{1Nb1~_fnlnyHP)fok|#_sG+E2ergtaisjwHdk8K@wqHNiS`5N8!{MiF5`&VS%ju0(TJr{4|^ zhf~mr*kmJSg?M0$)QDM5u2EUtE5%$_BeLMDX$MbPNHqt}BKTUi5yE3BV2dFPI@r+A zjXFO)YczDXr67~mh{sjCd?sy??cSM1@lHfIoM+P{FNZ4{@JPh>WxBqc*|rjg053mx z^J0y6^#tjyH)UqKv409>bx0x3`?9dqa@0AI=V4{h)RHD@G9RTyL_R5^;C|Ye$fy3r zUi5c^nLbjPWYq)qC%AQ&oOm5EXLWy6?kUVt$^9oWtaBs{r{i)sgk9G#>oumu$$+D$ z)L7@h0>~a%N%czUAm;B2J~W#DcQ8$bO@RobXrUedAoun zE2L6z@pRLNqYfHX+FphV4=_7iZSR_CMDHbnA<33xkf>ypG7@I*m!O9Psf*d;PA1VE zDAZxnlytnSL`{K`w986>D$z67rQ3)DSLGcg-0~xtCrWcbJ_yB8speNQEPj8awii8d zK|sW;H@Ss{3Uc!!pmn-Z^a-e%#%2Fr2V-{IB7==pXj~(EAwQlafT{F5u3ug|`*w4C z@M6O=vy+8vP#w?{Whl358cFC#*P@b89`BgEtuzmKW8>Z^OxilWkC2(Ri zik4BY>h6HNmU4g*ZTLsal2Cs|7oL#&lT7MPng>1OQE`xE8w^}V@=`_4G{I9K3XS@5 z^g&^U@^iO$_i<1s)-xR{N3>R*@Tw(sbrxyo#?jr)m9-p(NQO6ct3t;Pi7)^q%GP7v zADxeopm~?Z0y&d}BI>QGBH=r`Q`+5L_eB*~qWx8O`!@o4Sb5h}lv{s!^)~R{G6h2! zh@WZuF2wnDl`Wwa9gxsoHjy$RdKr^Q`sVIvGA5(}7K}wCb-G0YXTwG31l)3?={oiH z*#zIRHK7mDF`q6>qouQv8D)?u3rV`1GH%PU_F-W`miWTPUWKS<0mYMhp(`XEg}O@N z3jvhoe%dhL2~wcvDC2*+;fP5>e{7+uq)Jh?#R;u&Y}QtTvDkO1(Yg%mC4G~$i(fCk zyTZB3JyKjM6Rc5A;xbWN8~w31K4R2*2SBJSjc^fQhbz5COZL)N$^o+7NSUaG?1N57 z#SI~fwk}EmGCMZ5qSgYtJH(m9+}IHvsj{AEQ>D(LvBd<6g-U;=skIC?dUHl#&>kfj z)t9G5bgt`RG8a|7D$W5U5o{biWtLpq?sgE=YHQx`ZPHX@^$L}>_Uk3!YO;skiQQks z!5sctrf*!P7O8CWJRN1B#w;G}Kq9E(4l~dJlzHv&!ZM`}6)+HcW_aqa9Vs$LPIdyG zPEcj6JFw=JFy4R3q+n{VYZ>z~wzQ3-z#0@c&5fZc*{?X0z(+g0KM9~DS91>6z+Owx z8{B}!t+Z=l2vHo46&GBlldV&KdPxsDlgk05*zA`4LTK+y?_JtZ+5Z!tOl%gz9^5Vp zc-J-DHgIj41%;X2eqhyJLdzv_pi7Wxz@ci$X@^T=JXn-{g11l;VaIHA+8|(VmkStTrpb z)kI`eS+h>vrRkcmk|eTms^HgJgtMR^ND7c?Vml}uNy}>OuGWMSbpj+PA=(MI#_$a1 zzj`%Y5+Hv8>8<6wY_@-T)wchp=<6b&r)&k0R9X78m>gV2#tGAQ-!T4Os5XDX;vLmhzv%w~t_wrB($fP_i#j){ zf(f%Xk(YmqJ!imcB&3%c7~q$K@j-#rOgpIPyL`M8eirv1plM`rW;Xs-L_QJw zK}4lKBTQN-b@3j6W7RDgVj6(@-6o9~4MYDo7rz}CA*#??BB}tkP%U#zY`779z_r}2 zM4ke6Q@Tw!7MlOa-Bu!?zcc#y94;rftl5LeArJbd>U>as9KUrrOD)16uno$zt#do z?4l~=mv*Zz8BGG*E?}ai!x$sdMnWZxEg~{1<;b!^s#KE7iJhNH-e^{0*hfI(HkUwF7Q1FXK~jb+sy8 zm8K@b%b>AXu^UtlK##7llb{9D?oq@_I0;~4MnlhM<1SGiVhm`1LU667UgS5{uJ$~M z)>peXf-j53xbG5Y{ot}?RPoa3IH!LRSqNW|f5L{E+OuKRrio0uA4$uvjlQJQ=Q8UB z1XRiNT0%%1#9MOPz{b%YB*{oxTiSwi&(w{I`KaLf$^K~0v^>8^jvFYqgXp80R>5gN z$=Qc6599PRUnvGQ3n+Ujmc<^sz?fIFq#d~|;^cI4q~ zeSFc)ygG2V1*G1u8e;9hmzmqHE zK@9oe{MFdH3~ZSy=UtRIx-dFPG?JMTNvuYyF;r%j7ysaJk_WA4TXkBr3lJ5m>~%47 z`Vm=WM4n}8-P@7r$#V-xvvI;ybXZL#MVDS>RLV>GA?(5@F@W7Ty(@Vi85S6r7bJ#1 zZ{pcph1kUWwY3#F!(2#8#!c^eZzr%D!&q*BDO{qKQ2s0D|L;gc(r|$$vmq&qqG;OX zX{Myx=W^&4+_njI2G-rDpb`-#Jvh*{EL4Yr3Nfppn3Jd5?Ml3-{;A>Ks|)XZ^U5Mv@F znQmiagNt&YEzotAu}^NEQVJB`W1!U&fQ*N-KYO)yVf^b!+Ymoo{hJXAyU5i)RoOU$qKY_%Vnv1{dN zJ-f784z9d=EvMWke z$z;gTIGtY`k|rTb8vF|?t+~w;dEOD@aT;l(BV1`ZLc$;CQa=v2f*JWixQ?ID9l4B{ zMVm+!%Z|8Y1;nFlu0?B|yV@JWnYNF=IAeUBN>!+mhf6SGc`y0rziBg-s(-Z$#l2eN zX-a@5tz!cjE;1uM62s=kmx$Rfi;uj{pADzGOqcW18t=MUY6sSMPYa{YUcRhH_x_qK( zAm$a$CJPJjvIOMKHh)G=h5ns3)OGS7G8y~vGkFp~`LR(V;-bQ9Zrvk!T0X`v=f{Fv za`eRf9yS*(>x8#PnlJbHNgT+no%r&x@X1cuXDWXKwTA7#c<;}*P#hHM7yPG>3@vg|7@U^P(_B%-*jaIM zwj~3|w`_Du7S5yA>*t{INOnz+!3#z_VZ94N_a-U#5vqkO57{gZPK?{T6h$>NKicUC zMTNaS4zN+R57gzYfly`sIWJK6t7HzIa#)~1C+J+p(1yq&^{K@p^uLfWbyX}|+TF75 zjA5RFIbe6Ibq6;Um5z=#wP8aM4s7@{-=P=4D#b-(&^yJ7qoy#Om?G17pRo(aDonEv zl4o^5;<#8Nl15_ou_&rajDC+#K|hH>o3hSDN3g`^d8{pdQAzB zr=w(lvr1iv{jvsm_A=7)JrXFl%a+ku_z{>=mwz8!;lzco6n3~|8`=RAdJvzCf0_um zrav6m;y!X#`{qXdd+f0CU4c}&Ng_B5`fRj!=(io8)31=Dg~C9B)@Z>aHvy|N>G@B7 zt1fX;Gf;`t3d!=JgSU#Xwx(Lsz?v@htzkW<_+<&}cnfbuv|D_g@XS^mF&p1NP#fe~ zIC+^hRWh6^jnq90$7@S^&e=+(p6DGw^~6!)u}csYu8=}IuMqoX)WLza_wMd+t>{^G{z3s z>%~I5Q9CwYANe}J>HJ@3hKHAh0JW2lm_=$6T8Uj;@v*ow3T!|x6AsvRUxl{tVn0t zQq8e_lMZ8Do&Hz_4i%hjMZ|9|=6s*?W7dourH5l}>KgQ;Wz&f$9kIQ2n;ZPWY2)e= zEuo5*3LW|pEG&{nhq@0(WTh5(zRu>la%Yv(`cD&dwJmWn??-U|5;AO>P@=uB)ED(t zY~&ubIhzC`4&Hq1{bXndOaw#VT^?9K@o;@*n) zavoxGrZO%IsJy7y4x4yNk%D%W)(5@8eseVXpJ;yxGyA6Fpf+-!*7Rlo?W5PtJd*Uq zxoafdCT6MC6BbbM+WO^Af#Xi1Y z^QiN(1&`zL@~v=A5`F6-thj39glp!-5Z_^XN$ohf2C)R| z%*aiO>7us^k=mII9xy1kdkuxBF~5WJUQMA_!RPq5!1f@>7&hzxeyVX1f?FcG2~x$F zBii9Z&4d<{M)LeWQoAWZVU{kdWidzl0}BZ9SGM%=7Ib8PZ+~dW)2roL#hF{PE5c)7 z)eGL$rozo2s@(|0*Mj`u`8ff*6lF=xvn0Ui^x(ES_-jBr+z~vXJzIu1qphv(B283p zKG|Vs*#OdySh9EzxK~-c;+J(($-@kQe_i!f2U%RGDUG9f)x@x15et4o{Cx$rnG8GS zlzL}k2lebc7Z8K6#yghgL_5_CU&~IFv2YDK*!Bl3BU$$fDS$2km5bRF-yvXYHEFLT zDZ;UI%V|1$EAh{)`1-7F*5}|HYYE_foU$d!b~zR{WokhMj8?wPZY5D&zYV^zvu(1u z!mdTr*_}!hz=B!DzS@7*C};3f4AP!BUIc8rMwm_7wSh*12nT31;50F&1~bwz3aW|U zLGd(pE>o!VJFWODytn?@O(rsaOwud2Ke-bld#h3ff7O)s&2{sieqz5(pd-w$u!G=g zyx<7RXh%u~Fk>3pO+K%#wOz-NN?{EkSk*Kr`Z^_E`)6$Va{G7i?IhwsW7QkYNBItH zGd8xI)XObUT#$(h^v|Q&4XGFwu9c2Xr6#-@qT-$)dIly;P|fAidBadig-&b*`y7psJ> z;1yeyj)?Yj-h+eBa(7Jp()MN+4|(%!86nTP7OsW7 zaZdp-)FzpjfrWD4i}y5kmcP2WPzCcf!E9OAEXQqi{)yw1rxH=SzzkK6a*N0?F$DXT zlY_c0I=39C5>6H7s{w&SS(fd&VEvZZ@zzh|ZEH!sXM1Ok+h?S@AhS6bcXEM&%J(JxCEw9VXi`x6cH0VGD3q}jAjza{a~oP zolPxmZNXb^meI6qT{Q?4;Kxa@jf1dGHBC*-k{wz+6xL&&?zi3b2b#mRI>>CBuGE3N zVe||yt39Dk8}qTP^)R`E^DQ+*FQuP5_j4cz{Uu7UGwqQy+vcHGp((!e~TQ))m5R-pJ z{U?K*`ZjVbEVZ}xv)io37WZsvv7LkytwVP1ZrFx(6{EpDilV6E7Gg5|uk4msew91S z?7o1om}`;@%yUry-c8wl&bLtilOqb{cK7e^dAZ#EbELZ+@JrYBcc#J1;^ZelkOg)U z7NSld>^>50Tir|9V(l3Ey%SkC{-^=%7s%1O)d9XIA(N&T;`)xm2k7B!wegk_htqYI zGmWo&s*P68%hTcF>T6(vNIcel-PMTLkQ1#31&Ebfs^2L8OiOu@xfDB|N_nZpIkRSk zLKcROVr( zxX1eNC=vbP68Y0HBjY3991+Qrq|zvUdbxHDp^sGEhLER2q|xo>Ms<4ZX{aTei(p~E zAJb7J*1XalcvXuK*;omjZkjX%1j(?MB+FLOU!aCQ0L238r`V9bnb!6BKdtdjb9Zfcr3sh(@?RK zp5wcA+PlDL@zbtW65+o6y__?2ol>`Ek$GGQDm1hutzat7U*ZxdyAMd4FaU!DK}vn5 z!#;H2EZ|%N=hB&72qC*Uv7(m^Nyx)hc0s^ZiH~K0&P}~B-loniy>oKl`B;x?G4&4m zZUfcVO$iw|(j7c(N(yf;(uS~@yh~I+m}I<76ynq!`m|@pm;C2{GIN#4Qq?8%KQuqf zbWh1W{c}m7Bf(h;s7g5G z7Ti9DnBraSemUa*ahC%RA7;A0>uz_d;-J>~V#@ z=0+!cWekRzz2N;J2+`#mPu-k^UYC^mw$)JBWz`_IT1bcJVDj)i7lwN-GwQ}_y%qVZ z9rAniL=m9mN&1&}w&J|~^O)7&4n{w><|~EOAF;Hl(=!;9sO_I~WdSO2LFt}PHqC65 zD^F%?WLU~zcg$m9V;&P~&S?qou<;b(Z`u|d&g<%A?#Y_2FqU@rj)+s^vCAlKHw(xG z;L^g_LzWH5#ZZ>_ZSiB2qgvO%k&1GynIGQ<_5(|P^l`1@&7lb6Oxe4-0QQHK7v>Pz znLqhP8e4C~p9kn4l#@iH!f#r?-6qjN#=BmIt8}o7ZR0V&w_fj?4jVL~qxk_x(T*-==ExLl{VP5S#|SkO3~~_sxAK986x*-y&zEZO{_egFo0P>e^8) zsVdh)3TVcIY_^r`WGT*KdK3)QHw)p2e>nrh}Tc%LPGM62!DdmG{~)0p=o6DJVG^+Ul$Jgo??Op1>M-(Z zSGm+AD)wewPy?_ zoZ^C_iZ;0>XIc#uHDF}9Zn0j?p`#=JZDid%7djH#4NuL4?)8bh4!Ffs7gF!NcN2N+ITb(OHP&H+#m=dq>S(#kh#?AzxX_)BIh?b2Q#02wk`Q=KC4V+x!(O3 zWAW%S35ZU8jG4{Bbz36r`Ik>gLWqoYZhD&@D1{S2*ggA8+e_7{> z{n7ETlT7J}h)cVNq|_JixY3Oq)YY?*Vr{xXLU-&6F(HQ?8S2fysp8JD$k!3zoWT!j z=9}Aaz3qPe@nIOqBuGO&nHu!l$!tP~t3@(F!m5zD!)W2USrNf)+YvC*fX-TcEozyk z!OL+eq#?boS5^s*n;L$tQ@m2MLZs#`O5c*K4*%Ag!GPpL#;@~MLsxpVo1KIkkaLRapIz5YvwC*gJZ?u2+wBXWOW8KpXs8?eYvF?p4a3_f-m`fA#7YEN9#fyW7)*E(@%;NXWc*AtgWGD5?!#lz|g zF(fdjvC@)QA$KTJ;bZc!sxX~s`a(D3-eq!K-E6;vULfrNUkjgLpzB*yO8jbnl;kEu zfel?>#Y}16)^{t!`PVj<(oA=O4Ijt;!7Y*HrY#xn$bVaZcAj`X4;jlXb7>=|x>a{v zOnnIMU379|TP4wTSp^~ukzGRlEb^4^LQ5~yFv=WeWj0OPKpGdRn6)3suofJZP#^=l ziSJSw$~)&>(5S2_UsyS2sd@oCQ=2#7f1$NQ1;w7jwyiC}cvSLjHXJX#Fm2e%Pj@S+ z^y>+CrW3?BQxQ{T(fi;j!256N{k3^qJLP5p(@FG>++`R}z?+Yn)EHa`g2iBdIqM`k zGPPWG@0V-3v!c1xRYux{*`#nYhxex;(c2E^=p>Wi_t6fpI@$j1@^w`z_yyeWb=uvh zK2xZ&;VO`h>vPmc)D?jmHvJSl)qA#fIhk>HtAbZ@TYnEfFc816`Hodtc<#00`rYXz zvDWp=kQJmo#|o*RVOf{RzBe}c%eLSPscY`WJ+KAjxlDa$bG_4G!|ZASaRqnY;tDW( z(k%Tama6hf#J54t!bVFhbpj&Ds(3P~4WhBFjOsVI=01PDFTUWV$zEXE(IO@(H?+UC zCO1ZcZI(@bO<{4OW@e`#B;1*F5$$zy$bIXNe?Ptke(&U_)b?^OlajXC+m&yXh3Ck2 zJ})*ZEu}i{a>_7?(^OwRZUxqRwd9zr|Nl(xh&oV;W0_~RzPw%(T_xpzroz7t>>=88@(P$H- z%b?n(gc5D7cGW52aLx0~$Y=Z5D=CS7P>lt)@*M@&k{~Cu)gbV{V}?ue!=6%ri1&YGk~zdA|^vr zAxvVsqguRG9RrSP>Q5`3X%(E5;FAv*d&fSffNK=?qeeb{K=0)@6=Zz$H~Vl#TOwEJ zzdzAWn5FAcj9dT|s%T0#7SHXUR+LG_zL#KmtnA#>@<&c}3kW88l~BvN2I=QVMUHaX zbv@E5rJ`NAdEN2*lV*0E}R&(1Zj*o(7#j2OTh!Y|aX|h%S zLXy`ESaxNuMIh!U#k|s&wnIPpIn6(@|3S539wMNsGPDQOGM|E_D2m$zb{c!d{glrE zK81iaDSMU!MTIzV6mwR2JLDx-1ak%`gDIU< zxvst=lip_;Uw1y=w~I-n(NDpicS>DTOVFEtWJJ&7<1FOoti$v|sNg8%+trQ_APaa^ z1Gme{pTIQw_t(+M&G*Osf!;r!!s+Gn-zEA;^i4q@;MAc&avenw>f;maG2E~D9$WIiA zP#{tEISgGQ|C;}k6w%WL7{UjNdu#FLlT z;e-i=_9U0Ez>{z(!TyNQOi^vLaemT@9M&?VWc{mgqmd+3Bli1zG;U8jC2i%SW?nh~KGA*RE z6?<=PceNr<;1)_cz4THH1CUmR!GR!eA(`BOoLsQ~1jo~RdfunLvtA~f#3`>m4qn^e z``STg>`PXE@7!f$UD4&oK(WZ+t?ISrX;COrMf_X@O}{rweCu0xYLzL$gY#+D5Nska zF=;hXT%?14vTf;gFVJUewxKg_pj4UEL6TvTsjZX_C~uJt96}PlLkbJ&WhR^ z)_VI#DW7B3nL#3UmPVWwf6G^hA7PXFug9>BZs}4poEj0$r}d4R!h2BQu+W8{{ppF4 z^d@w4*=kNR%(RG>_A{<2lBswc$tHD0$ClTnkA+2` z&S4qs-OUa@3T>XhVDCX|#F#wo5JbQlbG4oA=Wh~VKL^rjn(cDM1^^#4xvqMZE>`U> zg0Y2zaXtJo;Y-2zI~MU_UMSeRKV6OzX%zdC;CD}TCc_xg;htD*ykR+el{+Z>t-6&A z@gJ#XDd0Xr9Y#G|W@2z~UBczb|FqB<^KTzUr9uOho^5voT?@D`HrsC=ywBvr-Q3Op za^dChxX0Oi4g~yGcL6~o`|n=9*Y6HK8fRFts-b)yXfOR<6nO3_*OHLEh94sIT}w8{ z>Do}>DZ|NZ5@Y_VO4!g)lHjS}w4EC{jrgf=rcGO+!cf20sVNHlItQU%J-CX6G>1mo zb?pT=7|*#tAHabW1ZT9MR&~E1MX*cI^zrJ1JGPP0}bB=2`G}*P*}sc!9AJ(w5ntAUbi^ ztkH^IPi3w0)nN^rHyi4|cwevQL+r_F{rXD8SnLfgrQRe-x$8$62upEX>wm*#+usu^ zX+*gynY9$zy?`AMds!x|RPU9QyIO#FmHhS}Cn!Ry*~G0Dr+5cXPcF}XuryEhmB3_V z+2>_+#gbkOE5GVE<=}8ht173NCYWT(zK-PJq0nJV#(~Ze*--UgF#_cMjF6te^`+AW zsE+k`72K$yCj4PkyRH8u7)8ywz=^#dMqU?|BIn*fX#n1*NMRR^dETgM&8W6pqO03? zIl&zwUa@2~pJ<1pg)hdDr!CIU|4g8iq~o&SQN-px^xM{py8f%O=-f~$#{*o_F2Y*S z5n}LGhe)*Dl*H01iIv%&2*MO1jw0UKv7f4juue0~3V-Z9OJDgYLjM@^yuyZ_4$a}W z!K{{>=>jYyU5jOZvVbAD<2{!cJ#HeK6nb=MIduRR7Rc~<46)8^KX(Tx)@!o#-Amw3 ziv+WV^Zuwiyi7UotauNUVECm-R7Z@FiHCEn~aE zj2=`=YP|9rH6gb5SLUGT&wVh>Wg$#%A1<~eqcy++xpnJjFo`_+?|5&v9b|P$H4jrB z4en~eq|rFn6$WX%o!DLc^EY)hdh!1INei2o!mTnj|NaJqvwP`wd{B_}`aSJ|(7>}G z)AJi~ofxU32UojVgkdvti?X8U@BpnWbdqT&u(Ir28a;@3_PnrmDuLCsOX$Zx2Pb;w zYso+ZWOgPsTL^27Rx-_IwW_ci4`TM;*hCl@QL;xa@Lf#ZDf^p|A6aO)_juq86d7F# z<$|4AB`B)#T;l{Wcq%jZNmbvIW4HF95JfW$_yf2S$ZWVT8p?R*5TjU6eMJYD4ft*Q z=)}d(5a%h#MfQvc2M}O*Q4ZM8_1b4=pS}M=?Sv20gU>siuO90+zWi6Yz$UZq_(c*y zWyStm6^CtLWkG@+rL=GLj!Eu|qh9yU_t8(Vv_g`59txqw6%K;n%~WVgb^#S#>*uKq z@3AF1%=Q;pE(9C?q%j*9axO()J08lQ$22brJea&ufb6m}e>IToFw8_^PNBex{2mxx z7z&tu{|EVr9vQ5rL~|@0#K;q(Z4t=D@{D}FuSCXxR{T3-I!@+TQlBEVihBwi!r*Ma zHoTtwTaGRTwQ&Y*gdGZ>-$GXeRa}{Cxxluw-j5Gs#_X;oB-iBT%v2o|t&U;l!kES} z7$N7*Bh}7WP;!rzsbtM%$?^mdp8@5uO(+TM&3yrouy_l^AVj@Ag&d;VzE6Ii$j{VT zEJIMbmnox~K&iSJ;jh1-)zZn%3}`Dv$vwaS;(^5GVMkQ0giwE(syBz8YRA|6!~4^= z>{$Fx4_#Q7q;3X6lPv1J<&j^g^OUZr^F7ACM{u|F7!~L7z2>&kWDmn z9RXtElKwXiHezFCk2=GEk?8aUKRF@$ZV-`dT1fAxYB7vr1bau5E*PK4xNFSeD(`h; ztd-|s+>yRJ7Nl1wCh<|hOX~;Hww_>T+Q%m5@S3$*e6hqUJzVSbXbt??(<(LkrBlqI7-l(Q<{}q?U^vLw zC1Q($p>Z^%X_)v&wg9y|ZwsU%hdJh5>K>GNYrcJYFJuV$Tw62>dh7Jg>GRj>$Czlq z*Tmx}47fa6O@K36`!v6cFh*BhkMHj$pFzHaXyZ=wFj<4rA#KfKt0fc!)7@c$n^9(XYb2xTfs1}H%) z?l3aS|BuPL%3ez_9(5?uqo_VHJtjq?`imw6(~(A%rsjt#!yyfs5E3APnB)8L&R5A< zB_oXbQ!FsQlJ=nrg|O%2t8-LP@cYayb;tMV@$t2C=X>wDR!?WU>+9U@-^k=cg+JzC z`AAL==>B^6{u?V;D~hY9|VD?qgFdz#J9;6xnAJwV>$Dmj(1=u@P0W9d_7#v zUi}wp=lhJK2Vio#y-+6DfYKr08Z~xU`Y<|9=zSG$3S|%gx-PuQ2KeE1R*#`{7 zKFp6A{%BX^;JcL<>TYypi}%_eH8Xyyr@G$4KP~KsP<#>2Oa_le64?xw@f|+`Q9ZLe zUnxSKpXlHZA8(GaYxJY|chZIns};j zWi&A9Q5~&h1R@51;$Zc@ez5bkWXE5!tNQ-gVLLU{6^(iW@YYsuVv3+7Vwv&lyxZK+ ziI24D{((2?9x5Et9^TqdkHtQ*+G*|CFEESxkKy?C?|#Bv(Vfs{@twsPA8^n%bW}qD zWv%lc133wy<*4(k&!+uyDqf2V6H68TT7{hg2A9jjcA1++Hw%GvGE^nTcM zR&UnzLIqu#1d_{sk%=lCcw9v>fy|{rjU(Zhq#(%;U;E{S~=)k7|2F!Rojg z$eTd{m=0I)M)a#+@<#c++W^AAfyN=DVP2V>Q*61rD6>d4rj4_3UOU-v-sH3!Pv-2q zD7xdkVY;Q#HgyDx*q?`mgm)lac(pADEqo1&p3K&x)m+y6qCCe<5Yf)^m zc#fEpRiokX+v^T%ZDLhBX}ibjqr^k*Z}_3$%us;@ix)#fQ%PytallkSm1A$4#F%hZ zH_Cw{EnK7H({LA2@sKd_gwIHHWdN!a86s~A zn0M9*g>lD_`y;k2MLS{Fe>k-$_ak_mU(nrX3+RF9D~Q2E?RSdx#u1e!tV^xBGrW;! zEDD_tcW77W&uRa#3jm&6iXp`eDSlOYA0?9h8pRO9j)&14>+f*XGt8?HG0xB9kFflh z@fa`XBC4DstQ>M@+ONYQ2s}@fI45)Ywi|3ajH!}(djz>#}+mqn*w0zhY8gfoTlb!wBHZS_UHtvg<)M(yeve7a3EnqH&1UB|0%pt}gsyy<2 zx@|`z1j*L`m1kB5m+ndXq&U`n=a0leR*%JzuFs_xJd~&T$S%q0&l*9kDV&R-M3pg? zvU(1YNU!*pQI&A!X%3P9L~iG_u4V#9N{b7fJU2PS;{MdU^d|RjCJNR-uCa9I#3a?Cv4`Mx5K>}|$`%M_q2R0WXMDh-VHulB>+ z1#wRwTOv1Rs>${3gy)R(4+IR%Rm--+Z;9P`*@eSX&%2f`VMU^ZK6*GqM-UWLG9yQ^ zoBv}ip}NsB?JacX4O}_E^xnaK#RP`PTW8L?W7AsvyMXM67?ai1Id2xLyNE7N>a{&m zgk+_hHbSuBcwTr}Z@eFdMiaYj(V$_WJ{<)!?dE*0QzBjcj-b~l9cbZruueV_*yqNh zI-D7y@uPyjL=YJ<14nHJk?*C%BO&MGQbIbMg_4;6eY%F6jR}j#5Q?dlg{(;r72F>7 z$92h~{3*>R99|q@HwbEPsb$`W%(SFK)3u2h=?r6o(&)}S zl&_lJy~%?ETuguD&)q7pa4zw8}#@9Uj37 zDz>CjT`k8$)HtP48}OK>iuQ-C3}U?C>&tLZY5Gl#=!2ZvB-KvVu0=LkKP_|~OS4d} zZ;mTPFG^3y3B_SMY3OK-B)tg>iHGL)e9b0~+K4k_OkY%?qVVH+6h5y$6pCd<#GQot zJO&UAsfcY?mK`s=@?jOGF_^un^Lxdm3!RXJ*FR&B_+-xOif%|S&; z=$kVJe=rlQ6JFoNGNcs9Hi$txCFzZt5#=G~w4&5VWM!4FsqvV|4V#H9f@K+DAc~Lo zrNBf;03KF5nU*ajv3y(|@@P0DJYCP@{0bPNYTP>Xrw#Uxjk+@j!yd6{cr7-c^uzh! z!V!@u#$622oMyfUF%Inr%ipfezh$cs7OEUT4ot#?(@`|Pq8XwzoW!fcTxvKejtsI{ zTV5a^&*fDeFB-uRWGx(fk2)W4>37Rw3V5EzP=`dr>EyMxGqVRCjCc$OdkatNuL519 z|23Spp?kCMP*XCE7-n^${GqUp21k~%*?ttLlzlR_Mk(1&Gtli(4)SFkQtIst?#|^& z<)IXh9@~B0u=~2Ts~ucqqQiVlWg^n<{n&q<#@g|IfV}=fk-ECViq)^hClUies5eP5 zO3!7f*E~vVeNnhcLsMRJ^n^Oce+Qzs95Ge-?*G+1KL4r@MGkKkDlD13&!GmdM5Aq$ zQd(OLoa+#&P|;nANH~a!kQ7|aS%>~TbFT$QKua-9wm->eaVkw;HofxPf2-^>+p_C+ z=i81`a#n|9qNoD6{^l=xjFnv7Zr>F^HmhqVeG=;n)hAb&TCJoddUe3DfB|=hcra`Q z^MuWFX?Gvd&*x}A$V-@@NC>IF_!mZMnlc??uMMMqNBo?1C*2llWz0%O*8WS5cC`*2 zDAcClJ{3|)kZW@#jR2VKjpFC`XwYJO-#*&zRS)AvF4x<>@tL*3zwNy6l;)VO2GwyE z?mCc+8Ejtvo@80DV3@*g7zNCS$Z~2v>oq>$BJtMIemal1FU93XWUE*hkU%BI#^AjW z!F?Bo(2`DAS#H?>s^fsX@l+trySC;BRgTC%XBr_REUwtiftke!M^%!UgjJzYq+g5_Y|lXi~%#&Xr~PHe+~E+ z>9mPQ$k6f7j2`FeL_!G#(bp9#EyA{j+ef zt3LPXz-A|ITi4Py0)W3~ywgzEBLjbJM?r{yf(^N=5B!UAa}}fTEZWv<1eiDBruaHT zWmShS(gE13^@E?xqnqhj@h_A{P)pqv@53{jNIvNA;u}v```_;dbge`>;H97 zAv^GQk^yCYn0=^It!l`48y*R7es7?Q0Le<3({ZIgOM6S3;NYha&uw7L@IMWBzeEG` zci*bjRf!>X;4%t=(qba z9Y=f2Sb3mAeYySj{PEzvL7>t3;>H!PP=kF9?SvsH*0RV-T?48J{C-y&RH}qlf!Sgi zoPMxZFt7h-+uk6N0I^GgwYY9ePLf z<9+6BntC4I{~B>{4W#zZ8TNY|X(`aMGC{gfgp_Z=h1pTM*Xq{1!1VEb44RPgrYYyp zFns~|_{nDHGkLaOB2ZE%5Yh18H;k+K$GAv&M%3|l*gQ6cRHQNKxM(D>;~tMJ|I%p(pkZ~Dh}0}E}{c4v3P`8jY)1xhve6EZMJ-AyW#SIwpqtW z?C4EB^;5H>_+?0*Bj-86e%9oK|7he)eJ;S1X9Q0PM-v6wEiWBc7S-Phe$F)tCxND6 zHS?FHk&dPN@5>2vYOAz}u>aKm86)+e#9_>#l{Flc9Q)}|lwi-57lx%h&_7rM;tY^k zLmig;r8NGC+rh%1gmL7AtLUc@;-;wE3Kr+K4;I-!c6s{gTVc<{2)am$(oPRRrDp-c z^7T+d;BtA;5U5D1P5Tl>hwQkpIN>LQ(PkCD>lu|Cph!Ur^)6Q6oD5S$^ydcQFubYM zYhIj4xZqas@bvnsSk@C=+;J;oY5qg0jN65-qCsr4Ef{p5vLNsrW4}*81&cdk{&E|3iQ$&;H}7md+_HRs_sCB zVngH1{G~e9@eFoW{coLSs|dCU`$C8nP>$tLiF?$B#$3)pc6lz`@z=$GIOi6dV{TXq zn?zbig5*tDo0Jfwln3H?$XuI}1`bi6qz+9O2QFC6OuDx7#gvg1jaCMrqx{E|GRZfs zO4Qq_gnAG+UoA! zPH*(03pQSxSUa$0f9rY}Dy0MpK)Qx2L(5HsNs0ToDXX30DCk79AuNdl{ctG=b6%sD zV`A|*vDkdY%14%KsYW{Ws8EPuL5+}ovEMwya1Az)8|)RB>pVe0e7C}B$K zau`wc8HMTWlBw0X_^aZxxr`uAR}w{J?OSjY>Qi6i5}PE4O{d&n#i)UW_AkWN7?t73 z_%q=Y&}&?Cd#CcB!U&k*kx7U2Vw1^iF|X)|ic#1zlk~B~qvl6xQq$1>8Poz>X*iMI zW)kL7(ftx!`6xJXUDOsPhSnmh8n5&y-PqQ8L|@DPyt0@80+#RYkBW^GX6nnmd0FP% zWSG|BHwKa@-f6k6B@#dxPr*sztdDookZ>|iB+e0Kl&C6O9-}N+iV`tdK#hw5-Y1IS ztnX8MVblaCJS-ocdtx zU+MPz2dxdkL`Wqw=1_S|7_FH{nmEb>+7u&=2QYT$lcJE|PpV6O}}_+XB6C}|*WHHFM9 zC8=%$yw}y4_^{c(D#|W$g8KWA3BfRo_N#XzMqEUaL_njk<=I@ZA8$MQm`yPf^v=+p zm_;Tbm1G+1-$g*EvqPMgbJ6Q!xM5r(^Qw#S!s-`120ekPiUTM3z5WaL43(pLS z0A+fc5yVBD3I?$p?f?@|*9NrD8b^c<*fIfX#Nm(6%b(l`zf%*-d|&{O5YS&m?jvNj z6t3A&w~5j-BzK^_f6r_K$IDAc7W0ZvC)?`ZN`6mZ3r zRtl`5=&^wVAqm%W?s)YW<{(jrDpSQDEEKI-!yGa&cdEP}+>5W#sai&SnT|S?&vKBa zp=*Q7B=LVTdTPLFDb#)K<$TEVu}|fOWIi+lHO_-OE8JNnd4(9zaA)Yp#+bT&waZ-1?Wl}HyRUV9Kse>gUu zH&BmNq<{(zZ3V#?!x$4D3*Nx2!+;79}w-gX?HOhwOJn131L9X%;%4u zBVLLR!bCJDk(xW`BOzvc8{8}|ZfhHJM&D!3{KA(*hrXvH5Q%D=v}tHTZrQZqTn|O> zaDt=2(b=1x($nwTQKoA>A3WMmRY6e%dk%4WwRj~lehiv>hv;4Wv>xg1uMldNx$>9a z1aSh3G@#Vp-o$BWjC1i8?=OIToc6tU81jWF>CBLX#E|=QT7Jxa@3S>*#q)69|7N=@ z&rDx0ua*B+nm4`Q_eQ*n+iN&D%{w3OO4_?mxw_w9NO~jvJ%5nJQts?WT0YUK&;jBqb6NAxOH#(7x^zZ;UqIa@oYAEZA0@1dM>V zy<``oOAyata_m4CFJeW1Ns$NYVxaZH+{Vb05m)z~r$ zbry>urCB9*-K)K%>s7|YQAP};{X+8DDkbJJoYam=ACPytwmG#`gFS9sne%HYuorjA z1w%f5g0YIuTE|irL)!N%26EqRxCyP?;*?SC-y0CL$*9d6nbxG{@gj#O5h6I~!{c=s zOTI~VYf)%#&Tj35nVeD=+epnLFh_@W!61cO|JxK3dS#l636Fam4QTaX9@Jog{{wSC zjK5WNIFun1PkHNqe3bPN@j4_}RE{i5V%-MQhq8&r3jt`j8YCh@?aRVr>=sn0qLfI} z-K;vCg^sJl>~-^NScWRuHA(;GqpDJU!97R7se&MYCUgV&SJy*V8&B8;smmG*^I`px zX5^|F3GD*;W*cXp|4=Xg9o5SZdnWHYR$;Vd;OygG<;%=}ng({^eBhcNPgBNc{NFEQ zzq!iVY0byDSpfw>QeooRFQ9x2hhZGkH#|q$Ar@Wei#4pK-5a4 z7k%iw=ei)c4XI{D;J|D%qeU8fC^5t&ae77}R@P238vHXfob#}CjmnmK&d3XuByAWU zrb`DZNzlxHyj|ij!*qS}d11Q{p*;X(sgjf2!m-c9Z=c{pp|xV=O_EQ<0;468dFs9{ zI2&h`q!j+hm{|yg?@B5(Sw_@Ug$iYDQF;UZTO~T23b<2-3@=I3n+)e^oO7JIbF2g?lHc9jU`NN`SsDPqA7`^6Z3|wZR5Rz zlt!z`TJCS)K<+7HErPNE_3Y=3Ak!2XiT>SDas{>nPx= zEkFi;8%`shYL)V=H;QtYV;MvEZ^zAZ+z{+8i0T)j)a7$)?HF1Dbs~qD$9txF+OrP`=mDFI~z0?jsR|1_LqP%*;Iw zg7a`Qd4MwTJQ)041_6~Lmy#Zd<$VVe*38iZ7XkCPtUZvgUQ|63Ep*~)V6?acX_tt9 zX@zRZ5j0}H>H`B|Edq~fxnNI#7n1}rHC;9`xlqlF_sWBn%=e*fi2_f>69r;z!f6~1 zj*b^tC6JH_yg?@@n%LjA~)5v9JwUMGqNF>gXDBT1b#hcl7*tgR|4r(%5Pv!+vO z^-znSmoVoDH+= z&`__poQMG-yFcUP`Gsk6Cg=|2q_a#t!5s4Gr}ci4kq@yfy)$Ct;-@%elYGyAG}U)# zSF-42^(+xJNm>r8AGbMSpiB#(;CNlF;$jA@R<$%x;pPR5VHckNhm%lSH!)b^=$PV| zgk@mO)pva;y$0<4R0_4ZaY#5~tXJ|9MU}$rAZ>B3j80CKF(=q@!)Gj13D-N9Mkojw za@atOIQyf=T3s?vsi4+ym5b7U%n4mdB?U%l!HJ_9Gj<1KF-AE6k#EJ|#^YE%)EjuR zb-kW_wK4$$lIO=PFkqv~4~`3n9<ciCp2nQKM+aG!qC&5+(1n)t1tL@o;ejd~!qsUlP z(rMwSRd5pXi8*a;Fo6(C4O(h4V5{|dlJUavA`eO!Ldw$;Tgfxj!OCmwvg(hl&5ik@ z+DP(2k_v|Wp)yNq6N_o(s}6I(XDC?twLn(KOn%fg(`ZiI*2GowcY4QExIo0h#`g4Q zvX*+BX^x)$@m0#wv+`B?kAV9GqT1*UqI)|G0 zSUtI4_+qJ-h&NuuJieha7rRQl%=fT{jB}Qd`K_cqCO?Of10lx9g-&mJaZCXu*d-f_ zzZdbv`GE1PYSSEAcu1+;H47D2O`)dT@+#gQ8g*SWtOLzUFmGyqP^bb%rmD=V3OIgk zFZ?v?yxUdH4Y_w|F`Q0ya0ROt^r^0H+u!lOZntrsGn;&P- zSd;Z{dI6@}Odg_tOHHc8f_|&X93~y8$ZSYDIqi~$me)>lt0fF_yH}R^=I5s*m>Hul zQwae0#>b&E7K~Gut}=A$9jqf;6vT(RmJBI9AY5v4kmQKT2Y@zO-QjM~ldL~aJ z>9J*HMV9Q@bv4?Dt!Np1*;09|qhN{Pf{iX7j?|w9^7TJ|bedo@T3WaPsqYX?v3AZA zj-)<=5cweybtR8`qomLjp`=pfw3YM;Rz(sK+I~Pn@~*A=JtQPQr~qKu09w_mE?K-# z(z=}@1iM1<0iM{)!HD3*rE5ZAS3@gm+is_7q*}uyU7-@-R*JDQiuN5%EmmpADkATy;{J*5ltJhQgS@NW_LktBF}B$Ad?l%|>|pKB!@EUn9awkji;F8G=2 zBgEsKP5f))#rL^5tEOpd_P?;Sf}*jkf*crvi}fOZ6l*oZ{VtmYugfI?{Tequ`Q6u< zMfLD$aGr52*UAyhKcq|j`RuO>nv8mFq z{_*j>hc@(_bU9i-T#awydZKiYZHQk%jVaoIeHm`w!njn;VO##z@MH;+L4N(a$gDw8 zYLC#3V(383hk?pK(^y$ZnJN^njP=)64^dEmf>VTN|4|sU7z?U(Hk$S>QLAaq!@uLcT}KDAB?h<4zvaT0h899Jw)29bU(c z`p(lu7=9Q&iZ%B&$$x$4?~p>`Zik3Kt?4v$x@*X!Gw)8kVbg(szVo3CV zaPC>|kQM&NN@$q4N&gPdFPHN^msTu##QZov?F5>*+0=LVjy`mg9L8Y)e7wp z@ODkmbTbWqzWTO74OhCUP${aFy z?=Z8j>9HPrX5zbHHxr3GB`!idG~br}FiN_jRI5tzkmNXZUkSywnsZqU4PA1lGje1? z6DHU1p|#tZ(j*@;+?eV!ZYk z&xv!y%8?t6OtOdp0Xj%NFY!1ZNQ759=mTPIpOz?z(^omDRp}vG=>~&v!2y&93YRDJ zsce$u8;4^@p2y$J!C?Sklo`@o=*du?`*Gp?xc~Yv;q-xALh8Ke5MypEN**Lm`3(>b zC|)^>4;=ZB!3#Bi81@!&G9}_>jY2wM_ACLYm_5H{q48ccbbn9{wf>YZDA1j9X z8d_UHEgC@6xB?&B<-Fpxh9S~Hz1VQ{t9pj&h!sO%d~~rv#~|#3HP?)#tj4&2Gh#u! zwiGeyM5)EQI*8sJ!H6}jV;&!w{Lj7(=q;NzTwAUvn)Q%>XX38iVs0-JKCk0?T;hc; zmC^@0vEeRIFMOfDUIae~a5zVD+xw;n?W(+?<;G90$bOzer*njUNDiR=`+AbAtS}y| z0K;4~cr&1=O|P)%E+Duz1UV9}Cn!Hmw?x2k&1MBei9}cO?5Mvs2{3+`y!~S+!;mx< zjtm@OyoX_bk_lX{*stg`>vg(B$;-4%F+Zr*R9Be7JG+UWTn@!r&!!zuvj38+GO{P% z&>zVP63yrk0BprKE;3gaw3eRy3F=(Ap2nnAvrsb2@t19!WSc|cEN~)YB@5=LA zG_@kJz98L#p`2>3-roX&LK--BdtOar1DK`j2F^uFQ+fqerNv}P;{8MdEa#zs3~Rhb zwp~yI79EtqkWnQW0)-~% zvBb^;Rs|{26Gk|gKlP!kDn-%kZ8c(V;=HH6W4QTt#E?dHnoE@!vFHdw=YrF21{rlw zQePi2MzhtP&0wm*RAc4bZ1VwtWy}o_%g>&F+%1rU(@5jA%(}&rAia^mO4j$Oyo8S* zX^%Se51+3uX%J%nDLtr;^X~FoVBAB-weH+0O*QoPlDe`JY$Zi)RH?U^m1td1##gLn zWI2|uDfQvRwq(shCLr&`z})C{OQxu1p6@W5RvXLlq%$DNWNWghA~i>a(=k;MS0{*n z!d+(Q;YTw`-~F0UEBV>6!l0ZpTkm8oXR%E6%zDP8Up0pS-9b<^yQRJRv95R4ij`sb zNDv*bX)_0V!<>9vga`Qj6izxW@D-rFtcxoDS>^%*buD-7A+G8^P@hwlTi3{NYSQw~{eWXo0uYMN>`~W$PRm+tfVfR=dr1j7@b`v&Mza;cw8m-}ABJN^ z>!Re4XKpQ{50jnog|%}?Wy!Q?1}rEqo8{ODqdATtWS9bJS8>*_I+2534~z!H!BJ7v z8li5L>ajIx3tj*bG}aT&9rnvuabyd@LvBEL)D~J!TQ$vQ;?;!t72Qng4fq0oOBwFE ze0Wqgf94l=$2$|=OM6-qMz_qwelBPNavpM&=)TE73RW&LW%7i84)_Jchp2z-^c3cQ z&<^~V>@lBrh+%xr5r5U#rj9?&=1w{@p~6$i*%pOAO!pg3+-!Mxi2mx9@vBbW)z%Pn zNSYEFb>MdT>{r?QN2bybVSYk?4xHWZetxyit*)Ka`u2vGI!EdT<4)@Uvgzcub=j!~ zo7H}&&=*~NhQt8f+gj~nBiCwcvu>>m%vT%Oa-ypSg!I<38xBmIQ`>%SF}+!z9<+z7 ze?o!wp$^BPttvMu7TsKQgG)6I?07#PI6>0>Nz9Wh%fbhPbdxJvP+9GNTr6@0EK;dL z+O<$0kjqjE4HHi#)HBSNN<$5QCtVYc2-T}!d(e&m^tVajP==OzBm1vVZ9z5(1+$YW zdd){@qHa|V#?~AmmSp`Lt)0>RPYm~aB{$@BQ^2RXs6N5!6dDJfF6Rd$?dabj|RFv zN?zu@&omA-5q_fF%w)?Ds%N&rHA(KO?IK8!scdDPtYPj}j#FB3Y&iG1`*YrMHViU*B z^sOP^_59SBs3WF-gCGzCPDhPL0-zi(5EfmS`Xf&~T_yA-F(ENa7Lhmcha__6=ybZb zEHTqwQkam+jEM|D!fDDRfPFBijnLVsG8bqg-i@KEb67hV^B4I}~dMS=FAC z_Hodk7`cAaU<_k08(-rVXESn;M%ZNr?hM_u-*^ESuX|+LwjEOoDi^vZtJnJc(d{O> zj+wDn|Frl8R1e#B9+vzu_6GsSnP8Rh)XN_uv8tPp*JUQ%Io+l5fO*=(H7;VLt!4LR z6FAIP)?(RzK51nAbF~3WDH-D*?+fSm(4bHqT;UuE^Dq+@({qEJkceLQGEH~bArI%rs(Ek(+VY7mEFT=P$HucoMv}<0-L?HbWP{mhMHr)hBFq5p7%uK< z4P3e7|Aj3hBF-$s>RGggt{OBQAirS&8=5*xQ(H!V7?{+ZX)-xj_64K7(a3k$>1v(h zlGS(8ys|gJvhn_-*^?C<%g*r0Ian=g2IU}IlOqc?`%h-u6ODxxHDu<-^W*OW%8F#a z_~s5NOG}_Iof*)!Y-iY2=rgsK9AW@5Qe$>ypgG!+P4W)8v?lGc(($xe>>$fvFB?gG zq*w@l=dZR!vuUMvo}uO0smO;|Yv|1e;gphGI51%uhh zEir(cpnZ^u_^d~HqDYufav6GjqA5F8Hm*3fB_^jK)^hik6(V8Z2{%ug!tyq(u#1w3 z%y56nxrBiuxnjEF)FdA6A3;?a?+FQ{h~ZV+9Igk|DUO?ldrOC{Wb7B$d%h-rBSj+D zAzFF2qosvbZ^PdN{%u9}lidS8e9LDhGb~WINwJe3aeL;5tS{67Q8Rf*mP;CDx+<7Iv4u1!s{82!>1>y^xvVCPhm=pV78n->|6X z?3p>XTf{K>u}$(!U^Vv;%6`oDRm#vDCaSy{?0-fc%&ovyYM|2)++H-`d<9`)i?^oQ36t(0hfn`D9KgF&V^}Pb77JNWAScH5YU; zIv`(JbZ2&yk+)o^;m>}*v#p1xVarH6&QG^T>g-=oEets6gMX7eSMBz>47knQfvp|6 z>47zSr+pm(9OT!w2LoedeMHNq9&vQ;!$MnkNCOZepwO(0QqgMy5JtvRenf5z(WE1m zmDgF>_kH9>Jnhk!X}oNI)H9`gkm`07b`-8n|EUV-*}iVu2*a8)X%`fp9f}GqmP^LE z*!l7#x^T;;X8n-8%X)^9eZ_>+udmBQfk3B^*37!fliWR9YLL~Rj6owRGaXSot8}^ zf5m3_!$v_+U)>i&^IzxAyjbd&lKUbFetq{f=AOuzrX#1=7JVXXMo`;Sp&b5kOXyR} zJpD zv5+J?XXWlTy!xjb7BXVQiRUJ(&~nQo!59<=AYx{=J8oBhu|BPtpwP(zrjkTw3XnFp zddc&#ZQIOhQu-xZgRgc)b(Qt9@sTB>>jvj^nL?yQ^U(Be`uC$TvM%rtZ-L`tgG@Mb zbP6~}4s$rvu~_K~Mm2I3Bd!;>wKMG$tCk*GwlinjFc!3g-~?a<6fUaQ9?3q^mgW>{{d{=I)DBv1H%gB6oPXpFuW7 z_mBZ@yd|mBOrnU=*;&&RFz!XZ&yk(Pjx4)wIPmV6cuE&_=dH5rUt^85$nFwIwCQ}` z#xB(9?JTBo--sc)3&6$(JT~>ncGlIlHd4tY(&UJLUM-JjKc|`ih<%?dzN6>j0 zAAUN2TQ+4E;bK_VG$T~Rofdm#117gzESAd?zYr63yN~be)MfHG+3B(XEF`i(kxrPT z()d`~K8vk}2PbZ9hl1o7n@QkM3V9PvmCduo(@JpM$dy&jRL8{v?T`iaF$<$fV7N$CQK)v7$$xmthTm zfPEvj^cv&}p{IND6pT0?8O50$?_2U~&)lyx7v!|MZDoIvDbVG1DBEm0*%~I265<=5>bt}46!gBBR6_eo7Oa)5`dv$ zQ~?4z|Coufe$H)Z<^ifQvqj;VoAU`^!e60)a@+k?+Kuc)=jlaf(SD*2Fq4pz>rhu@i)Ii;RfH9gB)(}>DjTJbnZC>>Q65gdZkLB9AGz0BdnBUqX-LSNu0Da@@@S-+Ay#%P z(0@p%DjSMVUViFH6YEz6sy~pAVKrTLUtrOHr0 z)C~|oqkQnxl0%cUO)@Q@-7T$WZ*Z|gHu9unXKBAkOMI9Rq+v=#4nPKzM25Slb$jvm z4o^GQjriqwZg{(w(tz<3IxWh9 ziKWd(8$)I(5`CVKS#7?5bL6HlGy9amexLMpUD>-jWNE@pqg4;AR5u;ZEzaNtB(q)5 zgaRNui0tn=Q*8Dx81!HIijL!yMI9sAWV;(>CV4kgPvZqkJYJ}*vj36;yB|N3lT5a3 zU5@8MRTawn(ytF{Ag+6M#Jpw>K)g(*$Rp|w?Q46^RQ1UbKg_a!)vUu5mNPQsHxq5+ zDhd%x%l#+FTb1u|cRy(~Lf?`|825uUs9$rGr0w^l?eCZZZOTdC%52mvRx&kN=Lu^^^GGmV-9dKezPbl{++=^&r%$wtyQ3J$-4wEDRg+ z8`_fjZ;4cU?7Q55OdA7v9adfC7Rf{{Ms|(RXID4=xmk0HJBeop7vqvWHE0utmJEj_ zJD||3R9eN(uBrCMPsb9wQPQ0vUrbLsdQnRkqo2VKdVvP-|&!sOMkB) zXw>yysrD~?m=FAElQ}SpMs6i#XZK-k#Z+THicbXHC@i)v$6^*jJ~u!3$Y5e_+jd`u zX7Qf8Z_6`(!Rg^%HMT6B(N-v6IlmJeI5e z(w)X%NeD>?7J6%px8J|P`)%uUB)_+vB{-dh(ze82)54-a} ztk?c)$`wCU?>Tno(QyuR9!jbOiFw^ZPpsX4DHnHON7Dmy?d@!4_iF?(q-ocAKd$}Z zqtx7yhmiI@H=nj>ugJRW>+X*sA>oS>%%Bl6cIeX}D5`ERbUj_+|-K1E1BnIoI)LJ)a7 zg@13%(0_1be}u}E-R6eT!J@gT>`b_s$;W(T#U!TufFVy`@JWJ zsxj*P+n#)l2zWyvAdwwMC(-cUZ|}Z_&sAoj2$sEf`X1+c_vmjQ^flTC zO_1*G^^WKJ=w(Q{pU2~6Xp!CGw3o|wn?N@&KX?-^J&x~B<}bg>f>O{QSE5|k5%TF`(|sLszc{jj&j*=F$0kqcrKroxV_S_43lZyGZ(LZ}5}$wgs^rZ~?v8 zFfR$`?jY9QHrxE^ttra~TT>Q0;PO=TV|ju#p66lUv)mrQ&27&Q zbIzN3SKO|K+Q5N-Mf$LEG`sj{cVoAK#Zhpt~O3)F3*p?iJ=nZw1XM000000001bWtR^Y1R$4= z#SjpGi90uFj5{}Ii90uFb$AN^0R-p+000E&0{{T+z1xx;H5E7O&cL$K zT&x#Z%WT_v08NT&%DN=AvDE4wJ^l9Y_sBzKW)-teBqg%hs>;ehAP^3~{db2S{`2;? zzfC{8;){rL7@|NEDJfBR;cmWi(>|NdV; ze*f#cU88^hbo2A=w{PD4`s+Xb*Eiq%>tFxc{3~sKdH=U>xcrShU~Tfh{(bY~&wszv zFpM$2(bYHq^`G0DAOG=xzx(yw^yBy6zWL6+_y>R3=bvm4@96V4e!QFc`TLu1{_8(~ zzuDb#a`S&5-&~eBm0I78mN!eRzYV%r|2XaCr|)k6t{%2W1R3_KT=;)K|M;uD?mute zzW@LJ@!j_A|M~g<-M&4LBzAkl`+JOV0MQ#ArW9;+vS$&78|7ae$u)-P|mRC_n;&6@Wx+uy@_En^;= z0Cievv$d*xu7d#A$sQZ$Xiu@rV-rh&g00*z55;~M zkv6&8%Rs6*6??O656y$AO1ayAC~TOU+WIEiuV@c0?Z$dfrA@7FmNe#W!?ljmrsUs$ z5*Z;x7=3GlgFH-9vZl;+w@=aL3reM%V5H18$M&m^$;df+nbRig1;U84t>KXa%f^Ud zE2eFF3M`jmw6(b`5TxDMz=sXNUTtai>=NRXnX9~IEfpwl^OEePZC!PLqYx8g<77d! z%HZ0VY(8xrZCbYJvA)yPY~=RYe%Z5HXm-)w+Pb$TW+QKnuj#ljU-q)m-ocvKeB@DV zSutm}z9P+LW}og8-Ss z;X)_2589mLCI#&jTTwQDkpc3?Hm7VeKJ4=tOz>bT5;xieFq|;gw6V#z1#M)vNmy*c zW7AM-P91u+D5udHnunWv+h_r{wb~2e|$9{V#vFFaGkw4?pbw znpb8L7BMEc&Jk1k{=k${4A(FvTlr#2HrZlIA=G}%8*?%8hGA=eZ)@w@X317;9=3Pv zMeMz8Q)hNg2uA+KT-i!b+sN)pY<1&ABTTij^Mg%JH}Xx51!OBjJD8j5Y=l~jc{N*q z##K_=&e~k|7@LMt5-Y|?SQ``D55zkn&0`34EYA9M+&fg~-ZeP)?%|kDY1li3mY`2s zrqW=q!G>!;8|<}zLk;%o6x(gJm1?gR*(SD(ZPnk*1O905yucdEmc7m5w4al0{ivlm z8E;6&DQ=-TJ>(9FqIEFWcoX4kwo*rf7nPW`;@SU|)f;TFiuG&|9LC{oSA+yRiY-sg zm^te>!HSsN$eOM$b&AA`gp9o@jGEDx4l}8xOX{>BsS|sDJDQ%tzoQvqv0s>vAC4Ao zxN1I98@_O3SQl=~f3$^rAjIDs0x)`eWPxtr6qBh+r4KxpO1KTJI}mx&FQkVYw^yeCZzJ6L)X0m|?ge*=Fm7C57;X2besZGn*;^gBJFGW`ZiepOWR68X=gdO2|Zm49l?f zm|2O@wsW=>gjhGEWBc7?rAb;7__pC~$Ve_*%(e)Vt?>!~2JVPE6zg&cyDQMu#GkR0 z#VA>9i#L!R{KA%OGKpwl&nD8uDi1e#8T^{b`h`8!?cpZT?Ny8<3Fwf2zq7$@GWI)u z{{Fjv+jrl+fBzk;&uG6~X3zWguhnpX$?cGA=cc|*8gvAr0VyGdy_N0N3h*2e`P-4M z!9=eCg=zrCHirQ&g9-L^W~7Esmp+$b#4|o;lFk6Mu})hk#zH3}bb)XN1M^I+Z$sBx9hH2V)H!} z+H$;ocRj!VH+#|Ayr0gqMpP9~sqv+Ydo1YHGS@5BwpXAK6%p&RWc+m`_xm)1MMjsX~d zHkyNJq$$s6#$o@mRJ1`f`$V@V;{roFX+9W=%nHv;`OjHEFk?SkK8J>>BF z-7SZb6(NbOJ==1h14-ISlDZ?wo+1^BgdIido+5ouk$Npf`u!BCV0Shlko`cBaDgOk zN0OByX-APb?k7pu(WI|5Nf&5R_B3gKdz$p4W%6-pQWjGnQ8p3y<%A~XrD*a5lI(U) zT1nFOB#Ez0lFZ8(NvgF-pNJ&dIr+6o60apm8)C19KsJlB*ZL@u#63ycjwErV2txdn zDCy;ik}eP>IZ;gX)f1xhD~M8qY)mFAfoAs-rSFImohakNI{B=L62|#bIf$Kq6QUTZ zks&3OVdMKFNS)V~!^!qcf+E9UUi+*la*xb;ePmJvHnRc#QSMTte3=w!QaeoKSRd(i zC~^%!^0fqcbyyOX4W_4TV;JEHGWf#+=a?qxm?rTqF3B$k)efxnNkTZgjk=gtmOh=l zxkQwgkvC5wN-yHBrDDy07E$VdpN1$Yae0zfoSrIjj)+qC{3M+yI!_hD576Yb#Bl8! zEHF7Xo377{CZ9^|EIKYSv4dsz4!AN!aVLD73F#7lecEZ?LFT;lInEvH{Cynu43t#7Qu4rS^!X&Yj7?tqWUIX>MRMBU zmx3F}xFCd&P}<{!@TZ~39kBMqeUtjK8OWQoJ0*WSC%H}t_b0M{*Q+dQ=e*=OM9DY^ zBXRofnEa_ksUIN9Q)SMF;MyyQ;Zo?o;wAJ{k@GB?e1<|NkLZ4X?ao2@Jv6z-fE16o z$t5i(J&_!HCnQb5DSE9hC4^JAO^L{{ejX`uUe4#{)ur%W&AG;LAhyDjOz8AKop;HT zWH7NY(4!J|@;L8*l1pmepTm*D)IOqs${D^epe-2%AQI` zX2`O$-KTm)o9#oise8myrZXyO{#P=^6EgYo2|G`=xL+Asc2}-{Q#E!_>iFPlD*M$`E>JAK;A*-Hc^{_IwTtNjm98UF8Ms&1VjC}?Ev8eO zc6rW@+i~c8zNpfN*3|LV6R|ESkw+^kA83_#w2F`3cxS}o)ZK`M3Uv&PkBD{sih7t@ zbw{mhwqU-n1+Q6LPuqg=`YqUr0<)(Qox2>FYJ3ZSo)PRmh8_Mq@4Y~4; zT=m}l_^bt%PIu&0^tx_GR(u_zi9+HR;}|5mFkZx7|#qe#<9q9 zG;BMjGgNv%jQCOoV;!W6GQnss5YEu)Bay@hcHsjAdwsDOUxH^fQ>uqis|*`=xL+*Z z3sR3z#1|nJo6+5vd>iSGKm60Bq7y9t5vAglcAI6u?>h-^jw8qKAz40$Uib6+&)IH& zbC=^ku*6O|eknSXLCrQv^2ZdA*R!zaOUN=J-k`NBpW&-Z$Y&XFJ`WKY2hRA-_D2h6 zK=tzzk)If^R;8_MrQ5yfV~fc94LL7>z+Op2E@XQ%5g9kN#ji5*8W@&I{A)6jH6Ok} z8TnY)+Bz)1*RZMS0oZ!=*~SCpsvlf`Vf_z)TMKS8CL@iBrTSGye%P3UL(Rmoe+}iU zi2MMtMz_beVx%}uaq~C{`O@e9uOJ^kq;g+*en!4c6OXpQTE57;KB;(o7V~-?@mQ^& zVA8R&D!v@)_++CF>55G_E}N1b0IXky;{kq=i@1+suXP<@y_(s_bN+QM9Mc1Tga4+amQmFAj z(UQehW_>^=UUQm#QOORE;aPtOnP^(}s3sKcS1B(c6h8w8fL9cXHAl`rdl{RY%IiwS zKgCH$ZKQ2CshBn+%1!O#CKRy;k#OI!K zbVVLmuZe;yCe&+&T7{8Tl_p6xI&mcmSs|K?7D0hXg#Ix0rr?#L{Zv#BsRlw-qVgjZ z-9{%AdRn?_0@>TDbW+yf{AN1h#fsKx9!ye+dUtybWK6fu-rl;lzLJiAVQgYIU9nvd zh6n*x%%W;uCUWMWA_gR|Ke{y znNDfBC*_`!^@x)Fh?4OhO5WZ>zwKiPm@X5roh`;|8RcCP#v>A*37k_BF5(4KUJPRx zlztHshNqCQ97uRcXgd+pMr-L*v78Aydu8?Jd8qs|R&H8eq}!&@H)EAG^&wgF3{3tI zDf5-2d?f{^JW0VhmD_>!*K;>equ~MYC zkwxhVi}FdJ@(NsHt|9ONOE+XmvFh*~Vty2q{#;T%V4r-hagAuH+Es*R6H@*# zDeps;9|S~agnY)q*qPKhBV~K?s(iAItpO@YwFy*zU!~6HOv+;co-YdU{7h0_g@!I3 zjZQKd<~#}nVg>ts5c2643-T~j)%bIeOgbuf|yT1>K{w(c`QpKqt%hx%q{aD&g&$frkWD9zeE{L5cqV$I?Z7*_Od#!=()d6KA z|82KX+wWY?twJB~wDukXme2pd8wa~)@7yD`AD)aOA3k8byq{kZl;1U%&YPb9{i571vJ_*QxWkD@j>@&ux@n^_!oF$;$}~B?T0pLcwlPi6YBrC`9aZQ31G=g;JxdOs~+@CdiEHmM_j zUThF|l$~dvgzicL zUz4dI*#Mf|JP2tHMZ6>1-Ps6b&1~9I$b?E;D_cLMPSm9wHsjfF%^*%NkcGH^-UO|G z8x8YqA16L;lZbAw*KJZJp4c*e7}7E_J<#K zU(Emd@%vxjefuUXQ0AMz{nvl~ZQ9=a_>UPPef#F0?{EI&FaQ15H`5P4-rU&Di!Gw> zzJGHku4Tv}F)Y-?^O#%%5;hutAe0Rv4g8Eb`anAf%eZbzcw^0*5^T*{v!N@twu3?|mx(r6m---WEe7L%GGK-M|t>!~C+X z0vgv{15xgF{nGXwi_5>9qDHk{AF&um8*2l@fVpT?aO(DFt26hhQKJjYXj5*? zg>tiz_b!H4LFVu$AA8n+tlzHR&TAY0b{(C~gu0p3&Dvzr4au7rH|2)rEhaTj)B2#b zy?41j_EfF44N;QPwAn0ggYfp+nQAHn>8tI^WDOVMcnZ2=JpV!9TU|t9B z4ZO8CnEXY20R?Bix<2{R_lK!%JViu}X`V*U@)_FCwDEOgksS7aRC;X2kdxCXEt|1) zZ!xL)+F+u2@atoub-DE(c!8EC?_j0@jvzcii(=kAfW~9?4*YRvn8R*^$(y{f2itIo zCN>tQs*2t8HSLXF*?A+2VI)GEn{8ON)#cI|c$-#6p|*b6c&xRZysKGl{c?APq032+ zwW&(RjhddjV<)tKJy{w}m0yj-VyxTUHV|i+^2)vFbt*mryAFf37!QTgJMc_zclVtvXH$dYZ>9RlNgup?b2R6&L z*kS(~S~Y>_lT9)JkG5bWl>m7_hQCCxcD2m@1{-7m)7*5)<$;e-UCh3m)Ws@D3S5-d zdGa?Qhq14Psj4{bIaf0xveBkd?DdNABP5v%wYefzR-raaj=4|+k}bzFFCy|{*H!AF zY{EOnkGu;m?Xvhsf2!+e#937G3g3BANfk_*nfRa83r%eQpN5S`ZQ&6})nWp}7e`!W zFwv1!!!m|ieABIet-sc>+>yMiaJ7p*#b7~5N_-YM4}v(GZE#pMTPZmoqZUA3SCEN; zBOd52I=s5t%=yxoia7VmC8rKgJS*&8>t-DBYHeoU4uRy6f9u9}vFtlL>H56#2(HIj zZR5%pTuwV+@e3nz(Qt0{-4s{$!grIdr!DuldALbR?9=bpb=!D;zrIX7Ae($CqK9{I3cRfa zkj$oYL9x!Bf4ZU#L}-CN4gw_h4M8}BLI%va5izyVkJ{)L7Z&6khr3RD3k`+Wm z;S62h!3*`a7vH`zthIrQ^MMDWjcMBK@NFc=h0VPEw3R*#N4I(HGB2dGns+i|lV&v@ zD^sJf2~J%$>1>UoH$YVKQw`Sf>AJB4@9cJcf_LFxe$bVKF4vLFE0CX@vF_(i%;>oUT)`gjre@~6l=kZt*;SZZ{C4FY+Ymiu#?5QAg2w{ z3V9iN&4L9?=dpr?oK+0{g&p7BwjT2EiKu5mJ|k%m$?#FZe5ZZ|iDe zpQYVyfAtHgNZ;{4#LNLKod!}+Agzj))}LMXN|4%DKVjyONj+l=TR`A;1^*~ z#_7bLOa<2f#Gc?zz$^Nh#LWDvOF3OF4j#E0#Tjh?{uFDu?1WlpQ`mbTruEbRJ6%2@ zCRO1K0Z;L;-JvfnlkDO^D?>~Sax~{_j@=y^f2o~coYsb1bhxr!_2nV9>J7t=b5sXo zJgro}=#M*N(FLh$3&~a&F4#+UXqp^LI#%qCC0)EVZy;dWXUC$!d7`kW15;Tg@)2%L zN3bi( zf3kO^>zSOK;3!T=*CAaWTy?&5Dld|4i_(sevexNtY1)24L6H6+^*~o9Z-iF}D=X-V z^oHPMk%f1k4_w zSSJU3!iJ@zEFQqc)dJ%e^DL;te?$D0_n@geWYR+E`OGRRycumCl;C@XE%tLoEh_4IV*D?e3E8| z?OwhBFl8R`SQ0fGefj`6cD+3?z}OqC$0Q~RqsVz?%3K&^_p@h9z{ypW5L;kRW(**i<$QgOD8p*X*`C;PfV%PFaP*%`{S?w^X;2W zWZZu{SZaT`Xr?`St;l}Ie;Erlf}}OEZ4Wl)W(#sA@m>n(=+#JRRNfi~u#1^W7!`7G z2mqmP=Z3&RWMeOChe3YV`FCg5j~~ioj96gc;T={WXMN5imnHu9ck%8c0a(}s2?8mG z{gti`j%I=@^B^{ueYnM1f+)2~GuC3*32DgMS`6@P3(tmMOg3BDe|C+nTW#&ZX-rJU zN)1bQ4Kc9(wxkrU*0E_ngAX=oXvgp&eS14o85Rx1USb*Q)Gz>9n{EGSfB`VVmNKc( zwXWy@rJm2DY~5U8o#9i54DQM;m`&?bKM2BMf275>kKHKB(sLchR5Qh@oJsVA~YVx^521f zcgB(gfgAY>At_;lRg1I=C`+d>wPET8_1Z0G`AG>L(kCLB(R3g=}vD2lSw*Itdw@!5f=HV?Lf#7+}pZlKyH+5_3Zm%3B`OdF7}FpgR~O zJ-poagMXj%%Skv#OpA3f^k|6Kl%0SsOK!>y9v-MA#>>-<&3SB;=rNgNfI3auJT}<5 z6VYJe5PKYVe_*80abw)*(6z`6ZVUB>F*gTuu^;i29}55Wl+pp$`+wdTlYRT!+n;~= z-qI3P$Dkwc2kNr#3IbJ7!2))PbHm|%c%O#6>+;p<}i#u1r_ zT;YO-vuq+1V@o{NWD}k_EGB`dz&i@e#_gb;^iopSf5=K&1n;X1UzjgV*9?w|QRjfn zwpYi^3HhE z1PcTBrgqLZ43~;`4R=>+KuFUqsji`e z9JEkDZA;U^dC<{4xtWU&*Ka5t5x}`^QKIf(e-M|s%3IbFMoHEXaNU&?O$^3xsDY7u zX>zrYV@5`$U<2EBGPxU26EOy(;V3z-&V?4!aQS+L;5x{U9At8Y?a>)Jfy+{KF?Da0 z_qh3?8!&yCaP!a ze}`5PpK{|H;vP(e?29%53`geh&QU6=piRP(h2R;AO_lA_h-rWnw#Hf#Dgibn_F~I- zB<13tPdI?E*9kWJ>ATy%uZQ5W0UYjoMN--oxt68AsC zg->5ETz}y+8OGNOU+41cg|CzRWnK78hVjR}u$?hUHt?`Pgly_c)=`&1R{(lEvEe1O zkK{OJfHW{efMcrv0!01(lcD=6SYx1NS|-CIez^dqHy}#Nx`0^iu@%K&G3{NBf1n!_ z1%o@u$H=MI!mZ)xH}F~Dy`d!lrO^|BxfnY)k!KL_kX3=f5K&h*rRi7qU-JLktWOB~ zLw(Pj$6?LH0y=vKBj_ToHu!Yf2m32qKm41IfE@Iz?!QGY(KLZj&-P&B}e;mLQ2YUet{EAQmW?jfikG)`QYI36uv;2f~K^oF} zVF3@@1t9+L3%N>HscByO=ZbZIGNuKE+H{L$$z)p~IEi{4gdj>4LIKkk_UM|?we7)G za})<}JiI`}X4U2mmK!PTw++8?o|(~k=;HLjSOtWdhv{F!t*A>2$Hmeje~0{s<>xwZ zjOA1cN3uA38IEphs}u)YmGX}IGjIlwI*necqg(2ZY=$dA-sEH>3_qYS z4RS-VNSQr2w~*hoL3g7D^pDiu)Z{08(q;2wsU(!^4Oz9R|B6d)fE)oI9`*-X2usJ* zL<|NTr*6n&jyv`c?M`Twe}azB!eSEvO&1hzo@kmO+gzi?GS33j3!;jXK3SB>CE+s; zMdXc*2RMhSG`X=3=qaziZ3%P;=A}z?{LyhXM>n<`X&zh^iEsg)n*H%TctsIBe{{o% zmo26%Qw~`ljiKv3w6pXlZ()xpS=I{M}%+pf{9OEfwi|ANCj3wAMH`pzdIBvagKMPHqG zF%D97?m>`+?V)hw`fK1Snbf8X|k9sFS*{-{rXzK8$$ZhPs*Ur>`z)%^!LmC^?+vw4ec~)e z-dt;tgJVbq6NYA;7gQObYLFN7X1Eq&cXMnac%}~toPLCwfBGIZ6@AiC@G|3;B7Dnf zd9Q@hpE}eO@+QURnoct47>Lg+z+QYC4Z!6Mx{PVCA%n+*6wbjll%If7rS_oppxSzv z`>EUr$Zx1`M%BUDY)D2A2Fiox{!T#L>O6wx>fYuHEkBV9h zI&F(&b)Ql2gA`wzy+tGD>~-LZiH1$9exq}{zbdrMo?UKJlr zQ1u4%LkoRqXn{_BR)#>oH#r&5=xZ=tV3E1L7S>-|bU0t?cqcX%w6b*+j|Wrr%^KL1 z3mX`FOObbP#ERl(0@Svuc7*=fJTXTcv(t!pVjS9W0b^@x3wbHv<{v5WNE8ZZ%y@TN zv!>I*e|)O_*szm4H*AGv*8sEs+;Z{^O;z_Xu(=bxuinMXt28Bk7qJRX-GUPIcGmDlJdtXRX@jqw3# zvM9571M^5JroaEB0Owh?EO(oux{*mg&w@zVfBMnaUgSNU9jw0})~X>m;X8cjzP1Y* zx>`Vwm}MM*R~fZZdN?w?GBDTL7tKcX@;x1Bm*49ab_t+PB z>hk*X{=xFMF&SsA3D0x$7;7?F8|$!iub%?-1-5Q%@2c6;c0a%O@d+?w5BlaxEF^(jwUEK!>B%mR;t5v&U=f2@c} zrmAGT!Oh;rGKulPaxBjsCUa<)NN&im7i8tr{d}XLE7U_SC?+v}vL;Av&!T1nE`vCKRVk>d-=l5}-7#-{(^oJv)ESrU8->aaoX?I{QCyjb zI+NYrz@a>d`kF1nBxYNUq`m2YBl-ac8-e0W)mMjO9UMBa*k_%F*c`I1e~Bkku;<@!bJ;Yu_g}? zvQXxu0%}z1Mx4q(4~i7w?-Jz{pXoVKPZuDsdiS)7zG?a=_{fG_|Hm>x!b6X&lI|vnl0k)0tF3e+fA~P6EU$Y zu7g&vR|-zWxtz?j2$G)(5~Cy@(boe3{C;%=#_@^#JK@*tNu6nQk&eZ@;J8|ZeGNG2 z`tC?g8FdN{YSgSTf2pI00x_9R;gwAu=TQQMva*D$5Y_|G|!((4=&LC<9Z8X9W zO_ajv71c|~B`=gOIRM{zk1S{W4x*!iJyJGUlZq)PYr%u!i6|HQglB9)T z{K_HP;gj)Z1ql?o#9K6x+6SdPDuY9>@)t#0Ci@O^QI#Mr4Xps+e6=TWl4&A7rD+gi64J$#BKls?PE~{!?nZGF}NLMMRY~`2Bd+=9?dX ze!KndAK$)t|I0srzLUm?ScjqF@mrit*`o3^6|m(*f4)g$#+9B|R{$p7_`9GA_hQAL z+C;8Lrr^hqD?D-E5kKLX=$9j>bX!0l^hhULbtWYV)G~am!{%6A=mB2bL}VN*Gi`V> z;Ok#Cte|)?vKa)W9V1Rr?xS@&AHMkVUbQv0=@iNwNxb%pqfq&ZRNxENCk5SF#HY(3c#!*Ca_}P3nPDbyGyF zDP4p$M9>TV%uSS@*8~2dfaQT@6>MQ7zsjfhf5GW32){~TQ^7}l>-uF}kEK0BD3nQ6 z&fWNPu#rMhNL43a5HY1>g-|pr0GoN|Y+4xzviuM-zUst9VeArhhLX%hMQ7T|gd=bv z7Pk>bxqa}7=(d5&PZM76Zh^oeNI%SHMhlX^dmyCIO|p7eR5rQX(JnC{7NY!YP?)WH ze-s9jlk}P@hX6ynKol%d9FdJzz-7Z7>g}E}t1H8}LGc&GFF?kI{?pySlf4Nvl5I76 zsB0Q-P9>a~^muFHJ(6cBNkMk4awwEJx&5(5<&$A?POCixr*=XLz##-hA|L6Or~_;#R>C4sk1;uSN5Q9e4u zJj(4SE2im>Kz&=T&C@k4@D0|I7O-%qL*gQffELwN3-~Uy7%)4dkV6YaBoW=A$e)?? zY@701Cg-UK9l`$%h7in2wvGhTOk^u;w`q}Riwa&K7ER&jqdgekbk*~Tx8E8Df14Cl zr;`W_hwx;VVv{1{SN6UCbQCq#`FHohCMK(?C%q7$j&TykEFMDSB|9sy#+It=STu!Y z>sTWw@0S|j-leP`)#Ir~Q%0HI7%W-@X#iuEi%XUn84jU%KGbRmRhiBmV#SOG9$5pZ9!e~gfELTx3OKaMq4oR|<>-pD{{i=~p%D`y2D*NmN6 z8CYy;aUb(=bJXYxeyy&p1_gHGgcr2$hF&*0>kiuHS;$$5B;AG+^pahhu}J@bmf#kJ zP*9IR0oXYtk2_&u<)|!Gr7IB^UUT-E9rj-(aR@ZyBq(aca*k@sWr{-vFv<#hC< zxaLuR|EVda31(~RO3}Fhrwm<_YmXqfr!$8xkNQyBveh3cDL}tM#*U7S1|uVNf}?wW z?=13UnbJMcXI3)47{YJ#b0b9vZ$?byNrJL~?u(pz`$tk1a|ue_fM8t7{4(g~GVVqJktC0v}zOzfk6rGQ$Pgp*c^X`n;_Z zSr4gEtw?GURXVe(q;N9n%8HNV7)zY#Tq{Z?HmgrmuS8_kt*51vtZM!O!9&IsN2V!V z#MUv(DDB1KtFf{%V-f#ZWSr-UjVmMU*Vs$Xpjd}?G%JHNFrIC4f71ltOH{(CYA+nK zBL9e9d*o&;1UKU$#@WcoIx!KL8bK?2k>y|UhsuOBd%{5_EkX77@A2hLl0dMPtUNtz zTO19Qhc;;~5&VTx8Kn$VKXXL_>WtQeIN@Yk*@69^wZ(=&+*otJ8gNi*HRTaj@`qd% z2MFqI?v~2x14sf;f5@cRIfdzfe}3Xcm!y^tSPe(NWFIf4jM>o$@6%^QK9WrT2?v06{=w4*Q>KL9R z`*GP#7#UmaTS6g8+Lsx!vfOZbU0GpCOoycYCis@9yt|6%e;iQ?MG*ogxo57|1*9G6 zlE_k1zCd+_11u(6VtqA$H9Y}bm*Nm|VX}f~)1;gL4T6k4S&?L9ij7qvo>j&wHhK~4 zi9+-pyUZX6PlnT-C+XtG7kO;Eu^T?)#xwc)=BBgtE)5*as$>M?{=pY zhx3Y~PcL}kQ{DS@Kws3$d>zmi^)g=v^hLeQ*8zP|FZ1k9l@1bpRB3AseJwK3=nyB6 z&xM4EcTayYlLoB7gvF`9xQ2jwWSOGCh6*Iee`81HqM^7)_bF7<-3K`W$OV=zf{Ik( zOH2|O&v&B3^dh&(?0Ggkv&(SLQvA0t3js)*VkaH4@{ca z-gV+#ha4`jM=e$6mLRPczd$^ylROmM!BofU$-P{vvQFCV%J_*cy+~y$%FT-XJJN9^ ze{s3pe=;;2+Bk|ToFvZfa~XHPWgT+$JjpnOouDc6JryK8-MG<-;VWB7%RpIC&rc%9 zX`mo}pGmelSx%DskShZXsxVz11q(7STWi`K@$2c*nsxd>R3!YWJ%ZwhU&O4rXc}rF%8eP^HoKvIn7` z;B6nb@e{v$z1v>;ju-6j1)uxuPM_W1t6X^Hdmq*0iH)Cq+behV1%3KFJN+29ebUBX zP?OUOXhL|P6&(jrtb;>dKalgXe@|%_g1JjA6Sq2G<7^#=tSGg~%U$Ut?=(mQpLxaI z#WGgc_%%#Qc@u%Y;Kitezry)JRg!+yE>nVC+w zoz%#ud2wff~$x+_f^~`N9t8dT02pwQeO{` zW3iicxHAemLnoppa^$T5*D^fyKgU{Gu}dgv1HHrZ$#;1`OOuewfKRhZ3M$+U=MQd2 z74WF1!31{PT9hiDRH1hJe@Un#E|5xl5+SW%H_I<==balLGt^^HoF9{=a(qd-MInsb z_nS)E5qQXz(tI7z;b1g`#T+HogbfT zs{?I=Jmpjh8D;E9!xL1yYjqikYljyolcmCm=4&Brqb&Pv5@9tje{p?LZl84f>_tlC zX~X>|lr6-CG4Bv7oy2T%_J!A-yVw<#24d<5*_Kpwq$ne7Q>dNl!f;+c@GYStT;8Zm z;HapOUf>4jew75ZX&Fr|^YCP|_>ACeQWFP_P30%D(zME%F%bYH&#K{dr6^T{5_|ea z-8DmE5PDH8%F@;deY!!0dkRl2iy45_wZASzH1^rG+&ohg@o zh~D%QFY%;WJyk!sZpD*0N~=}1ReIXTZt4_y+m#}CWl$*kD}&NPw0-c?>@^cMgzBY} z*h~+GOXpj;$qUO~xrDRW%u9xh?1l`T+_RjTTp@Fk<)YD!f4{v7#c;QTpACv-;IWY6E><(?Ae%e!PfM~f zz$FJcmdO)62J*_l|3get?p%3z)#1_QF{{cO1Gf=R$fh7~ISuHNTspECbUls7 zZf+5ZgV|?ze?@M}szpw+XO(QQN%Q(X@+ZJRgP&XWWMA^NMhv8?zRkj^EyoTaCt%}i0OhhkzT-?ve3-3~bY1)5)G`&L1RZZcA+ZkyeiYeRWjIdUvc9y!rs_zJ8@cNoDR zPISbiIiQOw&t>D}=!ObTCvWl?IGO!qW&`A{dhFT?e_YE&q9LX-RfG1Fab)iR~0tU z1UO^45LUOhb*6)@Q>j5@5!DEaoMmR&O6PT9Q@G0uyKw)kQe9;=WEOytw>mXUszMeq z2uXq6L2g4Tjvkb?QaKy4>W9l`F_E!BoP)Nb8uA@hrbAF&F4^y#10FLG!rH$LDLUW zb`m;E@N68MQY4~>c<%m;V#vp@DR|o}e|0I?;=l% zQoAa+V$GI|U%wl5cb_k$7Bs$dL@gH-9}`4dIhBFvjL)gIye46hs19;Ru5xqa3 zW(bE>{e|f6*zCvL;SZQJ$YgkuT$hJPdfbe@?Br z17%g6JX`u??^n?#R0zC{NJJmVU?Q?fQ zWGch}wz|+4b-j9%!zX1akf>Eke<9AKs>l~qY%{22qp_1l3AxA^Z8hL{l~k1}#~Xsp zR0Br|Fj;Ypnuc2M(k(fFVMcZQ)$pIi-CY@8O{kz)ptn$QX`y($PDqBAZq+`{0+XE( z(Xy75$X*X5NE06JK#u@a4PYHA_WU@%%Uq)(IXaJyrVvJ=jha%dDC9%#f3^g55HFKO z;pkamlz*Y)bF4C=wliE=j!D%FsyyaZ-47kA$!$`HqZInpUh2Wfm_1l-QGqSq6TU_q zigJv?gNe4LTrJuKRa5UN33P7|KunSpJy$9ZZ3zrfT34^ul9Y{yKq(UO21iN_$lAmdX0(+&T_}Z&0b*)jnM7bRn14y_)$8gU2nhpl#0gvN9Vd&XC^rffEFBJ=k>RIFLD^ymLn+bbJRc?|RJW?&dcQ_p+xJ}_j zQOEsJs}zsLEV1hDT0S+eQh1Hi$s$?Z&qc2i|83>BBzCT?@V=r>UQg<%d=q61FANW|a)M`wl3myLob z*s)l`Zj@FeO_BoJs5BY_-8tJ9r&6z1aWrmrQ&rT3aB@?Qf1(TD?hd_h2yrrnb>RC@ z%WBVSiuzERlh$?mu1qmyO`#T!LMck;--iPaiY*4bb}3T_i*qKe>$pLCGLtsJacge&+Wh{BOzn?YqJK>}?>ubkwgpu|tn+f_ZL zix#!GXkCNxt?$`i&qY3j8?sy`v1qsLNKce2d3$7#i*hWh#yFx5%r;c@I4q0G=GiW< z%0j>^c$FE_9knIjWRj6k3uvh7Y7b6kqF1&GQzUy_e{=y#CD17&ve{kH%Pz`MJ?(1{ z1y$!zpWVG$TUSaQF_j3^kIYm^F$DdjTGg# zYmVhKf0T9xpded?Y&xDXdLTb!O0*k;6y$&~h({v~Kk)CQ{@qZWyr5i3W2%_)2EGT23D%~vi8XaE0{C!O zGdWwZTydsAo(d(loKz%?K}!nDf~qlopp2nco-C?irBLufk<6fgP@`Xc_;wCa2oEu! ztD&<8CA= ze?I&sMGBU^hC*8p_ov3c6PBWY**dyb0fv6yh_aP^vFn9T_gd1(0z7?4l6~Cpv zCm|EJOqhb~nXKr6Pun$Su6W@-)uUB>J^IswG)`;zP~oXr)k{P9EwmeQ0%=`ddapZ? z$zM<{)IV4q)N)z})xdsIW7gWmnyAy)f10RYYodOwiTW{Wq8<_&tucZRh1|V8DS{Z} zCZNom1n1^dJzNfks3&@X(a}8~`yGiswoOsLiwq~KJc{{%7Qq1fwENMF$6BQnDaDY!=1Fz zd@;%-9iI&)6xCH74@AE@drQBX6nU+yQ&>mD8+c1yC6R+NxKy3zC7lWI6mRKQ^~6g~ z&A`=#RMdn(uidbP7R6QCnpes_f2EPBo{o=spH-+m$cRCfZY2*=G&Bf?yJt@>*ma~= z<;kr)ZdFzZ&t^2K13l!lqEL|$)@C2Bxuc>CIP!L>f6T*Ta`3wnfK&=byyHiYrJ2@9#!O{*=-w?XQvfATgjT~=VF zQR+JNVm{|d8s!G|Kod+tEyeTt;a-OBNb}x2KnL6PT_?ryp3{}<7)^usGT^%o0 zWulSO$Z4wLsxyuQD_R#Cd!o0fmG612T#6hvMcMC)-s*l^4w<#;IeT$X;)&% zy5&C4xxl5My3Cxw$<3*kH4g)5T32)=>wZ#t(|YQg!J#s;P{)GXtl9yJbcyU=!;!#g zXDA>W5p>N1!a)_yoO0eQYyYSn*QQ;wm8m5a&67u;e3z6de?V?Y&emvnnms>7Wq455 z+Z;rIa4!MsfdGERoiz>w@a*zBw^&KvccicP5MB;ECxZg%E5QghgQ_IFs?(jiTPd@< zg=p^%mnf-w1&8&bnsG_FANy@|cHk8*Si)lkCsE1Nbwb>gN+o6;wRv6>phUtt)a3-^ zfm%WIu4hgpf2MkQ3Yet@)wDa^kL|D@wdZsR>gKd#hdMr%oR*uIT!j+$)gJs}6+3hv zGU0*Alf8g1cAS|!Ak&KHI4Jg1=Kgba5DI5IXvjiqV>h(jwil&KyewVnLArEFm*Ubz z*Yaf{7Zmh%ka8|K%epT6P>eU_YjR(}5 zQI__oH|v6f-f+OYbg8V-LC3GB(x<2}dppKND;T^N3)XQL3Wg&n$Q3zWodVIc1ENid zgoQ-4e~Ja7Qxy_DY6YplpYNW1OS8P6DowwzYzhSqmL;P$~9W>2UrMqle?3aksX&JIngzW0M52eUhG zzM(UVQFUp}e7(~dT3vBZ@rse8W`h&0n-0c3e>^R`O*e2-=-)s%MKN|6<3f`I?13Qj=oimlUS`ROi{5gOYSAK;yVWDlZ(qXP+ffdc?QcW{8CkV6Bce{g63 zQ`yiPL$(8KjMuAlu&j)2ZuFQ^RvwB6B8-QkQ$v;(U@vmvcUq7w*=aPon!LDr)66D(0 zl2%S#d-oKc0$F-0wq~VM)u}M+ShnYOVpF^)`SwZf^wUE(t+ift&Y^<_ofu9!e+-l< z+&@u{oXP~)4kw>=1Y8Z9H#r^zn+dPx3C+QvNK*7R@sf{?(yB9 zA#LFgCus|%O(|<(rgjo3N;%w0GLE_*Mvw#5vc_z_BZ)}fVx*%S7%h;!I99=T@Vtqe zT{LC{!47+|=ZkRLe5pk!YVC2?C@C(dsOS0yRoCf))a*l=@gve+lv+!G5ZU zr;(LhwaMvQU@|McaF!WkaBWBnRc)fIK$s@i_r|_aK7Zt{`nc7NJYdp&g8e5-CFlCu zW<)@=ZFR+FC~i)vLOrUCgvDvC1=wJmih+qknusKPlc%9PD_pm7mtv1jQsmnr&rHQ; zS|1>2r5sY29ScZ(sLH}=e-0MnMw#VBqP@tiDk)?lt`#hXdqifrEP3HdK)76`hg&)n z@JOCfl0gGJgRJgu@LfE`a-6-FNp<5A#WPeeK<9!}Si?~TJ?Z51tZZRFk}F2WH!UEt z+BXI50nJg6$aAeTQ>qy4)@wej*Lr8Y#&~ll^@0;*B(BMO z(vm#^{86KYgcS)0@nxr%VJeHa+`Z&(pbXexMn7k805NEIop0}>LUAhG`nwZy zGuD^SdU>CPd}kKCphkUY3WiUC;yOEeE^YVh(jCL3oO3&DQpNr$iT0wv&h8~?ii)HS#dUk| zG$@Cu$$JJKWZ6*KEuNXTyBrZZ4ajxUDXWa44}PP(0~f+uSAnexnZCJe;dlk1kaQS&m<4x{9Q!lllkib5T$3$@|}gB5!>jkPe37w14* z+9(nlwxZxkdKi*=b95ago+U#7k`@(^ibP$>e~_k#78S*4o{Y|6r6*;d-Q=Kpev=lR|e=R4-!p4 z*B5@6?AyoFF~Q3nkpa`;zefS7bQ z!_&=5qTovdZ*wI=^x1ZSCGCWJrOclXOuqRlj=a4JL1fQ{S&k4yJw_0CV}NB+Il?ma z5|&xo5tgaPSmrFfCXsLGE4}I@d#8f+y#}TzKApg2kB)&OqQ$Amd(m&s==J#+Y3jV|Hw|q-bWTZn-pq5vp<;^Cjb@ zF-W&wc0OFNrFQ$@67AjaJ~N2gP^NkR>2R@(MSmD47ST%>F^|7~jVt>aSN1io?A7DS zzPbJFZ~yiG15ir`2qZd)Sn5y!0D5Hs08mQ<1QY-W00;n#RJ>XM000000000LwwL}q z10jE5b7(Gec4t*o4FCs;J2z;IJ2z;FJ2z-`cnbgl1n2_*00ig*008X0+p;6qk*4`7 zF!oK?1)x~Rh-ho|#k|0b+1NY)1yV|OAten{l~u#1AOAiN?2Vl#W|9=eDw9##iDMvQ zg)cw;{`>!Y^Y%}tKYn++{r;;z|K-o$eszC(_3d|mdiA&8e^r-d`RercyKn#f|M<&) z{Qj%uw48Y9l&}B$ci;T&)%`>N@%r}XH^2Yt)!+X1*Z=Xm-~Ic)|NG_N+vP9c|LJ$U z{k!;q<0Jp$KW^Xs`CmWu!LslB?|k>G|Mfqwx9|S?e|`P8SEuj3`TbX4#|wYuNj!gk z9VhXMW4`6jt22Lp`0986>wo_4{*`yW{D;Rc_c-}J)>kFI_Le`d&isA%0I$D(^RIsS z`mh%3{OZIT|IeSl`&(S;zrFeP`~Ul|UthodKmYvyy!rNdHTD))8vl;$qe zFHfLdmQqi9{JW0*dS2JdnEkYzOD})tv0s+jd{|n&j5o7gdYk#=^z`!8FSWQE@zN>3 zA1+?ELil4__Vk_`iL#^WRseH-G#7FaP>&yzs|A{_+0od|XFaToW$%VLiTi zSdX!M-g+##9&td{qtsR(7o^4MuX~(q@5`l+Q@@P(TjymP*UR49XP<-Z-^O{K9^zZJyT4w!Pl= zOP_Ir)_y7LIiH>L**ovWFRp(r_RpnX&m|7p;)3TMFVD5cvEp>%L`GaOk3%@iyv!0O z5EofCq$Dn7AMtd_Ppc+6wQ|hUTrT^5t|Jz$oi-Nyv|UDt z6<;oOkF}eZQsb8@3s*xd>#|5#+M26=iqH2gj$X#C$5tpkj(dr-iscw_AL16B_)~ddURF*h?#Awb+;PS)xDhqQ5KpvFBe% z{;VMk+i6Ei+jYu>N8g>#MjwYCy}TjOyYFt$-F z@pcR093fjJmSb5~HqIW>5chiS*Gn5Nb1ZTnJ>HA8j9aqDTGmV7&u*G6ZcuCI&>MT~ zwvfVhj_oi*>D0Je>$%7Bwhbwb?NTpga^`EuSc%=WbMNAcwm5(9kb;nd*y39}9UB6? z_V{h&`o<6T*hwSq{PnWLXW|%f;5@f;NNWgaEDq;XSI#ERulCDU_VX62vYp!q+2N?6 z36QKFVi)qg`;~KsMISOyy}#5wkF?Hqn9$lk0oo^<3qexSvvgpebk@e^g) zxriQ%9p8a3<@B6<$|%e#mgV5PNF7Z1EY78{a5# zX$6h9loGdmTk2`VRqbenB^1nvPsbh%!H*xg>>Jy%##Y*9+|JOIp&<7j@ASPt3wix! z+phJe$oU_i<-B~R$s32s3;9;XFMW9w^tu(abF5GgEfas|J8RtMxAAXWU99B1#>MxB zu89koA@#*2Zn1QsCdTlNgpvs*xb|3yFa>Cq$_nkertQXZTW;nD5Clun2h{n^gv9}iPZD=p75#I}eo)@HZ&iJ`F?ip+tdt;ATkl;Af zT#=gTsWx1TFfmH@;JB+Bt;XKrOt7c!lLc#q$i{!x;;x*zsJKI+@ng@$CJb{E=AvnI zXYARjjb(Y3G(=%pL$hq>o_AqgVxN!wmvB!0^dPy*`ZIp>+){F9>yMIK_OO`T zxfwFH?5O3zR-AjR`MxR}ae0XM(+jN61qEBSa56@ibyQ5a8@OsAIwRY&Fa(Bq+P_}k;-Wm9C?J7EJoJYuwAoAHXuf;Q{8MlIB2(?rG#akoP)lv~`n z@QMlsr8hnr@)bI1^5YGY9LH%_zOnIhVHg@(I({e|to;;DMMKYFKf;L&%|7wG29h}A z1i}{doxe3q54OUy?Q9lKCM*;heqfC@&C7qBXDkh(8@p`9X5$&e5lY2suj>`*nk^JU zN08PHl^a6U<9D}#CD&y^T+xu6%@)ELuEZ8g&rj_mBrJ>p8v$Q29#sqgP(ZK0N{OZ5 zFWP}W;RCYax_=MT5f_gY*;13MNg6kN;bL%Ca6mO?c#8K^!=H&wo3=A#0|PZQaUDI4 zF^VsLVTPC8Z8KfXJ+3DfZ7n~%#&6=oEXq|)hT&@^4d2f0+cljd-9D~lQ`O9k^H_#b|f49X~(tWmg_98+SQ0K}RU2Ix{44;o9eh zLBkY<;}8lw?p%0`+%kOD@DIXXt-T(;daR*;tHl0@tJ*i0C-w~cAU?Q-bS?JxGDpei-m|yUSk;|e29Hq6=-zDwkrb!I&~KQZiXz}v{k9&Q6K4f5|;6H zm}$%j0YyD5HvW;$|I%*Wp1WG&quYE|OK~ads#=Q8)DYo?5EuV=h2loIw3uj@?2cqvaRDHPFK z(K>ZI7A`!uPG~yRE}_7NIw@o*lx769XIiv!ZC`Ki$%gu4L3i|UKjjA$RB5jY8qVrR0r?a+dj3~9nCa<7rob= z`xHTij&or_!pYQ%uc4XZV(lu--C7dShQ0)CsN`?4u!}r?bO|G;T%x367be2-3 zl9?;=8X_^-BAiSJ521{nUdSC$0tnbJy~ds|d@}Nh_rh z#c?xJweeXEBDNhM@7ACo(+jl!CoR%0koz z`Z;!g#SVt(4-|op%5vn2&TeTXB=!#2)Z`6*XmzBy7D81 z>ud{q7V&Q3C?Z+$i(#EtWAQW{p>$@b2_s+wX)*!TU|L5A>5boi41Xmw0D;BDL|phG z=+la_aD$@=Fz*BX*4Paw%y_pN9pM&XfQ=(C&+#iEECvuE>^EbYO6)|6j{uUT!Ih{4 z6NLL@0~)>;sUhvt+i<(eehV2O^zK->7CUbl*Ol#QTz^ucG+;wVIHJ8ceE2l6C>lJ2 z$+i$K#s=iXtMMa$)~jeSio2x-p__iT2SML7;30%~ zxI03?yLkmH@g=@Ojuw|a;-SjFu^BiWBn00DB@l0{s-7ChiCaema5465Yr_WeGZ=q7 z^Z2Mq@e+GtIcKp0=OB&{(H#yO4yHdwXn>S00R*UcsI^WjX?)ud(f zEaP_RJmR0NrSOPImo(v#{$DoIM5tY~DLS!n|Kfr+-XpIcUm{V$r-xogC3G3;k6q(Z z$R8Mg&Ewmh^VByMXTt|3aauVMVyuNAc6ZrYpWePu=iaGhoB8R`PzurB{8o6&oJVZm zJcv_F!hN7!0(P%=6DJTx;uUM+*9`yP6rhl zrt(6RF~g{(gqKN~3z3~$D&M#-(*O={FYY&gDqXG0@0p+BYHNsPtRDWg{#U%v(qk{A zSuO@jsLw%`B!blo_Nni#kSa|tv>xfKqT7hxBe*d@J!%=TY-Hl%k_j?T{gfHVuD6(( ztzz`sFsohy%fa4Z)!9{X;wbR3`8o<0fh%Ee4M2Dw?~c32=I;CJG7Mb`=5FixWU>jKuq>niW`hr8m3=a^NJk3BN;Epj4XoKh%5t8>TeYjy-r$GuW1$9_CF~?1gxS>6| zntNnQhb&>SiWzEyukGB&-ApyPim;n_r6J603-+?<9+D;T3{hM71c^gJl(^CHDU<>E zMjTb7Qni3vNMRY(?LR6E9iH=H^eak^Tuwb_uAo>?$($x?&in!=xZU$$v2!SYSQG== zZdLKpExMpXschnz-pFl*tmA@M&&1_y=)SnP)qoFOyH`~KE`4k>Qp+4a7OS)jt6MSo z%1MzSi_f8jH*2nF?byHU^bs0h7|L~OUZ(wYX$K3ahdgv<)$m?WMVEv|CW{?cu<^^g z9#2Q#SHicYkZx<3TFQH-p)pD>c%NLOc{Y|pebZKrr(PK96&LNo z`eSo3DzPfH{i4649xa>MJ{-SnyYfn45XtJhR+=;QMgr40?HYCHRN~Jwb zJW}AX#6(UWZ)!}^DDj?ug&snH!wg_dh!V*KTP1BQQTItt>kvPQvBfPz1t`{Jd&9Vz zgCQ`ksuR@Brpv+p2$zstjO%2Ac;{yH?v24pho!@0;#?plt6N?n)DH`ZKw+@qW>IQV zsGh7rO=B?+qp>|2k)LEGZjXSJ&#P9hN40Vu0G&=%{@YvV@HgLoo~~4bS{&#qRwbnC zy~5P@_m6!4{E@$X|Mj2W{P8c}zYeYc_20h#?mzx}gq^^p!XLmp4n;J(h@XG?&{e#C zxQh09u$uM27SuberoVvI5Jk=iybAs=X%-9a^$NZvPAj!WhzRmXIU_{lhT7asYm!c* zyfCm%S5%5Aadz&1g63+(7}Z*68ILfWN=D{v=}65|!Ey9VVy^EYa1h*@n`9d%E2+bb zfugA65rGpcc(vkFF6NVGKWdkFfNadM-OfT_V%upluICh9H9-&4J_+zCuMZzSOWU~e z-;*&^u^s}eYF&JsO%iW6aWSe76ZshZSVz0zW%nn%XoXdJ*S@8f4 zE5Nr^DQLRYYnXSukLll5r_R}0Nr#kOXuu$?yd~IYJHS3ySIjCQuo0X+qnP4tjfFXu z@tn)Zg5&9O3rUht`Z>AkCs*BjbUN-)s1;S3iLNC}gj%YT_tQIXcI0Zt+)8J^>$9^m z!Yz8no+ZA2@F_R>kg2@qChLbb$e$mg^zHM&H~qdr4)9HRiNhPYD@(Z8BxFd)lKLhf zx`wjeENoG%q;O!cO5wl?8E7gzvi;nsdkxEJ=ZLBHgvZ1REg5}NoT7$Vvrt#8UTIti zGw^375iYGg-^kNI%5|K3Th@_Tl7gtLz zY^zGsCU7rPHRC;8$_H-oUmh~fV|>;vZuP)d9ch?ll$W@Zn$ao_$vWSjx6mo3^u`rn zS_u4qH0KsqC44fLi=03>Z#)1#x8X^jDc5djpZ&ap2&tD`^|(_@n0tzy7=6%1;dj^h z9+=?+m;2Y}%iTWfYU2bGtFS&*1Yac9E79(tB1l+#4e@EaID$!zbPOwFIK;sIDCv_j z&_Ujmt&Kfxo}%k_P4j>t$U1UvKoPPO0pO;8|7j7n_+4^%B=f=Ggti2AV|h*QM@8AD z*aQ(;37#>(SNa=r^Wi)6X1#dV7{$SG{&7NzKHfQNJQ;zP%(>TYA*N{n!gZn^7`{E; zq=ocRQI_6*%v@X>Dc$g{tP{rVCA!*Jh}zzf&+?9j`oQh`f1hvP`dPtfX-7f#sWdWw zUl{BWs&s_ARKmiBp`gyNp>HU05?drB!@ran;$rbMx2M~u4rgh}{N~*Y39YL&qTNaZ z$|AhULA=K8i#?!PiA5WLk_638ik5hMrif7J)xVgMH6dv@g9JdKNA@?u{Zx2tk_2S| zn$b=U(P@_NB3cyR0ItP6G z3Ss2PFO5(E<3nEyi5@RJjJc8g5}|7mqLFDJQMQqn+xKjmoC<1BE;lCWCkY1 zOUeu+#0W&ViIWg4zJ=EjDlxw7W(|9S%G?%W5Mt>qoUnmJ5m;Go3Wd68bWoTr%uPd& z0?XJoEhU~qJRPW*@b`MP0#k&428BXh2(H@%G8XSnGNnJfyUdTPTd+|4+`x~G*tEsg z--&DR%Gd>j@L>?i^pcO6L_KTRL=$BpfM8Bi0fJ%)t40tGTKP2Ana>D;!-Pa&vnLoQ zlp%PEl`Ki@FA^H($u1);GD&D)ba8rd1VC<)fFSB^rj5hfB*gkc= zcgq~<`iDb|z6I=5O<%`CP8Ov!pV!E8xxK4RD?#sD-axvSnBm-;?NVa!Zb8|K4!)jVtoezsSKCqbW zzL@LoYL@5KbTR8E7ITn63_VIUX#JRIZtsfbrxvq6FXnt$%k9H!xjwDs`p#P3MRR>v z&GL?DuAdOi?Ljnu_h-@kvBm7~EM`rp!n0^TuI4+72}&wV$gsdx-doM_Aer;s#r(0g z{J3DgdAYfd6}*028vBoI?f$T}-xJ0!-P-R8WA5zvAz^GF&%*_sLfFUS`u*d#_K#`G zcQ*IOVQmb2sV?w7OA)-ale%e)XuPe2J?3I~kr& z?(PpdJ}@Wra#|NUefrPKUVLnKZ=Vv)9}f|KYWCuP=em(!p1deFInFTS3zz+0MOXf+ zOE|@Sh2aKP^u8zbc~N%xu-*PCs`AIvKm8X_lXuj?tb3p z{`G@@oS&K9{nG9I5xUn-M^ey`OBn$!0^=Ygc>mBUpEKz zCF$MYY6fE|vXG1oSn%ETc_EIErh7ap$ok|=J}zRJKUqh9conxVNRoe{hOAGkxcyA` zr%}R>vnw{^e@-Ik7g3Qv*@OIL?es6A7s~{H|BztWzJ9*jvwl!9zE_g{3CW-FpII^1 zrNRynMjQDm|4i+Ep_Oj-_l1=nG+h0c+0nmz#^+OuxGtBagsVfZ=lDlue11kY_x-i( z|ClJI!5O;L(;7;$t)HLp`DcpaX$e=F-{Kr6_{wp(I?MXFhUIY)>%%IR54$@1<3hH7 z$JE&;!ZdDE2ykcU&!w~Q|J0v9 zAq%u@(x0s18I|$ANA%kQQhj1O{{$0%{)^;wYp0cBgbfFo|6e_=`*)9TNJeh$w9@Xh z{D?>N_si@4>N$&FY(GO`*FXq#I)Hxj{?PgXf9N4$KA!!d7mHi|p$?I}aw8;Ql_cuL z8ut&Zar@vJ?;qRuznaV0o?OnupnuFgnlBXUN0<0Pr`CMgOYxKL;to?!N2>{ zJJcXctp_*A3gO`cWy#o>bOSkm$lTT>2Z280-EL7C53bp*zCL_?oiwg~|NF1jWqBu` zvMlgY)oY_UpQ%3+^3Ij{20kRiv7GbWdc1Ky-thm&Tk#>2A$%bAHjn-4={WH5#_9e> z{QrTIWh_f+pF=DAewXbZ{^dp2-QaUzMJUn!Caz4xb|8MwndV2YP^z`g>e|G%; z{PZfHdt{K=zWKHvBr<>b>(|%s{uWCfB3VD#56Bpi*-vX-E=zxPZcwzg{RU+_<5Bt& zw(wP5;RV{S1r|{#UP#PLJ9lYLu4sq4UnFWfp@^K#0Oe4Tot$A8C%^0zhR_)cgGp%Y z^=p;hXvqF}_Ua7qVxRASoI_g{2D4nD@e1V;Cov?Ztu_Z&d4}gH-#s5^Mrkchg^4{U z1{=iB?@OEtZNHof6OCXf_G3`Kjr+5gx@6jSyq%atLa`nHmcC<1*XiJmOWZkRC>stD z2R(I01>vC06U_z>4`0z?I{P&ba`GT&4|4J#XAc5B$6}YceBC>L+#>5`K0bchuKfQo z<0FYtX)PRYm@jFOMy1&U>i~g8n(zhYzs&(Uo4oT=riA(M@KxC$;kq7&VLF0TvvYR_ zmz3FZq-^roZW8J{$zz`n4?oNympg+-RAyn3=W{*-8(Vq`TIAaH2M*?O4cY@4+Io^6-;(zAVj`0=x? zOeookse)Z5^NJOKQ9@#?Qkh`_mqdkZc4Kf59vt`A={*pC5Uh?on6kpq=)QI4_LSb= zoIS+JL#*dK#K}Vtig*l349pW9!Mzu(Em{X@L9uq{MLX(j_3tO&l~Q`Qk`yaF2|^iO7UQU4s?favDVxkcrtUr zS%aFm!Q!%i<{**PQB*q=7`hS+F}V+6t5RX9Gi6kRGXZz0FOuxfq=kcq7W(EPZ#yp7 zk}M<*PAn!|bVY4Hh7^s?F5PsqXysy)%7eDBOFEA;D2zzRuU-|l~y*08M7cX0iX zc|rIR7timmP~FGb!Pd4mi0YV|0dLc}Nc9m5TX%+kOBLB;r5k}34wmPUvx4NIg~gi{ zoothWpUFvW+=+AdFTB+azM@?wt2JFGh95YRX4kn|bBo=1J+iVhq=IRD#-r^y!7eFM zb=st}U$>;rvmH)iz@byQG~CZ{w!F`r$F@~@OXS|idu7tj89FR!%~Q)POc5#a=q{HL~UFMcU#fp6XZA&i2v(o_J8><{iF81j(nzoaaf#emQ9*FCi)TE@Uabex1 zKR4&h9F&DM;`BFbob0h#-;rF`d#_ zb86D=2nMv5oc1_dQ(><&$>GmT8NsMv{f5*wn4IBVtdP&CN8w#AFh-%t2NOwb_k&k| z{T}5NLP^*%l8sa*R=9h%W$ky2^prGfkKLf*dn^S9Tp|N8r{zW>X={rQ_8F&vN>gSgt@-l#h~Zc`q5wi2|J zt22aTi(H*Gxa~I?m)V%=3CAF9^E#Y=9K--TDf^hSz}SO`B>GfUS6GHLuxm-?O&#Rn zw4VhIk?kPJcix25PQuh(^W3W%Z+9r7vp&}H`q*&ytGK_s zso^l=u`8~29P-_j5hP8ryS*k=zT@eV$J~)nW%{O!q2qWnKDX{S!(jMK%j-;kFojpJ zWN?Wch{qBGYOeg4qAPza9AiWus&Y8cI~vXzKA~UOqeLv(K0k@p$|}7r90a*AY(F-ernqnkaq_X@gwm^~{Kb zmi*v2nPt4fcIX8rIkDSsfUj zh@dl;%V8IghVf-Nk{v_35lIa`q0GU1#&l7RHi~2E_$3Twlg62B5~R5~+V-5oG4Lv# zc>s%g(lR?IfzeaCT|Ga4ysUJMNPE3Nvb>aJXonnI{@eD7AzaV5y)XRt%c$ih!D?Xw z#QMk#8vhL9?WFzk@^;m6cq{A6F~C&OAh)5(-ge*2Q{ zq0SwK$h^czJOqrq!L6vBobx?AzEo@!!jR=@?ojR`1Tx z3Zdv!9GGxqF|B&Dq|qgRvl7!op2DM7I`n(0%C;V=(zr48k9%@$w^5u<2({~=DAAl% z2Mr+}xKpN_BHX4b>4vA3#q#wEzdnZf6V;iHZPCnD>g5mJ%nYV%EwO?Q0McH}9#)bEbg+;Vn( z-nngml+?`1dOr%i_*(ju+i+ylB46;_;n8O}v4f7e>_uKwQkcmKOrFSW8=1OpQmtFl z3F*MOVfX_!$tmI>pR^_|=e9UAY3lrUNBcro>o^&PmyDVtvK{5V5EJkwAN(u>`$hiu zAfF!VwmEi~n89*?Jra@tnQD>so)NXk4@QE2;d~HbYhl_{j}LQtOjN3x68MiN6>TE< zGEKNU{tt8ISY1bnkuXxf6p8zb%0>||uqh6^nT%v4sb_?%$T;lA`5{`zJ~KwdQ?Xf58A)|Lrg>07#6~kF%;{22SMm6}Ni1f-I)L11iq4PEpiLy;P6n}m zDH0*)c=B9i@wMU8Ksz?!^5X+(&oo=Szc|&o`A!>G5+3w)%v1M$F zzS|aNWji%;Y!1e#CudX(K!7Ltz@w0VC8DM<%}Qse>#)PJ)YsN7;J2ez%p)e(Jif|3 zEO`@OpM7%j$%{7zBZM7x7xtb!eG&Sh2jjL|b4L3*9qGG|?Uu8`dXJ-~V?$x4qz|x^ z*XOl($jyPP_)-)HuA~DPL6??=z%v{e=7}<0SNk_HGzqkD!lPl3dEI(gCnrsRtXaBo zR(j5iEIIdiDW=ZrihHm-yQwTzLTZZBmIUMYq-GY{vL5%3t2GICokk;b#U>297JeeXzJ>$aa(L1uto3dN%{Q z9N#moWRp6Kn1@0HmmlhXJGOSOKV5e=Ffy?z*UgC`oVcTes0x|*p@`JYEM`+zS3geB z2&)4d=7wWb!keySvWGrv<;=@)LsK|7R5FN)!RJ=y>u_5l$e~W=V2=AeuaEcqZ04~J zUBaW^|!t?kd8IZ17dz@?kTA7TT%`?Xs)bZ#eqo4-3=nd#0;;y=jp zXrIuui{(Hl&kxRi&GGTX(T;DOiK+-RML;xLgjvia?pBi~6G}#P@)DIvVqMBmj(T$j zsiCjsiJA25-NEp{WbnrjzL~Y>sje(pI4utH9aMb#%+aJdA(B8kcC$5W>-=3{9;sTR zo}GN`XwARQBV>+$@{u&l*)k1{1L-~!G_Aa)x8RiFV#K)%mo#SNl1!a%Up~3~f#KfH z>~P(g@;SWYR(8@wU026m6txlvr(-Bzb*nL=8gInu(YyAA`DR(HDZ(s4i5TSJy3%Pf zauy(Zqbp0!2rtg2H>chNNQ7RpsBZSKIibVE=#uIqp3GB!o|34IevBwZhCQQ`XLQOl z%JLC!J7A}pT!~XUc}k{5HDYl}Bx9|*77NS{r*2KPwyHqljDCi~9Tqb;Ms?7C+(nK$ zL7IhhRyQ+x(fb*vIbFh8dW?Trt!uNwi-XYtN^oX%)%P-bCW6g5SH&z=xQ0HNC1)r( z=au*g*KBitgzq|bJ-CcnPdU*VoT~~`+by2X(>ZxMCr{_(>6|>Blc#ga)6q3HqF3)b zGVF+l;&k-(9D}uqu-Fa1om@Z65!cz zKBg1R&!alAo(#q+PD+^26o9ZgJ_3N*^z1MyDF-&01aZ6t zW?(W7h6}C7+#U?vNMKOU88=e8<0oR`Y9_(5+RA+1)@_=_U+ZBpszbQ&Bez|!i}!Nk z1y%8XLKW(|x0Fi+q`VVvBcO`D$Rf0TpWa z>Wj7$jAcWEa_M#taXS(st_syZ&4LVRl?|PZpA&Ufodj_-tmZ=+yME1oU#3qdo<_usL^g&)Rk`ZU#>PnHgi|iXE!97F5e6_6es6^z?DF?C1C$>s=qaMz{glw7o*Gq&vB>wAA^7S?BBtzHzH zzI_44WP0d^w+2LD*WnS7nYHs1Q@c)KS~K#93x1ok)>g*n#n!T{Tgd5Dt<%Q+9l)-b zP+pjQ*|oRrVi4I$Hub~d2B`N^5$ z$cCTe?JctfrdrGKkbM4I)ZmuqxpW+e6%$I#Ub>H*9(b2i_SVeuvX zr6zWjM8PJ!QxPK=232lz#7uRyIF7t%CAcekeQ}3?xwmu1-ue@NYCiUfcmtMa$)bE1 zJf>ce(r7wl6bwEW!}M_l^2ZknghrK#E3p7%qx`&QrpN$H8iv@Eo1-_+lo`YcnR!A+ zD#Ikp{GD;a4EXJDo)}(NrOxlyAjBSjqIZX3|7){(#MKmkwji9ymhg% z+8L2r1jOzbgW~X1@)U7nsD1myy6xk9zWVLHee?A@-3r5h+Ek(IW6q3Y%+O-XHjDXy zF~QG(6ePPqxYLAp0TmJ@xe+G=I>510v@qA1StO6cSXNsLr!FzR%0AB7M^&vyjmwde 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%0AXC*($Arsya!^#&tQ#$fn9K+!DB^8&S(!LMQV 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 z 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ÅB+ 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 z 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∾*9zXAoiCBF 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 literal 1103976 zcmb@tbx>VR-z7?LcZc8(2lpVsgS)%CyAufR?(XhxK@S9n;O?#m*PDFz&P+Y?JyZ2g z)jfagI#s*6YxiF3x4PHr-3rnWkeFb9f6v+_8vpg@|GU6|k$@RGJDa*VGpVW|fx*CH z@|gWTeKtEwUp9C3Kmhv$dG`qn?7tc-{2x0(_+OnkyP5z0(~*PSf7%f&80g!$3I{G^=*;3OhudH8Ox`n#Fcl7e>33l6- zCP+0r${$a?zx#dR7vSHJJ3iljzc&4HjvRV;nK^OoF)lGF?|;eJoYWw+eSETW^Ymbt zYS%J{l0Pn$Px2D#qy}5UrdxFAcsz$vbgK zbZQegWv3^6X;P(76Dots9A}rl!sWJ$wSOqR%-YcMpsX=SONOke4QJ^mzAe&fr=>|)wWfoYVl+i z-(!NB$+~xV4cL$wbiLZ9<8F>08AuS8B@HAh9UykF(znnxS~Ey$@W-*+Bw29=wZh|~ z^J_42Aa2=DShi)lpQAKKHw>XnAxY~nH=?!Ukx~qQxadsdC5?(WVFt0K|yr$zoobBf)-841@v?3s^FRRM~s`+$2yp^75sOSRC0r z?(o^hXI-u*i_iS!$!>$E@Yi*8)K0U$?kj|XGz{$XbnG54I2hPp9{#^I^S?9H2?7j^ z@}CTK@%S%#0-Q{ZO)cF_0cM7lHl`;330bR^`IUb#qn^KEeW~ZP5rEwyoTP~!TGm=x z|H@YYix?XE?#+eDH>H+&c3^woor+|G4CI%o!9UHCoXBgj(~p(*b8+i96>tg(AmQ*h zTjr3RT&ZbB6xhhPk8AWId^x4bC<&L3a32sz2*X8V>1t_gV< zJ{TvmT~);jYH)nBulltdq(UfGC4`%krh?hT#XIqJP$!>dBZY)!&PvWyh&~w|uarc| z&ZJD@IcGiwkfyOJ}+XNc-ROwYy&j96)ZB`LOfl#U)4FLjWcdB_&ykE_79NWIJ1sy8o zu=Ct2uiqp^hMlF!K_AnD@YJ;;NzeedOYJ=cc0lD_<@NX{D;?`G-Q31}Z~IEN$71L6 zh+KMem-8s9y20w!C>oMMKr|(1ns6Akpz^u+i~2G56=Mf9Mr~yy1E@nB9?NIcfBLR> zaAFAOFZRQvm_Ffu1oJP#|7X3#{wMav_Lg?~f5quP)!_e~Pa}VrhWF1tO+Ab)4DHNK z0j&QChoV*fm*BNG(J0oEP3Cv()xCY+2wbX1YHNwN=|0{}EmA{9y;Z=i<7tv0j4|{5 za9dA*s!P8=?VB;UUmdU$Y<~7yn%tbaJnh4`Cd51LCX4~zIq>GT1bKeA@^x2-zOn1} zRI7pb2F|u$JG6PM&m&NXh%PRe_4WOUTTczW*K;N_Ck%38L&pv`%=llw2I5LH z!*YgT(n0?u46H}B6_ySmpbVyo-V))&{m$n}MFQG6vKbJX3QuMMWrqjsv81D9iHy(O zZc<-uDB;^5lA747226^;l3bYuYC0r& z!ac1)(rQG;)}t$kA9?{j9QsUX)^3rQxqho%uLSElqDI;(D>K*lszKUES}fEgx5`<3 zot&Yo?@rOZW>|nWdB~cK>GslbiP7!F@TQsXAzuA1dLpq(97xWZdjT?^n#MWY=cw}f zHkn#_IB*-f3oSkU&c!NbAJcm8q~Q`W8oU7a{MuV{vb)tbr0f3Yp^;8;Z|bk#u_+Q9M6lw)ng|Qg@c4C-t|lh4XB`p z8&aqw@2DJ>r4t^-`@`C?un-`}5fU^a_olrN3OX?Lf(&&K!f4PUti@b2s7}tYo8&CR zCh}-3HUZ&1Qh$jZt_5U(n%5!F# z>yO&~<>0@oT_iLZ81X;Z`A6;kCqe%b|3BfVt*VgIDl=l&0~Y?B90a5gdUjiAg~T&N zkLxV^y-bD)x_tI)4+5Q>O>>We^d}AU&bZo~k2PfA+th#^|1djpXXe}a1+(DC@+M&~ ze^-?RzD1bjRk!|2XXl;Ahl4*GGE?v6MegG6g@eaygVyI*phMEtl}l%YXp`{v^=WD4 z>D%1h`oz`M(D86)#HhX#)b`$LmeB)4)E5zO!m z4wFyb*yRVTJT+w{`M)!UDm9`JtAtnNRjY`lqGln}M(LPK3*Ob(c_^;wCe@^mxf7e9 zUfhhok2uNyWRm5e0EBnLm1KoR_yQ(Vi}2lL=3~u=bxHy`FbeaiB;hV+;0Mj8s3ABb zF~5kLXkXo{UhUJ00yq^OSLzrl*;;N3g zeNv(Y5ieT?gs9wEG_0s|9=5~D;**kBxS4H0;g;`Rz-xPP^JNfR3#ixnlT)sgNbPfO zgRb4yecyEn&mA0@BrDH>r;$>$E?6~a&``g#qu`DIreTv)HQe6rsI~BDLRes|iqjF8 zawmI-(sORcQy`!+FRPtU7bV%FD1*Vmhz_se~R90 zDf2PfTrJcJm(k1X$=DfUd_)NNVw&Z|*R(dyad=W3pn@{oP(GMAX6XSYh5P3LE$XU~ za#svXWN`$vD3c?4y=BA7r0+Zj)T(Saocxh)>|hoF2nJ#EVEK;9E^%pqPV9vftU7cK z=~xZfDY1&Dc*(a2%79552tND{{ATXoSrC(YTS;`jR3~#)u=PK+Usn7(U*!MXA^Rs^{>MVo+0@SD|7Mk`H0BiaSAFT( zFWSZZz_a5-((jXAzuMyo2Wi9O35(o3BtsyNHqS*;)>f}4pABud1@+m!&>1VSl}WW$ zKC=jRIC)sgf#-mC}=}Z8;tn5jS~te!!}{-?kp0T`ICfSS!%oy#gbns)_!Ru z(vp4xfqADo%TaoC<82{eRX+jT6%didC75}}EtxRHR1?P7)m)I39I8cqB;yG>c9Ip2 zJYsgyhF3HIMN)6k zb}@3Pm$}Jm+T7!vuH>3|!}zz8Ssv#JolF5kZV_9_fgpC8nO@DG+tO)GYe# zEoF?m`wNE*K5Zw$%$R|Sd8j=+-^uq0r?++1Z0EBpU|3JR)bhl&8q?~A@c8Rqk16*525Yr3r(JQxu1j?pmcyv4w8I4}6vLR` zC`ShgSkjsjPRqZn9xmr_BfOY-hGCGrp}z)wH9le@-qc_7{P0-;e1XeewS8dfoO^ur z?dAV)d#yhkiBH_Jxr}`~J#F|xh_X8Q_IP@CRe$DII=6Z_wBsZ2()hglGA0~m@%`ue zqP+e_j@%b_AMcejc|o*M@?lVecDUCLE+KWU@-`87u+nFV+N6XTmKLk&dm4T}$0SN@ z;1KobC&_y5lTzEUn|nl@4lTJ=0H)u|%M!+JQeRqpr^yn8w4z6NY6jM!+!De*{^lHSS ziJkbBOoWhPQpr%`eF&tzd#Zs8U$S^q($7M@8}8sclN2-eB#o;fx&kI5jbz%nbWj1$ zI#NoJN|DSCDiMH69c?8o%PN6+@F*p*FY~yF30j!O^gLWy-$Lc~wdS0WGzC^@`iUl>wM-6Wp#wSp}Z08{U-jina zEc`*6$4n_^3)^w=$+%#6w0WrNrx7=W9cfULrX-6n2P9en|4&NcffOe^<(g5m2!;*V zfva!PDpjk2Tg^aNV1U3%C&rJ#g`)%9XwK&Q)|nqQ&mjQ25F4dVFatG2`Hcm;t?gmQ zW1eO>GNcuP14kp__=NzC;qU=JoAvpn$?eoL+n|ZpvXFZ>ir+QuKY85<)FqTfB2sHM z9~Ua0!d4WpFl>kKj1DrE*(<UF? z(k8RbLj5J5ufg%mF2cA{N!17}S7YJ0P*HUr0BN#+a>qAc72!BGt@^zKUY*~2w& zM0Si0=81ZlNaMAW+HB+658T)T<8OlYPZRIHpbl38AKUZJnf8gP<740D@@kyY9Fok( zN6UaK$DrozR##>T`VZ63S8)9#*zTHN9vr;{{Z<(}L3aKta#xFsZ-$+oUfOP#z+RLo zlvRJChfqs@xz9|F5*t4_jgh8chwt!)w(aZTPDK|E>@B z|J@+kSeje70Br3|O#hRWLv_-+To5yE$do&lEYA$YVlLL%c*o!;B5#;TJYCDcuX#0~ z3tQmQ?{U#{VPS;x2OpFoPnS5PK(E){fb zR_e+1`BFY~*E6d(_kziv|E+C#h*mCxdc&8WpKtAqD3|EceJ<9Yh^Tk{Eangd%6)m; zcY;gB%z5WO;}~uW-ChrMzeJgv10D9tAAT56nQZX+3lNtwadpO42$k|$!%KF`Qc@(E z-6n|~YbFCRtHwQ~$`*{Xi$e9ZMMRZKxFI<7faP{%t~B!#GDDGRCLn|SKBjkI4x+vB zcr!??iXGSmvtSfMDUm8)jWh9TK;a%9Pf(PSJBmR`7J=w@kq2`*n81@rkx2c~G z<~(;n>pef*zw^!2a>Pllt~y^j9&d@ajg(PLBRFG%@ZmdYmhg|lFMNs(xK-l&rs*oe zi+XTc*1@Fg>LS4rblQ18W0Xk`Tth9OWBpV_{b2gPVVE|W97)lnu-a-?g|{U_Ka=@R z&#FBmW+^%AB=CIZFh^N$DmpGz+1x754_1i8W++4$l{PVV)p2+D;t?h^gN6{7N8}?u zF(M^5646S;m!qm%teuF)cTO_G9(b7oy>Qe#V1q=cN?6Imcr=;bhUJPV;lrd^xyya! z(JrftVw=so7udtZ#|f>gh{@c^Vn>Rv?Pj{R0)mk=>SN-+33RjKl?$O5#LwB-iw+M?G=eEa zBH-#@290Z$ID=Qi-SbqtnwD&Dryx6?Pj1p7(hH+OX_A+dlnTTvZFb#X%F-~V?7YRg z9JTe)Hh;=Y+Az2%JjlYgy1JwRmo@QYTB`}*&Nqhy@g?iPC8HzSK5?gagQ*^kp(Fe; zuOKXKe6=@u(e6IFNTiVIcPKr}wTNery&Rt@>As!5$09Sin0$9;UEG=-vAU|k`SDCm z#Bc}ZYx`3jO7EsVd-)=+i`0Wg-d@yoUyaggbYCBe7AaTa1N;5|A&p2Y^6@60cO-Q5EfT~_`)0tmE3pe5Hd^JBi5L3sNs8VGP(C0Wx{1i z>B2AP$M9nqVMvM01)i_C{u^e*4tN?|ojT9qQh!O}ryhlEE4%iA!8`*MNcCXo z2eRZP%CZska97kUy3s`GUuDDOe(1Y&>AM>J7IyOTgzA&tI0AvaD78$qb0MOAe>{{P zpB}kn$Msl7BkjPo#cAK&xjPS+{&(P2hl;#{ZDzxg8_)6TrkOj8e{&058?pXUPnk5$ z6~Q9{8qFl>sWX``Vn*@|U;84TS6uhYV~F^X=7EBy`nyE@hi2sv@n0Chaz$6v{>)5& z!TNU?N&c)JsQ(*`|MU?57f{-&$|mk`qIO@_D)1bJ*)5iIXryKH`a+C9x|zpGsw=y2>|3H_5Ww;@mIzr39vf?8cgLZU$8 z5AR2@Kv!qp-23RK`-kh>dOPIB(--;5`E$2MuKL5V)n8~c@ZU3;as_&Obx;mo-y2SA zH_=APhEF?|x$6h}2x2&g#sLnu?YPKlG~%+rB|5#6LhI|;!aZTmEL)e+LK?S_6-Vt# zAAx~jqLf`Xq~H%XeD85?HD(o)3#^u(j0jy>u9R?-(Z;92%Dxl?1_kM1zFsv0XbWyu zZ()wHJeU1$XO}3Vr0+W!Som$HOr5(MXFr3)ZN@KN9$hrK3QpIL)i@7u8z z{TA=IRKQPTPxoIJ{npoz-&_UziDTa^d%ZpNxl%!brHjk=xrguU7gK@Ohcql+R=%gU zhC5XxSnvnmhrFm~_@ai)?va~@`jNY@7SMRHtGSs>12JB9#9!<(Y&!cGDeJHRk~GCZ zICWl%uq@3HYz0u6PB8_FQf`QZKZL94lC_dB@o&FULIic?m7;eEqemAkJ4sjdM;2Uf$ikO!%KoZM}z50s`iunvsQj^ppzS1?eI^|z%NPMm4fR; zkgKyWbczYw4s3_Z_Gu@yrQn6snNKq^{w`@Rs56;w8~AmHyWP;^hbokc>s7?=f^e?z zFqn){BpDGdeR8lI_t{x(w=o(}$c1m55aX&&kjH;F&@e9_Vt|#0BsWSeE`!>1fS>Y$M|KklPwLd&Ex_q+zJH zV262jG(0Gjsb$J?`1S!knWf^izgk4DW_Og}i1<$adJ-uYSHuiXwdYgQPrA)m)@zW< zgI<(<4D>|Z$#z>8>ARCW^KfL>vvdcBMm}!I0db*!JW1J^RN3KGdj)xUvxN6}JNyjpnJHq0*S@{*O(X>VdId;cB zEF)E(_9M!=q?kkmH}bv=`|6v-EC``UyN!H9DMZ7y$W>5u?Q2ydt4}sMNTy`HA8&># zNmyL+M8ZI2Uep++r?V7cO|w|t90EiyZPh{P3aUTCzW8`qpFw#{mHz<$D*;{a0Nt2B zHsNof|GNal{ki+!V}!o}{r}vT{J&5DUFANzLT1$N2YQCf_F=Y``f{ma-J*)n369W> zf*;UsnqT3N&NnY{jq{S@_(5g|6OXbt9^Ki?8o42Khh;pKzn*oF`g-Q~A1hx*+D#Jj z&4|1!GpP=37gMr)U#(ZHCo2t)h!ac*C0OWYbSL4YXfenRe$l7 zOPl?mrsItSxS!!t!(!BX_6Pd7L{umkm|+d!1x~}CnMfJZ47n%doqL6%t`Bi~Z>RC} zR$SrVy^-$A8-JEB2+(7#aPK|7JDwzF$}9CoNoYKEIDSvDUPoL54#78mm0eE(isXW% zA2xD&e)@NGL_f|hqqz8c+J|*_CEL0eWEd+yY}Q+rzYi5L@+;G0`LWvUdQ^Aq$ff-r z2BXDDY8WC6xB|#cdjQhLAV}A1zd%B3Zp%|MRE$eh$x?5Q-%fI+g8O=ea2>1kqJTz= zxy{JOv$ulXEMJ91vIKM*9sNk`;K}2;d?m=1L|QJMG;yHMidsGf_}1TG{_+H*(^%g0 zXR7$ihJWXYHN$_46&*~SobBxl0hV^g_U3k$F7|-`=u3<9jP-=I7PMe}sA8Q&viI*Q zNs(RQ6H8j^;w@t?6cX~e?{bNaofy)p?J~bit+Dq4Ag8%~pIwaKoqT+VdtR-K zn|_TSyKhW_Zy;cAuQzDdJ-6TNW5^a1%eB3Wvg!N0D&O1f4RZKsMQJ6Db+^y)d%HUn z?Dc&)o-4gm*7JYfe_J)t?`?kQeLB_mdp}q#HK=`Kc7}Idb@Oh!YX&sdQ0}EI)EDV2 zpxw||>o%-MyVX{+nRLcvu9sPBk+~1!Ii6; zT#>KmvGlcY#CPbulbi28Lja4H%^#=>x)*vHr|PR%Yz`%EKFz(o^g&pgL~)!?d}GyH0^n>vbF+D&eI7TVn~4F(~-nzFPEn<>Tm!nBfSv}l$k2HNhI!J9Hy zZgI!DGQwcuo4G`BT^M$LXuS>`$5E}EEz`saY3@Sw%F;cZzk50cEf^f6)0(JRI@4^a zI1qGwO*A-G)IOg}8|ZK+t$-6-6=!O8wmTrm1eh5#g{McfC%o-m3Te9!cs_tKuij8v zS39}C^io$A%(ph4L6nmS}QQfzi?$}*_@EpZ4P9nL>08ki+jle(bH|^vCa3cmOVH$1Rs4z zs~xo8H_J3l_yE?c?xK}T{mfPgwJ}t)4Vy8xTud%ZZ^^}-s~4KX7D@uh_CmFS`F$A8 z4=x_fI$T3WI|6$YBnVG~mMTiU?mP_JEK&@8bW071`UQB0LRiQt8^aUNuCFcw2Whd( zcTs_a3e5nkG+NNv0$x%Lp8YPkSHE2KCsIAmb?x-hEDrr>GEL7?AH1Zev8rHH?mQ#0 zP8u)FdQrToHK|l;rqoQ%J_AiR*eN@67Lw05faCt#y){QvO@pm>GhsqE)&cw`yxAPM zxaLv)!#o<~h)JPqP~}85RLoKF*Ib8si+%8+M3()fUCHqPK5;}_Ha3_B_268;ce9V} zMgMN^#*$n7b~vSxgW&XU#%z~oY3;~;{xC`hE&N-8ntDtEEOTin+gTzg>zS=>Vg){e z5&hF@%Ti5Z6}qn@XW?#BfbZn=Y4c@EiH;tFue&ky)l~5Kz1bJz4G-9v(PbP{ zrY_h@ib(q={Fz9t5Fe~UP$V+j+`1B%$S?E0t7K9_nrJ#2o)fz8Y0DLIMyuRidNtque~QX@O-2LtIRrg9E%c}yy3=B3a-HB zAmS;Egh41V4h2B?@lM*9X_&l>UDL>=fKIFHkK^t0?G8k?-Rp(R_aPwjQ<&-6y`cls zGtyWPMD|~As%uKcK$ch4soEUs^fsIqCEV8| zsQscgSp3`M+OMC<$gh2Y^d~G^h<7RJ1~tRxh=GcjsES#gfHDSAGWC|sP=+#`C|N?( zx6DsR0gUieY(YW0;~~g-0tQJ!++j4~>V{uz^Kr|AlEIBiwHd>ke{f2q(m#=7Pq2>s zE=l>7Ls2z@F;f^d1F7?SfDXzFnohfep^Sa>o9qd05(h3xL(g{-W6z^{61&PYOIXaS zi#QW=C!@ZAd3{Rn%(84rol`vbg}Wj4#pQ3XQ!)lM?Xd8=Eb%`pyUk8S6=iiHhxdRz zn4W}0>!?aC&?CyUaW@^CxjKx46-wh_XWSRLdynJ7fpu_Fx-rHrFYpBcVd4Avd<>D6 zHL!NGib6#3ib5{buYKO%be1e>2>Qs$PiwgIG=G*6jr~%cc?fS>O3KHS`|?2vY5gFM z1v1(u+M%sV!d)+~$n`3bf}CMs#M|SLR%Aa8C}9Xp)Kr;K9L;Zo=BD;RDiIo^_+DXE zD2YB!5BsAZsHO89pJ|0qF*X2$Y?ynF^ed>a5}*oJatN+S40Of1Xmx9JiR*(Udq-I= z7zwU$(4##ayx?t-#o+z6)m4THIn2 z1K(KJF3%M%u@y9j7xRfDI;d8H>U9;}qESgmw`7FgDld-@;dXHA>+D?XhuT#7lRTeGJfVqKu9STg5PS*Lq_7^%Kx*eio6kW?z(;=rC= z-6)K*B3f|NqJeC;0Z<|_gVkpdVx`8wH0hy%?%MC9bW(4It`)`Tyi^eZR3}RDXP4bW zdFJaEgf4=$S2AXP(RwvAy-COk5s(7g(&5~y5Mw*02)}nrWUR zwRpn4erEpaj>6&vcdaWdIU)%SkT z=~*Uec*tdfCu|b?oR{k&PKRX^+2p3(QA3^|SJ9`! zD0Dj|fTp@|ySL))Kbj<=>fcd?F5%WT>j2D@%cRIRCy z=kzwHYlkfJYo93HmjE)1cE}lsK@Zi+a%^GniYg^aB%W^5c-B-QrS8PsfC^LzS3Z-{ z%PswV-F^R08K^20ToDkN7^G{^P-UV&(&e3F%GS7qq!&ype(j}I>5W}f2(Ve!0+^nO z)S*Xz5gw?fYj>q^yD|&g#RtuTjxC4Mqm-Gr4C|m` z#v$4G8AZ1~^S5%>B46Qh&N66tX5A{N_mQ6%IQNEPzwCX3nfTd)4|iTFHCfX(j&)WH zEGW5O+k0?*wN+?3T|E|_JzAId=gdX@6NT@O5hcbE<&Qf>yzY?YCRj@tV`n$4iBto% zi4}K7)RV&tX2tJZZS%@cPACkVbhqaa24^a@mLmm!2_-l!>;!AFD1>Oa5R%k2HJWMf z!775$@(NtpyTBH_w!kDF8SQ_*l#XpC~pd3CjfM_rXnBIaau-OZIn! zRDam?MS>qONS{V50j=LIRPfESz6aLw`I`pr@lVJ%AJs?F48GMV%^e?f2?dM1*0QQR zprX6JzitJKnO-)@vg$(J_#}aTUh=gnB!%XxPT5w}n5dF9p87Ot;A+C@3EhZ36t&QH z#ugJXk|kO&EHtK=AF12kTD7Al$u!O{2f8QRROmMb09kyg2)De!(`YoP>4bmqBtP!E zWoocG6aK)|>gbL?8N|f!l1=BY$*u^NN;i&&y_v%nEwmDzrBN@mM~3+(iYNaROScFe zXRgHgBmlkK2V8%jYJtMa zWaA8DcswR+rZt^ONrd05!xFj6w=yK5N=<* zjRh6NH~eVo0yW3sqeZ(ti?uJ#A&bBD`Imv-Q`C&}Z*S62H%blaj?VTGpXnM3;(I2U zTTj|6{G^MciY*9S!1i7a6)JqW4TM&?$u55KdAZrsPkaPt$gseB2ziQm z4D;(kIGFOu&a8+mfk;2jkPwFTMv}mGu^Z+3U+2lBh>9obuQuFahJ03#rtu9E72&ZU zf2@RvTOIw2Bd8tSXL!lY;?;sp8XG0xwrFxI?b2Q|S-r(HWk zhC}&*oO53M#eU%wY1J{u86nh&)ZhH9boASY3 zZsu%HBZ~Ij`NghgXVe{&GLs!|`{@su7Aw&n>?1hsPgfYB^UD)+*6ZEzV+z<PIK@NFN#e3FI8a6og=`uB=EGq)&>D#8>Iz%yIHux&_3 z44=`(DGg8EpwaPjV-0a5QE_Myp4%;vG_TpbxSNJe#9CleAmzJP8XTn=zwL0`<_*f5fZ_Z#x)*$cx;)URf*N^rgmm- z?PWeH``kiE{aUio$tCFV%lIvtD(8XiNB4z;0NCrVym*1RSTO37(+u2x2Uvi z503^zWxL9x+!!W^MFyC4=7Q{r9-<+*dYDm85-+YE<@ogFGBv8j`Vxw4cNz{D>&w1G zCWy@~H(OBOl6<={7VsM=CM{kdp)e| zEKD-*#G3e~#Qu3h48*Iou;R6c{u_H#nU5#@qG4ycyHoCaDlg^JeR!;+3FcOsB0!N+ z_ILHo&P~coy_IMY2m5+O}tr7}}=)>haEHQSYrxu+h-t05| z^qs<0QiwlcF8*LNivdolF257cmNu9wD5Ysit(~bQL0*=f+-~`-LT4G<1Bb+^S%b2J z>;|$-arJv*e=?001vnZ#%UHt?`l~K)c{Fa)+a0T=;=9EAC~dA7PQr+QjS$m3rU}%q zlXf&KR=>iAp3ym`+g$M!>2kc|(s4xEjBb9fH&>UP2Y`>euBL9!h>Ac{z)?0_kn(Gv z*|7Gm73N0A6yJd3KuSANH5TyYvXiDd$G4Upl^>|5eO8tX|572)M!v+Uz8gCMpVz5pR+*4>BD3B`rK*}O(I$o zG9mR;Bygln}Om)EyOq)uU&VlTKoS?+f510ir zgx0W_6G)hE3Q-u_l1?;nt3QTAoUp!k4sNDXQA!ANv~lN3cOZ1&Yt@j;X{4nExs7hh z0l!^K1^z zZ9ubq#!pERsY*O9Vu6ql&MCl%MZ*>fVMS31W25Fk#7;teC(>e) z8gtQ-v+aRh2xtBtOvv2?q0PbB1H;T{eNbbmx=EfD!(D7F5^PKXlLw_wB+&=a5bpM~ z-&RxNZ!jKrJ`Jf)M|+7sA;C9(Pda5h;>?8G8#7w9l?Ikh9MXAgYeSr+`EC*V+Fmse z;xUtTVkBS{9S(9<2{##0O=obGbMtLqVw4B%_Quhb{&4B)&20?iCY!zqo+k9^0ux#< z}b>cF)L)^DQOa~YN?orjA}Pp^8=f9^2c@N%gy@z=9sK}+wtc4 zR^hhWZONhA!S0uKXtFNX{?^V@?1?>U(TdLFUL5tf%$U{9M^|RQ^RU*>?=SrXW7c>f zAb%(QKEjoGm`TaJVInw%o8M6Z_&?(@s?Xm7v%5k$SYH~ zvD)wkw^HCe;7!1gq$|L=#fkem!UUrk-Ulh`#3QBeFjo|QeKO;8`_teMU#rBwyD|7ZeY|a>^fDKv6tq(C z*+#81mTIIcJX0eOqZ8nBN~9QHjww%m?C$^sArdBZ4r`efpYJsUAjZNJ+Ug_Vy>QDH zjfixJe0H&U26s7Q3!HPb{qlL{*g@Vtv!@cq#|%kHI{2i-rzmc5*CCDuEdfUK!0<}0 z!9lqOY7doyXlK72Bc8;2E%}AbWV5#C7wB?7ydAx5eX%y4qtdt+n!QnAYApBEfm9qh zr(qnXAsDXOckV<;%jZV;?&kJxh-Dr||9XgRUUt!Sm{P#kPj?^K>xo9U)*uT>8=)1x z_xe)gL$=l|J^``OO>ugI1jwxc4VW$VQl5&tA>h0Og)2n0_;FJ=nLp2D9R(Y$qLc^) zkY#@KiH>XmWAnG)CvuyM1g#}M2AYdX`1c;9hb#35!C^-;O)(+K>=Chn1rByZb$x(( zvP7pW1C_gPWS$dZh6$c;!4cwcyCm8`-XO=k zSmI!n1swy4B@owlD$#$V6P_forQU(31PYexk>3tPmA5GvlHW+_mD0zsn)oLjG!-yj zmxY;-CfT%M(-HH@wQXgDj`IN^<=2Pu_CFm@Lr+A~HvO5P{M*vLE$g~0N`+1*Wwp97 z!Qe9SUiCS<8w*-N?XLhJmzP!U>g-|4gLQZlag+~nHK3XqK;~JHWL$c5qOEP*IPLz$ z4HBYX;=0>lI{7b%YIGTSX;G48EznzOG)`i#yD;3{;#%U2i+49J~=ebsRcclRW z787xbgIgN&OAkCVueNSt;63Rti1|_Pj)#)z+FKAz1FU$xdXiw~Ng z)>Ctki|Df{Wkzx$6xDB3Vk!#RrTQ6ve;+|m3~&Y9r4b}T2=tJ4fQ8`nXJ;H-Rt85{ z*Qiv~jog^{J?b2@K{0?CxR<;p={`I3`>Z%QT%&7&fNV(#&*?!u^j_cjDKwv~z%VOI zL8wPK#4v#jG+d&}Y1ihwt0<9UQ$Y*;p-ourc<`UE8JButpusk8TRZ{XSJRqXXzLi{ znK9ARJlXCxF&0isPe*>@$tg44&MhIHU^1LOI$)D8wpSD5(gEVd(+Eh((X;{_5A*B! zib7EDK3?mM%3$k~j-P0TjGUAEfs{Z*^_QpyvslG%HvHw2o~`;6et|evP*+XuSeeRS zNuz`-dNCBn*LduGfBH@$)Thi>4y3({?+o~#Wotok)tdYA)A{k!Z4hBSXmUvee>h-% zz-%A-fBI`M_9Co(?-9Vj{@RFtHyA9)pTIEx`Blz;9cKSezNR|wmThDQIu^HI>MPz` z&2>+k4!a+uk+3yTAmKn|4rv&Fk4BUYgp@&*gdkCTe%L+aiC0bcBn?ndUjNMw$JVpY zMNYmuH?ThN_Nea*n(FO&dmq#Hdl`}-zG+|}w$t}{->>a`bSr&-8k_R}Xxw}slORr6 zb(+hydw;3zc|EC&6?i>p?R|P3IM;u_uH5ti&4e=byxqHhEXw=cylj5FpFixMx9Wd9 zQ`0>sKK=~teP{B&`_tE*>?>$K^-sgb+Ke9R)zseCqk&6-mm984M*mA{ z|J>QxkDit?4&Pf+0HAy5(m#5$8@PG1ZU5X2*tcC5So7njf4%H|x>>dOCFl!!TKu^D z(|YLeW6J*hg)8?IwCVG*y19Pq@Bb9J>36qUEBJhc<3IKx@M_}!xT^nlk~vklc|6d* zHpTfS(Vm;7UE4cu_jb`}-`ggpFK|)a1+ebEYwoty?rpX0vh`dO*WO%c-qbp2onh;> zX0!(o?Z2i-b*FZ8C)W>Gu4+%*r8xUnT6Z*;(b=v7qVs@lcSIleKJw*Vw&Y^2r>jc# z?BXdQAZn*v4%()`)(uUkb*Kdty8Yok6K$m1N1QWix-uj1ZW`WIcVS z_N&0uk(dMM6Qiv=rXBN3JZag8Y*ni;;c?G1+_%Gi*#G&t^5Yq2vpxNtpz@(zTv_@F zAWoX>*> zw3x45y+G?-%dlYg5Z@8K(69{>AP9S`Q2d+)5INjion1S0``fg$w3^9&tj)H*8iHAeKYW8{!pB~v2}@$C7bd`iqgYH34U080r z)6B#05spl)((WG~1KfiIz-<4*6C!O_?Pd&+Ekiv6mt&KL;Y>&k7LGQ@3hL_dg2b&) zc*(HYOw9RC>}iE8jt|EXK)mW!0x?+4j6tLN@;NVZ2Uc1}(LR=2!AN8X9#J5fOSSiR zD+dsKvQNU8QhcrnN1Qo#dF?RgB{CQ5?Eydf<9gn__c8R;;`i7)MraI*9SetcRWN|l zZ6U@`dQid$(6q2y$YOdd8H1fg4OBRH8NbC}bv?bduZzPiLI;Xor5co0b`k>zvCmu? zh`Jv~us?2bksQ~H?z|Y^kGi`7nGd_OCxz5)jVruTk*)-p-Ba~atwbWd(DvwTfSE7> zqw>AiX}Q?O<9fAdXE~OU`kxx^#e;}pmq2*`_wpVXnzfAUKE{-+jZhkn@tBrHF zh&aTevOYhfeqNn$S=M$ zzdGMF!69VDvWvqncu{mvbX4AhU1%~yhCFfWS#->OF!4=iWymI5uo%@INBLuf?6Jk{ zi1Uq9OovPco%MW!)j`MVSWER`xWvGW9CX`RVbHGa64(V}0X zLv9T+mTVqDTC9yd_y#rKi#kTv?_fKR5FU%hqf3ZMNpy@uK@{(0KGzA=v%m3tRn^p0 zzcs8Qre~3;9mAFTC-dLOtB8t+urku};3N+bafJB0_UP`A$gn||s>)&xB}&GDUPpWE zFRJrH)eZeo(pHEaBfeC1_O&&3qUloA-x%OHD?>>2N1m@nH8pl^{9fbF`l+KYxKUf$ zpJr#>BM6nj*6C1h~4bv*R>XfK4dcBF>U!}+D zeF=$DLl@^r6f7}R$pwoftrBw{!luR`IBbaRF=CzWzFv;1Qf44S^oXire@S;3I!am* zUG*xmV4S%@OT~d66o0;}n$p7JsMHj)Nt{_drghVxhOmO{v+5L4%?rwtbVz^c^|Gpp zJ*sm^6~$=AUXt9o4by%U#X=v@7lJJ$@uhe@_Qu*C`vYp~YOdZ(+JtIs2w0E(K@?e2 zh4{Zc)%Y!H z?4binN03IC>SKRVRmARY{#N`sG^;pungjrf#S(0+swARoC$t`mcIDyoP3_7pc7N8c z3_cONvd4_ADmG%)LrUmU(sF!bwR))*Y2(cIG#rbL4Y*qTky9*Ib`uMFKGG6o1JKt7+pj z?P7|Bf*aEm!;*9a)FH_v=rmb?-_z#Pp&pWbOm&Mb9~0AJAyY_7c-1qR26#Rs<<#ix z5ck>NWDC=(SaEtUCCUY_gGa~4iKSO`>cS>sZ9*%PfR8+$Hm8I zSb{jv&&5wZi4VOY4r@f>BoNIeIF#hQCW;4=ETUkrv&97$9ap7kM`)x%KaB4cEp44t z&sUk4q~GxM;5b>#OGl^Z{ShO-p+3)XPv&_gHxF!lY}LsF3ruE-Ar)lk`6ji*h7?Dr zF&xpN8a?#f@OKUh4?bV2q4yT1;w?jF8KL5ga{Fp5vk)+}CWkoD;a%0V3>ds#jPXeo zb{@i_24CB@O8#l8V~$Bm^D{Vi1UdYO4?^t-#2aS&->D{{yFh&ETX zOKp+~f;Ps7ANvCp$(p%LlVleup2xO&frW6QZw~FF8b?THk;e9Yyxuhbi29fiEn(N8 zy(aln%OPG3fyvTo?hIbuD9?*5(1cLI%&@XAh27ol~BW(bN-%J zJ#^&%{S1A#vl z3}`Jn=t7~W=_t{jv1}RB+a!ar1NRrji9#_$YDJiru-jdz$-*4Z;w89OG&7`z5j8Fg zib0(sZBGbbT3kIQU-FFa1mT zziBDQtW9zYMmO;%ipfSGF*&wNS|s;i3WjbvMV_y!*Lj}mV)n(wHWzCljAY2(ijR!Y zS#>BfJA}$DLC<1sVdSQ?*(BS=ru52I^no7iTp#djs-S4;^^L<)gcM#$&?|KJritd%Bw7O% zrGsJek=M(pNlC^pH&??Zy|JP)abcj>ICW8pGIZrLev$EzTEg+6%QcKhYYc1kOCf>E z5Y=n89)>h5(Jwt-uWELxR#wCA66GZihgh?=X$6f(S~A*+F(cyUEkx^8!}NTUp%IIa zqQ_8Re~}(n7|-ZBS3sKu;3NTc_)2I^kK@a#DwK`hST0FQz+hrraOD~xG~qW1cxjbY zEXX{&y}!xmNX=X30Lqlubz`HxbK%%^^ypMrH1ZqIJB{;;%+bKAKUHGAwCz36d0eqi zF6fnForOwTV?ySus-`mW!@6}#G6QNGmW`o!K4cWt*)7;Yu+E0XCGP{aN{<$UWxyzh z;?Dc5>X5v&swH5&foUMYNb@8CktZJ zeb(xa%GA`Sp7kus6hy&Vy!@g}tWK|Z{;Z|9iXn-2Y`!w-Q%#)@C_;NQ+slS7p)s#I zAD@p@j0=}BEewP0)Y*kG2}@#a4V_VocrA5g_>13z!D7_143rZ*q{q4q#Zh!+9U?(@ z(FwZ-a%OrQU&bIo!#WjhQVcY|U2>dmg+saJHdY#D*19t1+5DmTs)kQ?_O3p~zLC9S zNMnQD^MI`qje=|FwzccGO&@9HD5gboXQRTXS?>t@gYSMhJ?An zqg-@u(HLhRM?ogdUW!g??c@|pNA2BTMA|`(l=!kCy2St_G{czt7>SZ)GM61Rn9w2} zQwk1tQC_q~6k>w2B&&EgM%(^P($$ag@VD zD_ryw6{~8+1|NSLOR|b3`$N<1=A43N4WFJrUq$xPEpt2*hnfqZ`UImAErxZLOPJnNoAIX_Ib`uR!TcB@t4lC&dy9NJ z@^ro_9lFU^NOYarRmv{k{CrdOqS3yB&*;7odWFtQa(T_Z=-{)aUA|~EpquG!FYotj zE9dg#^tmN(E?(W7*?3*RAP!`AcFl~{wlFpuoox~a@*F#jl{!~%*a38jqWh6m#bsLy zr7{FdMp_rRp%cnKWcaGBYzRnM>rcjqEh85s-8_r)#n*eHQAylu_$GB-^V}D*#KsOD zni+Y8$$T8_iN@rHVMn(~L*-)`)ocS1pO+a>z9IB9PVYD`abl?|9LIwS%l1#@I#YtT zXi=@Y7EW06#KLmZB9o>g4l6-pJ}()Tw{VS^GCn-Ivfb((RVp+v9SbXM$^7oyx)bZq z`VTtm`6O=b!|B*_tjfDxv&o^zX>aj2O>KY*$=c2`~ z)jXiP+=xW$-ciSQPy59(bo9~XM~9x*&LLOoRyEf&tzH}SDAOwD$J_q6;};nc^bMnb z(zoRIafhr4vdYs*CQ>OELk81H>k>=ii~JhPW+tHP6&CxJ8A?f@_#sY?su|eg=rCs$ ztMy8~??2*o)^B?An$5alXX$qy=eEtQk}MI)uS;8t*QIQ+7c9k92~hoRf3Af6f3bhp z8heuaf`Uheyi0W4q}YlVp6Zv=;MQ!w+)O7Hx)!1&%UC#z zSjnn}LYK@!Y7qWbbKNmEy?c@BYG2y-R-cO)dXmM|GM995X)`g=em-D=D?Sm>z0C5y z_8Dz%fhXNBbiI@>m*@FHr&+%5^zA$7>F#j9ctYGxbi0t}(o}S$^Mx*#@_jxprmy5) zeKtMzuP4*HLvDHdLr8Rn6(sVm>(gvm_oiNbrTiz>YfCJF_k?W3@(Jfh+5?Wv#KOx38>smT#3> zn6-$t`9j^3EB2;4We!<9B(%8(n@?9egKNLObe|IP1kM^!ErF#Y&&vr(KFGzE7M?GcTeK9BQ}k!Btx~xNBZO@73;$5K$hNk=FcVkrMyRxLNW$O*&5T} zyVTcJymKVVKRC{6MFOx(Wc>;8SF{IbsOP~Q1U+r>-nIOp-MTpl&Yq1Q@|(G40_`;6lye(&HC>(w;!PYkn*@D-Y-6jw;!N?Wchk2UoX$gh0d4q=f{1Wbe;5G z{iNGozMFo&KTMZdKAT)-b=j{M$6RkxVYp+*1^Y8svovXnGE4^A(&Pr`=C=&!`U<~SI6yt;U{LMtyg9dX~~5i3Vq zDT}hJQT`@x!J(DZDnhRwXKir#9%#5%`Q5B)UACWY^j<=5vy0MLRsC@1qz~J=*mTOs zS3zENH-=V$fU6_n-ue8V25vg`zS@4b>rgaKf;bU(m3twLh($-^)h^+oZJ)vmpom99~d-CwTSGZG=; zM5bwt1+7VwpJrx7bmAJ36@%VltmguKEy$}2H=aFbf9#9vb=M7}VmKGOPi;6YjY%Hg zwZq5BH~XCv_JYy1w9n4iH8z&aBCC`>IhHQm&*O3qeR`iY zfAQA7I;+b~z2j2MB{rUq{U&2k!PV*XK9_gJZUtS_=gZ;lJ9pDpPwcA?`00J_ggZjE zJoY41r;IULQf=3+lvlVsN(OgZ`?6=F&W)S%KJjmyIOy`r{d_=7RZ{izF2b-cDLi{7b-rjOhy5^`R*Gn}V+AJ9 znb!9(6AqVe({Cg1&%IL8I^Uo5jZXd5Tdfnp2Q9Tt&TV71r&^6GX_i;49p}J&PHbc> z%-J2?+-Q{6>f-2>UG9Gk^w!m#Sb_LxNJ{aF=mo>qrmY-XCG~FaqL^|S z#l;#V+9`@&qTajkqTvhVn3E(<2;C;Vx&8{dXlsaUR)RK3ihO>BHfLf@LXSc75;{cC zo!a4>B7rtY>}cG2xyunP!B}@T^hSe@isd7CbVuxI?9`dqQIZ!WF3ajCZ#xO~y3_Bg z5iiQrxe6y^6L?O)}Maq$TJf`%Myefo#&2C46v`m3O;tv9T!3>}n>*j=XMaBKSXzMSu`k%QL|!3O(lI0bZj=ok6YD~SJH z^JN6?e$M4=fnG#mM7xN!PxYa7J2ltUj6}bCRML<**^}AL4BY zrw6*@UF_##pLZ@Es=Kq`@~jybSP+LPQ6E?~--SvZzwhwHSCHf#wN>#<`kq)Wv5tzM zkSHpp`Wh>#s{|>YQo`l1r1J;07fVAONPhf-k}V%+qST7k=jr1(1YRO7uOXGv-DCL` zuo)Z&)ho+2L!aKKcjutXckz`Omm-DSS;_C4Zn&F5qo7ak6B2k1z&yuUDz36r!qrA` z97&LNx#0w$d6T$0;CHDtuM- z8tY5=>v8DyHhv5^&`4;kUMN^GbcwB2Hb-3n6QoYmgn?icC({rP1(E6gK-R+;i7Z+{ z4(~!tahzKS_TnBHe=M%py@6Wu*5w5gDMvi^4wc=^{Ze8hlhj0Rctzz%T&Xb zB-|eRZ4j$;jy#p02L?lVBgu3mAPI~U3sGFf<`cvk8LAYfppZmu7A~W0? zp87^?th}#eigVx+7unoU7yJa})|$9%7s}Sa$#}ulrD7s0h(O$j0}95)HJASaIn!;i ztf{)pmkwHPd7bP`qZlpA3P9!ZAJ^9DUQ#^jT(=V-c;mhqr;YCG_jjSVSsl+ZUT0n> zBlfVo#g{oZ4$!I4Fz5weoJwEXD4SJitGO{-5x?g~7sy;?Z zZgWByYpZ?khJ9_;6wN*L@f-`EmI7vgS6H&AgH?F!;2qSny5h~CiH6~xR)$^9v2uP>~W3O z5@C3(KbnVr!!BNAI+NSsqO}&xPeG37;hVvQuMT)TwI=0KCyRfB=R0gvE4evxMqY=p z8}3A==*DSJhvE=E#|oC*HP*ku z4kY#9=tg*J;xtP0+}A;>0Cw&{s97!?`qGAN4C}qllV&TsZm6)8ok!*ZMleG*Ubq5x zM{QJ2#ubKHF+zhwAeRf#3i+0{D49jKq9%p!SzriDDJm;=Rv4qVL{hH-$7yx~XAcf?Pi+eM$QZN*s&RwfH zUnM?-hjlg@hlLjzr*PRZVUC~oBGi6q&A!|kxa!@0(e4a z*3MWMEg4*M(HM$as-G<^Z*f6hl|vyQVY*{ez!}R|rW^KV<9Wf>pg$*e$8p#m=Ux%p zbVS~m>%nLX3;ID_`Fb|A99uDi16o@1^6c)IpjO!}>R3TE`3}gA$_-?lmJGFWQR6DW zXj;4>%F%YvGqVM1MN`~?o|4)nEIFWe<)*)alELl$u7w7_T!^YWb#2b*t2J6e-n%Fd z-FLrQ+Y%`0>;>h7Fui_geZsC;xsl<<9)tyY0i!wf_6lHPFdJXc$~tl9W?SEvK!FeM zW?lftnQ}JIB`Fj7!VNuacn^&UB}hAi^J052;Dg=`2PJQ6r7k{|PRG00h*uhk9okoCDG zyT!O|eqFk}->)z``5ZNHUl!@eS}zr;#?fG>dA%ateERXBd7x3W_e!oXnMuPvkX?vTwceU9RK{>>?tpH5K=*LWkvW< zfA&m)p1k@wt7^3$I?pTg${Oz&O9ZC8c|&W1;f}RV29VeyEO9NTZjQp89_z`L8=T;o z@!1>Xnk&xFX*3L-^J>l=VF2@o4(l=5=U`7{X0n1K$P5Y-8utmUOR;z)K%&)v>Y+W7 zX}mByU}GmlpgSBgHf4J2y{W_2dtk1x};+ICt(- z!>27%J+SCe5p9;Kus&&>jZ+knXd)YtcO4>^W}~nDwJXIj+T5iQRdnTnVAnt(W{Gji zDF|OHcPiEQ~(;#wAuOh?1^E3%JVbW{Lx2iam$}jkrjp0v2$H8Pp|SKW^WF zGK^aGE*;D~o8}0{b%z|YF{lgT0UJWfLSq*LP3ekCVq>y2CkY4Uop2cPXl91>lL>=q z=jV#YPxc5DFF2pq8TAo`VcA)m^BF9a@)mbwBxqB!uxYi~EAORzQPMIN}tJXIWrmW@s_1 z&_$PKUqS>s*?Uc{F~w4-`RoOY>@;*7J13km;wI_M3MubAmV<$@GER4T1@ibV01Uc} zLyR_%*a=sRBY~x~ZJ0he4z+?HkMB-p=>$8L@d*+iFQ)OCk%-&n-wR4X^3oK2e&74$ z@PbbeD+e1At&aYN{oRq*N4k0yXz7>fGS2hi=j)`i%jcSo)ep`aEirGrjmw7Yt)gRV z>pqRys1n_#fLy$l2=-%>10xsb=kStm_E)q*m@Etg=Nhy4Ynrc+be3?tm5;%y1oWHc zty7$b<3(r3>P4n4Py{WD1MOx_3Qrf-OHdRW&*~!?zd625D zGi{n~wPhxX+vEe92}PJTiVwd&rjRG5v_fxr^1Oe0r5IP^fGKw;QAZ+Ddf@ij@!M0N z=+F*VD07hz*+?TIBiXc7jSZtb-b(TzM(!%O=&`{;?omC{_SO3KH1XTiN4%d+k24F& z#PE|`NZ9+>h!Gds3r3Tb`&_wsZgmE6zVPrKm%gd9r{*}^u-kIB&iW?%axmk%T5j8K zk?g808UXLg#U|{i8z2E~JuMTyWFyImI)@L2UYFfxx4d&z0yD2#dZ*bH2Y?hoPXNo(l^S)L4OsE8$Xw63j!pGDgq-IO1 zroVEtw-nykC?(mxmv#*4BjTVXDP7amd0ovh&f#ni0$Dd?3*o|G-b_d~N`T_rpjDr| zo-i_9kt)vkniQX?6@ zLs&e1o(Z^MCthI^6~Aqm#4YVmoGRZZeR`h`o{<#afhOW_dmCdj1g`jm(g$f{*pzU5 zA3&lbtl}M9BDtWfPX7b=Tq5$Ja0NBE@l&J&rB`BC2d+_3yxVJ6pC<;c=Vgz}$Wj8& z_>A#Bc0YwGfU409;YpB){1N1s&>ifLQ*gt{5Fh;}mn%7X2xM@;LWATUVSuL4uaJ@W zj~tt$tUv%EfrB6q7dh<+vyfH(4keOXTt!JO5*|DD3@{rAi;(XLcp}d1@E(ft^lgRQ zTu>(8!AZ_TQSl2P#@i88o4+vm%)Ak4il~tRWK$$6;eCbV8qn+X4j}!T z1lwU++ZkY<m<{KF84EiEsx*G1aG}xa9wX_x?SjcDPJzn)0xILEqY9PuW!<2o%Cut z@8vhshT@S6#Le-OZPL|r^P-W&3*v1;DO?0L^?1{>C(xCHR(Rvp=76^$EV&N45`20R- zK1V>`38XV9u$h^lv*AdIb5O@8Ls|Q{xt22fnPGR^G~3y(PK{8PsFgUr(9_^Oi!5N>?lMn9!k&JS#b=JX< zErwH->xJnHsPPp^`SkvTOrCD~Bp(x6bG2W6Gkt+Keut`je1FCrDsWE%e*H(2oSCA0)+4ppd7k~Gf&p$IPyEg3>8&=__{nn*H93JS_p=dhfG=vPVl zwNl)&hs;<~Lp3EtLkK{tI!~J-%ms4Ch@K#x@6gR?9H{-GHA6B_^hvL#!NL*^dWR&d z;pZ~~qLVjuBdaBJPIuGUw9YZ;VtP`pt?5WU(Rn^^lRlHWPCn7=?FZ;f`SAngFZFMi z)}{+xF0CKuzAk%j_OWnt_JNuMIqA|T?QeIPzZZi(od$k&Wh2e<#1u8@11{g^^KI6@ zKR!*ugLj=t^Cm zt7;H0Iad*&EzNg8qFL2aPbohWMo#A&v2LQp7Tc(kjWb9~DVx>m5Rh?*M7RlmUuf?V zqc(}wWj*DMJinA#er*%;e3qY4K@!1vy!!FB7q6z-^T~&*sweO#8RSV>k%%hNoyH1n zm|0)=m{FJ8JKXm3U{A*V>aV%N=HNPFff8Y|iY-F$PF#1oIAOrLvndQ8?##)TVPZm= z*gx6Shlkq-#}VS)?cYpqb98tt!EEv%#d&H)%1)hT6tlYPfOBJQZ>UX>3d_`zR94q{ z%5+Sd+0U~_t1XjmrX61Xs;-uqs&YQ=``kX)!s9Y_pE_;ZTzsooo@l8N3z^zxb2Ez- zcn4@_FI_f9bAcchKUw9FF}SvwHnVtPZ?kTFT!EzPEHA^3WZGrYzzMAedsXAJ!C$z* zqcc8Dn5g8)I%Q5~9V90z=bzORzr)~=B{Gp>bKsa!4Rt`*_prze0w7>ZgneaW4$DV@ zc=3#5BZe^cNp6n4lRwXVY&0QkzP#>r+wBjGU}s>+`@&@%a^cX~*Uy=QYoU zI#rfnVn8!aoP?mt*;jNil9Z$MEGZJ}r?W2k>Pd87XL&~kF4R_h(rpG*exLW?xJ;ZQ z;V_tnfsn>0r$Q-=svrRqypUma;?l^~VB_l>0kFeCnUY)u#@JuxwwM&W%#Sf%u174r_`H(vVwpuKCE6tUI zU1#=*WOr3kV_Kf6^gjD@;_@nJB_3fR7gcJefOC43EGIzttbyN-w0}VE-?ca0A8N3I2p7NE{_!zt%S?CbIy`G zbT{1^fxp)LaF||ASDROQ?k+E(eM~nFE#W?9NQl$CVaeKC1 z;r%6h8Gs>CN#PFN3|def(tKQH*Q_nCoG!Y--G2@Tr-;OMpevcxo2yRjOT>msW(eUq zm@yb76mXQeV9~7hysF(?6)BD^7SUa*^2%6U z;Jh%_3yVS?M#WewYq{pE@djfN^4ziKc|v(2qZTeyM0d`YGEM5$0T(1L@jx|NC*9m6 z5#MF8W?c;xmYj$hdejR&_xrk&vo?QiQa#VgXItuKy3Xf$(#RPFCgbOur)4&#aTw~X z+`l&GCHeirLe#W+;q~N+=zg8M#piN*yr$1tU10t=m=(wC%T%eG8P;=2M%$4=axN*(`JsEJ+;u?MwpdKH%oLfmV%w6dnl2s^9V7@+y>JmVgjHC zG-1yqKJxQnMaNiE0y$_?;G2n&xK%ySfae_(C*^bbvgR{wBiM1s$euJiIhXeY7vcm+ zfX#_+o13nUN``oib~09vPGA?$hOyek?&Jlj(9U)0I1}c|+h-Ai0lSGMB0EZFatNqC zXJ>Lx#rKr3V$AK9+>?xWmW+%mCl+ub(q?2PT?JM5W;Ga1*>xuIMY+%F9!2!(iEI`p z7gR_=JePeW*%caoincP*qd2W6P}xMgD##EM-H9~ue%nx6M0UPU*L55T zhUV3DYmu`32#d2!JDujomsvMV4!M(7s#Y6NbYv?=V8g=E+*e&pVsJ51m5w~6g;)fb z=e*sr5G-r;YN`fSUe;_Bvt+P|b5<~aF8L_Mj6V$^9begT+byx3FaWKVr5pNanex&C zo(FbP;C6hUqnnUzS`}plRA3VPS*U1~o;J)=60^g&k*4g}^l0kXys=g*HjDhYrd&BD zz1Sw4b-*tedyRG@FE(fkl7!5vJnFyBhH;0kHjdytD;mR?9Pl-i!!xsCQN2TNHmh@X zEbB5wN05Qk{IMhSmTRiDJC-k_885bX%7FlSn&Gl-e6s3d6U=U{vUD^*FQysFBb}Se z7b_g(7J%-CVH%T6uCC@;y&q>=5%X*v*f=63h$`^~b0M^k#6{g&lUu(UkGrI8w!T@P zu~{%%2bfq5TE(kX5&~@AC#yTo{ag&M(Y%wWZrVEtOw%@)wiARH8f1G(YnTy>-)}yz z7TKxO)4+fcbgH50lF{xC$;wE^@)6yAO^LNveoe(BrtKBcP$Xlw`uK*PrRQVGmCz=o zGKg%3&)URo__izGn5cEN-F>kMP;}X!kNJKzEn(u&xUClt)J(FNU@zAMfX8uuWdT%0 zR@-E`#fW{NUGahL=klz$1AQg)xwv=Ji}tV`=r+seX-KZOBaNHokxuzkzFr=;GdWI$ zn-@7qX(?_BscmPjk}V zlWoVLO5Pbet~nO?b$BOq=ZijD+#eT<{N49Trfs5G7B7A^cb)WXKI;F0w!Czp>zPKm zInbDVUUUH{>p=HY@v@zsf~tO`ZL@v0wr=Cpdf+gQbUPKt+v`Y=^-Sw#=0NvnV|RLQ z-o(gGd+R5i&yRDx(CfK)IX^B}x?YNp^K*0MJrn1I)#@l7*|2syZCE?p6T1`@qu}A9 zDSD$H18f=zF`Z!~mVnEChD~d3MW!KfmTt$T5|-7@1KAjALY6IM$5O2p*>&H0&i!dX zLoqF`_<v=W5LZhIO$JWCR1u`D72P0I5kLG}vhcNs`8sZUSu&m@CW+nT_7zR^dd z+$KD!k3-U3q2GEX-Nqur8p|7PZGOy7&-OM= zWx4^$;<38C_L?ps+AOb`7QL(oS~x1RejW3o_u?k^uTi_OdYVgXW))0_?p-`o#c^iO z#-@3++2RkKrloqgIv+(xdc7vy^@W50wsUn9d2;NZJjSr@X2Vm1(6&yy#RNSD{4=}t z3ctHuR>3t<@U$Wo&jhw&As0cB>OsJW(rHWfxp?AHj|&eos-xt*MAR&mB{*X9K%8<9 zA3sboT^!>Ix?C}knF46!aSZmDZ{y?+hYxHb+q!VWww3&JII75D3Y1iqy zcRalXR;J}kXzI#h(3fzIzzJJv*TnY(nN{#>&C;{Mj8deZ5(6eDg^;VDV*9mt_!(YkK^_@_l~F& zK(IAH`pY*Wi%Mbz68Ih~go3!{w4ge|_XAZ0L-WD$H0U;t@uuKeAU+jx#Bhdc zv-78>UThk;DkpVxZ|tHh{4bJ1%3VM4xXNtvE>rkv?8x_gZ2q07w2Dl&}mr>_kntDgAoLiW+N9 z7AQ7Av{JXzZ?N&aPW7n}dY_eg17_yX$4tHxLLmXdFY*b&N&m!*9v5b1FWqk3I{>AN zWn1+gYp~q6D&TN_M-0*vf)>@f1Lgk1hTtPzw z2jDz(8p{eFw0}G&1sQVX!EP4H=SltUkbz5vcNsk!plMuW3;i#XxgAhsRolSJbh_kg zBKgzDfv`L#h?l>%GxACZnrpEHF0;B(Xmqg31)uCP zmn8ONKhp3FCbu^a{zSAW-KVw|+>Wy;z&&}ROSvrF$0!c|WScfLB?${zsmIZITsp_b z0&_>Gvx zZKS1dMhzefZnZTSq>q))W2pv?r;~MeEXi;w-BL&1cz*+~q)wL%okm-xI~?0UURdhb z3Rq>w@55oSG0`7q8pj+>@@W`X!cL>{2h1Gkl9lmZIY6@e-=`Dl#MIC*0PapesR0N9 zKxvEdD}~kymRpB$C_0xow9GY?QfGq-O`KXGEAapz1ymcPETlGYVY0Ij1J7c}GtqUV z$EABSZtd9~L;ev)y(5eD&C|KfJnjxhVEKY2H&#E-6T?JNwRFc2C9Bb6>X?uwD{+a1 zOzTtD(P|Pv8L<;K8NhKWFv)YeBzqF&h69wgIISBKew1S`DSom|bW-4~23O<~X{$T4 z8VppZ4%zrD05aiL~bj{!~SDuqiSAEYO*$nvA zNFKV?`161}RyNvf9vCLf3|Yh!rq7_|&@ffI_iE;eo&z?ko};;cw;f;B_}rhT$X>rk zbbfno_-I+%aSBy$F;vg|sYJ#%V@DQNH6kI%p)33*xi~@RqK%5C{9-E~ZjPdLD>Q-~ zXu?X8X(*!(xLd}LGbvSwcFZXES%m?I#J%>~fm}Fz8!wYr+w3*+YI{C+Z6|+j@Wu)8 zcxa6@uJzeeH$=oIGyqNQHE#3gaE8d|xBJAvoNcQBP2Hbu7qkbkT(f7Mq4_P(QDz0~ zjo~wUOTqL`Pm-?W)3|x*?X$Ai?m2sX+jIJA+nn=f+s|DquW@UxzMWe$r+7Bi4av`) zfQVO-AO$??nAQyuPre_B*98bTnO5=)_Z{X{XNCW z39Qa+4@Rhzprz#>(gdag7mw$qBsx?^k>FYdJeYwJg)k;1N+9Jrxl*$drO)}!&ln`l zjkh2ugUAL*4YMZ2nT(U^cAlokdDN!5_iw10zzC6R-m2_W_mE4ZQB{u&x+odQ^Het_ zN2VPsZ6WiSmc?p)(?%6SI;J9B-TH=3rJL`DCf#;TT1FFrgb>cF``?Z#U3N{{Be@V< z{Jom=6fzkaW2*~$gB2x@VakgY>ytrbjM%ULW=5%k%+#|&(OQdloe*eXn-+un#Cx884 z{_1z1ef!1jmmhslDjFF*nrx2#$qj=LO6-_Ts#XB0_pGhhB+LFl0mrYGOi`PER{I(4 zFKH*w+W2|jKQkY=3HwXWwq1H~`{vuPfBO%gfAryheD&Ec{$VHo^7mi<^4l*y`cN)C z+|#D^YEX9I!=JQFxBEHwA~2jTJ0CY#>MhSA`_Bn7qj`M1l7Qb|Kb2m%bL%n)3r?fr zYAIjDK}HPUzDre@xuu^!l<#&WlW%j-C1>kN7Z!SFl$$`@uq3qI`;B3 z3eN%ki@ytYm-A)FsxUFzV)Tri1#BEav**psF*C)?F*7s7cFY(vGt-(9J7#8PW@ct) zh#_X?HShZTy{FUZq<7Md)EdpSRMYyat2GT(zj+#C?4as<^*41*sbh$FUAOgX12Yfy za}pfmc2i(8QtB^s`z#iKJK2bLduk#h~@9!VFp^^|ao_5O1QyS;yT`+-rZA zdBa+w@N7K7G>`MNAr~d~O&!0w<|FnAuBkijLn(kM8i2a_s1AB^U}cWr!V8?DbR#Gh zTPQV?a5!LF0M;bnaj{T-VgBw=VD&sOtH|V~E=?hWUYj}jeKsvKbheA|ezA8Mu*zrl z5~xqpyfhxtkgt|B_bY17G?fF^C=78Agy6B+?w5Tzsp*uxqf_5&1ug=#?h;ibcA>Q+_Zrjp#njVV}EC&hL&H)d&p=hnNdO+ zbqx!gqY?Kq<*zi`<TM_mRdn-VB0o|XPe^gAKG2tr@z|e4RCF@FTd>Y=@5UsLX*MS zi8~={*~uLQQ;sJoqE7Z4Y4c_)eQv z17Rtg^*2QEoY5IH0^W>jD@WiN9HoIy{>WRa`}kMM3b=n^6@J^2A?pEOihzz%uetFD zIiEuH1-66=MW+>YE;*fBI=P_-3q!pzm?J(TOHoO4{ZAt|FQ2njK4h7%CsD0XS%+xS zgo+Qv9O7i_6Os*#U2$>h+&v*%oFN#p;vgV6mUw~&G^qHd<4Ijm>n;|$7cooj1&v63 zky#c$K$BlC@G$1xh^Ik|DgIPQKEIjl{9$t@GcBA(=f^Hoy9x=9VHg1W(snWq{O@ip zGmpXh^FqR;3cn*%mlQKN(j+gw3x(Q#!^E&YL9aXh+M=}y5ip)N03k^^htqBq@8jzn zYB(6Z-bcs7VszYD%eticQPb>cg{kM{9+*BOp;@=RgfDK9lu{Lh-s-`xe`DYB(C4s%= z`j5W9Du0qW$G#QR{rlh^geS2NXPiR0b=lpGlF7>Vvm=i7^=Po}@;bmd9^=@DTwffW zaWj`rgnr=IpZU{pm)p42=0wuLcf#?n`|BblJDW#255dON=0V+R!h!2aiMNDEFHtl?B=9z z?z2Wpvlk_Yq#to<*Hm$OMu)rmcf$2vX0J_5AIdw1N7F-nVHOr?af4GW=VXT^?1Ok= z(6Sa^kA65@n$Xlg4OIWecTNN0{&7(_wqf^V`BD$ET1wWAz1 zV;mYrE|Srd zbbi%i*~{jmV^9fX=c5f{Rqz&t`-%$m5a7O+A<)~_L&J{|)Ihe|SMQKpU;Wi#+blah z-S~C(YBOE+>E*GF(5u~rBIdSaCX*O4*QMV^Av3QXVj)UrQEvLMwED<>7I^e~*}MJ4 z=D4@8Hx~f>%e;PWoqV|~e2-5UD7%L%+j?2o3^S0MN(%W?pl)Y9H!EN*U95P1o!;~- zAZVv1EcedArpGtm4{M|I{7>$aCFoUvEQhsgELDxs2NVR+%J^9V-P?#Rct-5Y6P4iv+*45UYTB+ygJzOC9p0>9lP+gTm zj7uGIP6^kcD$%Lx|Kn+aJ*3Mno8w? z0*uDC?-#_2yu3&DC-m0$l&N^Ad1&^n(c{Cv%P`IUMVL$7FQ^jw>p*g99ZOb7$ULmFWXv-KZM$Ta9sa=IMJ-aoJ6}Oq;UB+LG{K!KvvQVJ z?=z(Jwb;;_U**2eCri{v1lbk%RHN#TjHl8Kn&T$Y||4?g%)wUz&Y85cmFnxWM8=$X}g40j|+Wh zr)lYjO&=%cm-=-w6h8TL&|$S?(?vje>q&updckug=!P7!&~Rb?N2z<7x+4c9A1$L^ z0!xrPZCO47rd&-90Tb4~_5F>7sWC@yQ$!|=?R-NorIWS6%ECax_{A{_6TVEprLt9G_bs&N zx+Zi8Tz1~H5&f1$X6~t-9o_uup|S4il(DFmgc78<&xv=n&fTqJwcqda(dagNjf-p) zKe9*)fe`rt%VSiE=jlrv*~LI46z!)vnCTeZHsHNBpvr@cKoerTr8Z&8FHWR zJI5;n0HT*m%qRZ>VMCD6@r!`|5KNY4ySqr)Lo$bv4coUv+CB+d-dEW-s-=zooVX}3ZlBdu*g zgKAha92?*(>@k$v&Eyn+-*z6nq_39j)x+{se@4 zY;?kUPLY_v8U8~o&m)|t?{9~_Y`s#^ZAd#V#QCK;_+WJpjFU4I=?B5_8o|Ms6Iii@ zm`{6BV)dCMLmRhuXZSsP$0cQeJ5kzdAr}z%z7L`*E}r>eSnGlk8Va*n56_{|lOs z+{esK`aBrD825MVA^oWrDwRF*UeEnzu>!SU zWo1g}GuJqyomIiUeLBgLi}UkMb-You1s%m&^i8PFNSNQioM3ItPnVqj7S#c6>}>G( z3M+M#R%VZ5(w_i%lJP;2+s))>QSFwY$o4p2KW0o!?vE^^VNj+nu{VA0+UDoi^!ATI zI($$HzBquEL*G%|k&LJYN3zhOlb5r%1%3PH+)#Y-ZKU?Lu)%k(R9I^yZ#|26t>PU4 z?G+AHB@?h41BD!ety~6|-dP!vEz0_ZLp~<^cQiUdNBI1heux6@&60sB3uR1nxLO>(BmF7J>moKTV~-7vx451M_~Ke90DS z%MgY+xEfA0syq}pSbk5?n%?{ATx;RKQ}hApbC^FxD;%oq$gCdb3*H*t7kd*tFD?}i z;CtAQWv#fVU%6g%5fM&#AL0^X>`nop$KQWIyT_~4GK2He!8`R3A|UOcKw@~1!$UA? zSKT^&`iyUYM|@{O_MAo%s}n~f`wQ>TC?El9FZb}{gZ$-V@jC1J2wzN%O04u$m@1Z! zDB1MYASsSnh%i8MJA2vc-*peL)Hdb)+0NNd7ykMhC5*OmuYbd> z|FzWm>Fqgt_{wCibM0-WrLVC3)F!NhusjB?D$@Jhmse!$|%KhpjwFhUSkjUfds7%O;DbFWMvZT0h{nR>&KeKFRrLt7#{FcLGOGUb_ z)cV4hML=iXaHQFk$aJ|kN|V-fr9T+RfJN1*M-?*?{I(qD#KF-Og-%;Iv~29mVcGS~ zV`|nWm9!c)wlIGeJQLwm&yl5wVYxrlZ{_?d`tWR};dOfcREP`ExIypuSY~o+!oLt9 zV?7@L*}3!TQKPj)G@|a?ZS!giD|5%wPPTgQT5-2+V51%V4%ztNge9JWrfux+&${7c zC!RvniX3X>$_1YiAPe`Lyy6M;%}YDgkz_qQC0cweJk44Jruy$1bF~p-=cN3W$P@;t zYk)+AZLXgh4L_^VH3J(d0h+g-%OB2FKQiyib8>-?iE04NCl&rD0r&UvQnIF}NE5)^ zi&08oh`+I8lJstIS+)9}jGYs->P@JskT-%nmP7lkI-|n&fh$G?7mZ>0r*j*&iji?l zWUKjAG}_3vYkkufW7Eq17bEJ;b-GL7<6^kxxT5|RqAwwn&7O_xP~AZ{Qoe>GTZN-l zmKs=@0Q>jO9guR_!flkbgzcszdxjCVy<-~R9cqy57ce_(VR{rf>H(e&g#nQTXng<@ zAdk^?@nyn@u~FalWmD@Uls7@nD-L_;Q)j28RD(H-W+IrHkHHilBfVF2vPoA6HI|2mv% z^s&b{xzh}!_b=5De?oum`zXD8d=8omZuKBRN!b@B-cp4m^FP_a`Eg^J8`X$;vhy$T zmSdL~RY0q9cAng=ZoG?$OXYlexx$t6xvNSP?|yFF%ZO{!6V{WSvH94>UHzv%gD0iJ5r7?C<%|}C3nUAABJi$%`iu1`rz+l zWEnd7Lr7-bOWNI$Ccw^k#Ud|$13fKyn=THHc81TC4!eb zON=0mvNsc{`7&0T*YZO-G@@C(VqAKjp5`GVM3z1Vh0utEPWO;RYKjmD>W!ulp^=qd z{y{#W7IvNi`P80w@+ALd6dc>TbvL_!4kROIT6g02NDrf!!sez;^MP&l#3CbqCER0j zRVROD(fEqnkg@PxH zmlIXeKK%AeAmMGf{G~Je10el*Rl0Zb&f*hE$fdT-4IJvauuhHT*(#$gNPb0hSZLz&_Z5}hm7Srj?U-%!FbWN2nvYS`X| z`gEq_mf<)4-dA8+wdygZ;7;r)I#*W9T7#kdqEN`F8Z2BBc;?_L)~#L+0gtFnwo(@w zL!~R0S6Y(W0bUfTIxk99Peg#H0m$eQIz0q~f9kLX<1IBLb47m#DyASQhY9rs;HTyg z)5%LLpbi+tWhQ4nq1|*9sJh!!@+aA6J6sX%3z+Asne1{n_j*;gh2e94QHYre(B@38 zx*}Ec@P-CrT6s}KXjn)IDvrF>L&YazSJGRFP)PlBpf0~=HuJ=&OY}-PGSx6iF{``| z-;1E5eVNa*Js)$N+1eU^W67YV7#NM-i=Z$hVPp-t=GOu*1f553WWt;_(Lu^yJafhC zGDr)jcy$R26jp^+=+lYyF~$YM5aQ9@D)?6i){8k1dOKGWw81tEm&Fc*QT?mNO4xy1 zI9n{Kk&arHp!uiSsc8`cds@<^1j8MgE$z@yWOgrjHDpSA2X|yG60<^QxzBQQS{cj$ zaj%S@F-+9Qa4(H@tsLH#CU41QU5JfcFV<}mQ}l!*U#MwK>wB3~PJ41Ob&_}bcT7>$ zB1O;KLiL3skz6fXiB18&c4_m+EG*#zuS0l<5-<3PN2Jq^gk+GgrwXSmfNsrjpORha zf-*4~_Nbf>zJOVemsoeZVP22l48As*iI;%7jB}ocS`=B*=YapXNL{{!K+?jpSGmEn zKD7y((|VBhyT?ifC$+?!_Wj(lTt}T5<8mJZ#9jHnQ(2wDFGY(B+zY|kNPzMmy)*z8 zIhT1PoB^{8L`C4MxH1B6T^y;7i|)sCr$f~NUaVNEC|=Wr*#_F5F4{uAPb`z))eshT zJbqf0-TMOYlje5?(Pq3bYu^r?qT?Ldim(^FA`O*kIj3Ts8694+W{#Tsrj145SN^?C6UO3y&LL>?FwMtC|ss zDdysfZ1p+xy?J8yaQ9v*o+X_vmFD46{3z8yZG0buF)8D3NZ7O5j_3NZ$m3#SNe8;F zI%z%>wsFmJ={gN;Q5otHjJ5}7{)$@3AgFUrJYyz;ui^sNVS`6HfELiS$Clu9)OT-< z;htoYn%)Ffn!`HE!Na4iig(G~Y)%*kosn_l%nbDTXan-07=AlmTCr;5I}QF!svmbd zC0B}SX`)C%jE3+0W^W{%;_s$}zC-I7Th2obJwD2-{Rt;$A>4yURMODXgcwnF!%(xn zCcW~$U;h%mE4GMt503xFx4Lxx$z<=k2a8Jsr+-oNEu)|P^vy|Ht=jnACp3C8Vq1`P z+RksPkyfM6D)HhUO3Ghkac!cGk3CLImTQs>bpv@rUs!owp=nP2i5ZiuJjbN!8hkdz_=V!; zN}$}dGXHA7wx}{?WY%IEto>u0TYCoW_f>xT{ERb)7Hzyp>KRutFpHQILf)v(x?J6r z5JzLuISkD__qp1nj$lqDEPLc%5b(0)*ua7!z18Y1%VVhj#ugLYwJXK%0&+EU}Pu^wqnA>)#TsQ`{| zc2**m=?`D@IR%PQVi@c=)usp7*+;s{*GwEIeR)E$zHe5sN)Tyiku2E-wwxuHEN16o z2VRy8)})Yaau&-|3|Ic0UI~L(ObWA{l()Y#6{xr*Ujr)ndNJddx9qBBZCbz8H~&$! zCSrB`}_#UGKJgyvKlMw z2I|!7l3%(TJ~jfsMmm}k1th{*!sDEl)+gm;o;xmpuE8EzwszB8F6kwY@3TujC%}<$ znlO@n>v6N9G33LKweJTQ?ia~am#U$6^`VL#NH+~@)d~cynwGI4xU2@S-$-XO6KDlce|Uae;QYtDW-(#2#>&hG!H`i%2ugbI>Oq28vy|8dkTrrc~ACJf>U zb8FqO-9LII6yvJ{c2T{AB4Ad61}{GozrRiM^uAuMemu{I0p2e*YkS{QKVDN$TZRDq zy00#JzORlSjKb!~!}2zpuh~X|7tJ^i(;9Wc!Ny6{WLbV1EJx8)N>S)O*fM=%NmW~o zNQ!ZtTtav#z1Ug5E}R%WyS4&5D0#k$`X{`tdZ=+kL{T!9pK2mHYtvG*FXzb}-n%w6 z)8tEelG?bnA~Z3C(bfWkQCu$;V{;ACzq@2Q{FF}~e+JCPp_5cP>wY}1gKl%xHYgFD z)V`j10&WlQ|JZZu#mSuuSxAm=IUsPja3Z`|#!GUbcxjt84x|4lF1oYwJMYBA3<2s?K8;6ECDf zkX3CvEmihEegGe20>D6{kJJzJ|L_a?HUVgc#t;zyp%nbj`~vDvkUY`<%`b5CVzxGQ zbYONhcQE_^!5C=7PNEHvV@N#(44die<=HHz?THsMg2I2Bh+z^&6aZM2{D-Fhj>{b> zIxO$#g?AuEnD&T%S8HX6dNY`8b4HKBraM5!Uy~ymoabl6B-JwYjbR9Nkdlr1oM=zI zq#PuvB@DIY{1Es3N!?b1%P*M7sDK+^#H8{em#Rm7+EE!2{CmG1Mw3_@ z^3WL{UbY}TpM`QUH#N8RF#rG4O38764dwUsJJMvRB*Vlpyk@7z%sYlX=XQy6b{!1=xR)+k~b#46}1d^KZyB9J9Bn2s7D*W<&4JriT&UEqTgBGdwWkQXUD zQQSpNax1!QJ+^@NZzl*bR2g~rI98oKLRGA+Turqc?WBpgoYdUR3cW1-q>K!$tazil z9PeHdXlU1}(nwR;;jC8A84E;sjwT__8O1YA^$Eu1<+4|@nz7{v(H03wCy#~NQ-KJz zd_9(lc$(+`>OxA*xG5u z(oVw-U+Ga1nst#(yDf|y%n5n9?EORncD&AH3pfg&ceSURmQ<7V%Ivkm_<~&lG|~i} z=ZvoojKbm#H`P=9#EqM?%#8Reurt|uwcvlXw;NElctm25fE20)A!NgAeusXCM$?@q z6-1`f)5&bouIINm(9(4RV1lE{j!WdDt4k{if-?U`;SnmA!2I!7{^;4cm~;c+!XFwvDew3q0B8Q5+q~I; zf1fI4f;WG6`fNtsmu^np$F7qIc)cB)!T)}Ik`piwaBU;=V}$sD;>`ZtNM|P`SMF^F z4`3XwV`mQ9xgP9ozCO0(9_;dG4Jv*It{(7Bxv)P~GNNX5sMmHiA!$uO(+@((0QR&oVN8=w4Aa#lei5hY|M<-`%3+ zk`K|_`oW^@n6$TzJO!=^&cr{%jY}1-+*?&1~Va) z*wHaRHE+@Rjat;M;a993n=9uy?luI{-Pk&kk{(~s4+%9Eb(|r3jKl<2ysw7pzRePv zhZLFh#hMQx4(K0$)i?)L@48y)VaZ zkrVXr=#brhurm$Yal0Oj<9e*yjo>TUVZ8pXZc)jZJ$cj+-0cwW8D+Q?==(didwO=< zFhie@_+O*f6d4jG-KWF-$Lapt9X}liLfpey_doaleG&d2cXaizWHoiPb};(SK<~MzP0B1C9s?hh#0(Ie>@y&8G#NG zcfePzMt&|Ytvi0eO~-({@!DR{_z(8gMo1ZL!>Y6z+#81 z*R?f)U)zoOv}nnGloty_Z$`b*U(KQMA1EHJl52w_nE=sJ(HCschqH~JV}Km z_rv#{OVj5pSHC9)Kw>*Wb{jjt16GrI(E+Wy;jl7Nr%VUv0vn|LZT$5OW*AnN4PqY4 zvo>9mMi)!6FRi6{)FMAd&Tnf?IVXVh!{_cI#oc?rjvS8O(dSb9Dr{uyi^+%}GA`0s zAjjS;9V^+?hPR2ut)>1eQgqtKz3@N6mR>|qmJ@(gD|Ym88M`qqukjWEQxWU#NMl1lLTqG)v8BG^Cwc8|qe# zaO%LSR^2k|cBL&77!aj)X#Pmq2ePLFCzzD0D{#;aZMs@A$zpRfAEnjZ*(FtDUM7G| z-OUQo?p@7vn5{rHg;+$@Rrt<=5m~8o7F|h-CKEI12(E02vSATCI7MiZ$i~rY1oDm? zg^~^qe8ADxWZ45I)rh1_tuMBz1TAwS0Z?B)ygjb<)=RdEkfZUAZ-QO(o%EiVk-@Mu z_15<%f%Lh=i3pIGgBv_p@waM)cV*9(0+Zt-=ER~!A<6*pR;K{S-V(BsT5)z~F={U9 zG9@>~Lu5}yF5}IBGf(FFMO~}FJF_qp5c7w%su+KF$XnIK`CR{xL6~1HJ7>LtYt<>g z=>a`Y=xvMvL1fK{$z?!qLy7I;lqAvpTIq%P=t#cACe-cUE)FWW7=&YcZ`7P6xCwmmEK7i9g-}Q6*xtP zZnU8U*xzpbALY(i)B&8n%t9hSu-SZ4e-JtUjdaa6ruUZ(dpA+wLQ)t2|=hX!{&~@iSPqo^Agnj?8-a44;6{ z?dK0}Uz5-u(cSB&Dx53e@CX}X2@-3ZS}k0!B-8QX22%D&XWXLXHPOdwC+QHk+84+sx~+z1Ac z*}c9w$sb3d2F=K^`QF{nTNEwAd<kBDhRX;)}+hmQ5fwuP%Nz zR8&Uc-rA7uB^bo8HH~7yZ{9;e)#ikob{vZ@K5B%KM+nle_DsSIxaIdk?h3SvPHr#Q zh|8{*H!Y<2T_SmJ_B*bdQSloIM6QP;GZQEjJs;>yIKz;7HL=KMKK$_{V>u@9JcJ&y{_?R6o}M>1LvBj{88b zvuasz%1;2?S!hp@Vr?5w+NVmxHKLHif}1U+*WevOc`vx%!kWpPo?fyh9^$ez%b-(# zC~k5QM_#Not6(=zvdAvpJ>NB~eYr+iPqqj0V!IWP;1!y#ANHI&zbX?e`#HaDMJC`g z{GDn|jWbc*0mnnTFEsc!CqdX8dXtMuKP*0kDK;Vnvn=E){u;MV9(y0Q=@#CKCujU# zQ3!$lGza{)`Z>%u!y@9L*EAe#9ILO~GE(X1RW)?iw1_eI&6G?uFJxCqiDr(3uy$DU$qx^g(E$+Ah)s@ziJm1+xd-Q+0eBYoN zi`C)wg7nTWpS<0@+u5hQOcnKEPaR0FO12r|L`G2Q8Wk#H}D&gmp-+z{wQFXT^w?CVeK(EMB^7 zp&Hx=QaVLXgj1&mGf%T=A{%=lGY!4Q0!bZ@FELF37l;{3XC_F_QmGta0@a8pGcY5P z-@f=3!VZu1(^*-G{s8Li@}q?_%Q3JST7wL$bav}SLFR=YPr)lo_-7;%i`-UO^%)cl zCIt|9Wn%U3;@(jf%Co#Xv6r0{oCMZ70+NqeE0SfxG!SCRaD++-EjDF?D=73B@=8&d z5sC;IiUjghaIDTTzv6Pr8oSU{v4UMI=4)kx|MO?}p98>8vqoL}*fS#UCv3)i-T%#! zTg~+c0WIS&>63b7ULo!ChORP_VVi1`7=8E;`So)Y4g-s4Vf_X2M^z5u-C_gv8}oQo zg7&1`v*_FP=lOI?qs**l0}s5?3+aYj5bF(~bkR9yqAixFOGd>9)3tDSQ6LBE2`#6; zA-i2xnDXQp8p!kO!7`%=S-yl{<>SH^L{af!Ad%MzuEzbL4_(E#T8DgvVENNshEV38+)jgj=x-xSgw?_W{qmmK z(i%{ksryeHL}Y%HyH(;^Lt#Gjk?rb6%o*dvn~$`8xE7Rx$1T=vvi1@r*Zh{t?(&-I z4MDy~ZBuRE5$X?U>Lf3J0+WH#D&CR6X^QFnZjAhT9Un!%AcbfRET>0;w5X0jPc?_& zwtNvdWwbUDDC9NbZ&H0h8d8}d?SsrMG(r_*^NSFzEE$i_yYLl5RG`{(cgN|&2*?r;@kyt*O>&k5p8I6 zG1BUX)T|&3@i}HBCPJXvR}N$Ff-^`aHa44tOam%QM~Xaj=k%e|EjWo`NZ9}$L_ zasmS0P5+wI@~>&p1baoqCn2vs;iG&-;$H)?X|b^)B_y0MR3lC}x6>D5TUs79{A^I> zL$r+e9)9~Bsy$ED`hIeZGWQYDlU{U7X-EKLU^Z0vOQ{3LFNme7KtHhYjhu(Hu z`HhXOarub+rirLu|E}gGl%F(2ijxyTMTz^e*L1n*=4{u1b4;1>8PMe_B@y<|{h>u7 zgQ#@`ZP%%~86SQWOHU1QQ^S&nm``wL`>3MOo{kEv&Gc{XiuW}UU-fxQ6mGeKDG)xJ zN*HPqD(@O1Oq)o2o&0rSMxrEd7BbvKQer55IUImJhkv1qwN@qMt zz$S1M&Nlw0twa*!{#7YWTw5j{{tLCezRz+>@;#M{^w_G*J4+O=MNO8$G3beC^Gbn$IZ&?1A^Lp+{d9-NNS8yyn1(P*?H|mHw zP>TlD`1OKo+u~hwGZcR!c7H#ld>_|lH79ZEdAv7)Lpf6I(M;t)S70JUHgI;JP(sK% z-;0t4ML-K|yhq7dM3ymUV6J>-{)WQGw&kN~Xzb!RHb)RQ!=A(`)I}FV0vLTJE|fDs zpo*X%(1` zT(SgG<27$&vFcQDONhdcE$QJdaTcdBsdiBz@mi;`Q0ZV%+;xb%NU&VKVX+qz<57jn z^0hkBtaNoD3h4y9aRRgxu~HYi1v`m6q5%wk>b`g1M+#K)gI~XK-!%o5fD83$T#7LF zJ&uRObYhUGdh-y&p!D$6z)e1?g|)8}*)6~-#5l-HfK=izUmx@uRmk2tqT{Ed+hi3Y zp*i;p3$c8K=3+JZ*jJqZ;a<^}o3Zp)sA0V>uEbWo6|>G2ZUwca_Mehtid}~3)O@ro z)qD1F?&%-FozX$i;n2k|oOw)eJ_F$BLD;8P!QoIl*WxNHy{(?H``+WPslZ3vX*h1{H#R6pd$%;>Wo2->hNzZwi7lR2RMqG|z@0nk z7OAYXo_ai_Dfap(gc|Z6SQ5w@vaXp zFn^T8Rum3d3?r;fe50$MQNIeDH{1Tgi?2rH(Dsc@qNUU}HXZJl6amRG!Ps|lDBelP zTGiA5nB;fPSg$5qR!5F2IKe-ngd{ngMV zO`@6N$eQ7IKB#MSNVOhijmKCCMdRCF-@ve^%w{^KI*N87;m780dVw!k@YFUIV_W61 zmfE*er9{$9&$H%yJ#1(u1JVxAKcP1-Okr5?ySe>p{uyI#`HmC1OeEjq-y7n&|7b9j zL6y?%M?QFuV*NekDh0RgMar*jnU=?prDFQkyggI@8yvlGs(E@45sGyol`74JHakT% z?|nu`;%#sqpY{{&LEgz0T`(@iQ$eDWsx}qZFZTT9-5-Tb=r9s%uuByeKsy^3@!Dcj zEHbcuI=5!1FkMO=#QM;w$)EN+Kb}!!EnrmSA3vo&ZGNHoTmQMK?&-uRY>L@mKJbjvm2kGu2P-i~&Je^xYj6d)i_ML7Lhe->O4 zn+^`>engU&8#SqF*ADIL%5P*qq}l>02tHT!l3(H(!XF=ZfEWRSI{^n|FTHOK6?0_A z)2SH_WOGK>g83$Yz!#PPPabiARseqhc=4JbU(0_YZJ=H*4B-{KY0H<68pBh3tL;jk zEZ67dge(Ab*lN^vQ@8^HH_rCHbN^0+Ro{Lcb2kyjJohttd3h+^`G~)+R5^I8%AMd7 z1*1eEop}Swfr9s=+%G>sr{zaAr?E!2req5iMU~p%Yogsv{H)UL)iW)7FxXkhy<72e zU!9DftvAB`;o4}p<8?aqTqTZ zrRLPQEQ{NC{!G6=^aONovH{ycejnNVPy0qfOxLg^mdOi7#VHTH40I41 zbyBn=kp5*dlJME1(c>0f^e@jAAZ*I!^LCSSxCS&cN|{YUY0?G%G&5GH`R8He_#-=8NPKwH$$BtECB)Z|LiK_nequSO8j)nb z2&3_7g9_H&zU616lx&c^=YJ72vr(b{Zr6wuC6T(a8J^;Caa3hVXPxr#V6jX&bXD3i z^({$Z637ed74k3zN3UB|M@jfag-d%0JxJUU)q6GnP96L-|E)GU@j#G@svY5ngKMwJ-rSidTZrer|?4M@gPu*6g=DM)%MzuY3ue6@0uu=JO?BI?eAXwt=bg1u2_ z3wwZ~xkXPSVq)%s{2-za3v77XwYBMr`Q(ZqiY> z;&SbJcSs1wr8ZYl4YwdkGj~S75?_~pR!(z*N3G)ihml4$aVr_&6QKA>DF?yj0k@mH zlu1yf!XWG+lZdrLR|#!utIIB<3>kBHITAyQu&ktpD<%FGUlZ6$$0FUJH^bfD?p7P; zuIcvEN4ZQ8Yb|%&3yS+#Q9FY_0)F#b z3y}(ov7C>1ZT07`hv^7=Qwt;B!(iOY(YxzEa1F>+OZc+gNYY@49m`SL)qPOh4*>-; zs&>vDi9{xSS=-t zz{9^LDN|jax08h(k5Y6HwZGl^ajnFDbLNqV{pKlBdTsIg6Sm8c?8){R*wJC+y3>d| zYwg$Tb-e-vY5QHA!nfi`)N5-y)Ckp$}G3Ko$BbWf^P zJlk4UyC-C*LVCLBtuzu7=>u#`<}+uEhgHQLi&XL(E_v54G0V;U9>s2jZx)6KI%Yg) z`K%6;I7vhMRFei?YH&obPcd>~?1tb&nFE+s2$yYK-FrdVUxogxV6#<4wR~JzdShUD z3WSp=Yhu4A`gN%wq5xDLw>Mh>R;(F_@y`hqCzoDTo-*fZRJ!+&aq1dO-BB48>m{@qsA!<$_`bb@Rb;hVeaYu<6TVYa=9v8AIbn#4#^Z?e;LJz0mMBOdWLRTJ`h7@~-ro;YR1!&!<_ih*)Gi)|o#LPU9045DL{?7?C@NIOU);zl=9LMu$=Kd_s{VUL&l? zr_O#5OMztkSDX?1*}0^oQz2IU&4(;2pKLM{@Y8p@wK*hg@rh|st8@R>-y={+0lRIN z^dFSPh^){AEqMrp!?coX-B=QOlC)>e+Lxb#PBqd8VuY%%OO|9NHMzi>yQt|~B)Q1D zl~)P*z>Dv9sT99f8$DXwk21PN4hDZ$>U$)@3{?a}x~hBqTDFnd?Aka(m*^wk;o6wz zj_?u@vU$T5q&h24{<4gnS<-{+JZr*BY}K%}_Va7!U-Ve{+*jmUE=RPeMDYU=ewvR* zfxI!ny+(qNNPlG1a2Veiu|N?aL6nQ2S?qX@JDzW39N0)-Q*Lz3Oax32ZEi8br3|bz zn>l5Cmby76okEQO^EM4FK)0sW1Y0|<+0GwU(+1D`&nsGeCV!=?-oyI#&RK;&9x2PD zEuwD6rQ&SD;M{FuxCnIDd{WttV1tJNy`a~|&wj4b`}WF{m+2_-_89r0EE@TDN zdPkT%@Po(5&$q4YR^a@+vk@P zEc}gyjc~&c&XT3MTsd4FR?w6huy}ttUROeGZhRx+*LiHz^y(f5TaQ%b7J3mMGt0%i z(tlhRHb>ix^rWR#%5=`hNIPXTG<8t;eQyvO?b#vv>Rl`6$~rw%;`IlloZ26G@pyfS zAd=Vt9Kq|MYH~TjgR%q-Mu=!UK-Y44&#M=m=5gdS`MsH3K6}-l?Ha{$Qq*yoN8)w zK9p-k9?y;YkbEB^2;;dsM0$8wB@1~aZe3K!x`l6i%n^RKUa{MfSWIK&aXI!BYAQ{O ziJ0{HNb^{hgS`FA?qk9t9;;)o%theoGk&-Er-x*emu&m{J0mF?VWHte<>)F zDLGZ1c-81(I+i06o@NF9F`q2lDc0}u1H-#2xlqm0l6Fo~gUYw2YL7?NvPEEDl#2?= zCKvJjkjdnOo?i)9Q+)t+vr@pH|A3Z-du4{1q@|TFffTI- z@P*4%|K~{m_V+at(yMIu?~bvsZkyejJOiH#u9PBG(cgoWKpID5K+m>O)b!UDm8pgF z&s+gJ-hT?dx?=~nHzc*uTFT)Z3YTTnU!eBb3qW)jNXV0T;rolR`%?-^C7|67aH{S| zolpXux_ag++THX4+8A-Mn0bxmAmD|`Vbv-IyL#f|qrv3XF;5}J)?z!XcXZh*Z zm#-|dK1=IV#ybXX5z7aSV$yGR0Ros6JvyPwD({}Xw^&=i9`%{*=&cjnx#x960wxMF z{Y17rc~7we>-_%IGFxx!+;pUhJ3In}Wc7ntmFeR0V0yB=A&lunstd0Esn z)$Y8sti>x6MYF`#lJXd?5U}j6GYFE7QFB&mg=2=V7>yPfHD$@pMnm0 ztX%eIyGX`d1NsyqPi8tl7-g73dlN@~1CR1=G*R}k#-T=EoyvAwBm3Hlf>sCcXz|sP zAVMP?AX?_{pcRX5(l>hQgApIPkhS8d#mg6!WMKv=5-EK;?MxkWP+;xZy$)kz#YnY% zNdoElPdbMgQ@F!IH1>)HHo`AVaNE8~tCoe1D3oUTrV*d+J0%%z>08nqsa%!&yz>J! zYw+vk&3>9td>_?Rh^Mv;jcbt}xG9^H{)|C?SAxIhjEpoTPyLjt8qGs{w+|@a0WQ*0 z=R9fAY{&nF{)cWDUba+sx@F)K(p0^p!s${V`$=1#{Z7I4U7*lXg`lF;5O>bKZ1=rU zRi=ZW^si_|pPs+UdH04jA}e@@*!F2RX}@kqK9hf3Cb!{NcnfmbdbA@L_N7t!vecvu z5QyGa8_F``rdrBbLbpyR=~R9E+H_8b7E$YVeB7J**>!RMe0cxq)l+RRIH4sVaLgr( zn?u#M&(ed@UY903MQ%nO#3Knd&DnWxLEtrOnNa`R+fE3EFRdqj!$WPRF3E_r?f8LZ+v)i)SlM=0nNN;=Dp_2Kev8<0N)4S<=1&#ZK ze#m@OenSmm+hP*jBp4KjO&1pR?cAwy@p*rmff6O$B;+8l%{A#4Juu6k0=JHyC5krF z#HVhC$!%(YKQ_01eHr6cZi-%&!teJP+LVTsL|P2f&XCmZaqD*O*}gn|TbogemzQ)P zo()cM^QQ%K^>w?FbxS61d-pp~=_Ufrkarq{-8RA`v zNIbiOL%f;xyLs936s$xRYpAz%M(dHzH%$yV$^=6vUWoifk#d;`I(U|>yrGjBZN}QE z7_bdfMw1X+(^IATK9KoSijHQ?gu;A z(YGVSlmWQzHvI2bRyfsHq^Dg2?VL#@?6AJD$`5wA!#X3HZ)zhN!Vn@vy@XT-3iR@n zgnZnK9cTx>$9Zj1SdYc2 zr}=V*cmMd~nvr|ys85D$`gwLK-@IVTUjlDxEWgU%(TGV9!lOIHzCEz_aB`#=*+r#E zqGY1>ZDLH?>|HU81(EO*p%E+dL2tGR`L+LHSa z@_l9;#D0%W^tf@}zC1dXQy6uxow;wRcJ7G`d+y}%PE_7{@6PSxW%b9lpV~Qn&ac6| z&#z6sGblp33!e`JAkrI7F8%$G^;-S|JP$eP^r!3%yB4*4lU3;DzSJyve)S#iA2@U) z`$LJL2*2C`D9e+Lfld0ilQoLY!h#t@W#`xFhL_&?-hY|IA0wTgL-X?aYr0al(A3+kso(% zka;PtT&}~`s%QoKxyQNm<;EwUK}wbm_x_=1sg7c3)}?;;XwB9(yIy)-M6S;9E6sE_p29-qfN<0M5+kN=LG-8n z=FYy&v1LAlkM6eTpX{r*>InBcBRV zKsubJbMxZ{#<>%a{&D29!9G2Ca_pdPZFB7A`o25N`Re}5FkBfBs>@|w4(eaRnAuGIyh)N;qbZDNeaQQX z4uGPZZ-Yi*`GC8c=S27 zqNn?2kB7CoD*gGx11`FlTx_lKz3v~xG z@tAC&V}XJ@zP=6J6Z#+YyZ1u3FqmN@-|_GGpL^F;&Ge$Ri`F7|_ZwtGbbf76WY4*$&9VFj;~Jo&nf@0Q#14*S0S z7vg!mc^Qk>%I{S9(S+g+8bw0J6ePX694OTx0ds8?`uw9%-&AcRPn0{3<1p{1keU>n zy=t$fZIn1=y4EQ&jLI*t{1}}Fd<_oJH>BRbR#$&i4`t(wnQFaFMW@!*KYGz}+QqL8 zNwP28PPH*>CsurKdQqQ#xd!XIWdgi-S3ys2B}OY?X{(6H%7qKAC&tXov#_(okbgZh zN9mO1a9AReaw27XvjeF_=qQ?c(2!+iIH1nxx!ihCG(3Pe(wNXD+wmL)NXaQjF zVnStp1GgdXVNnl?GPJpVkmJf)Oss(9*v2a)3oIvP?sQ!9ovQ9MQG}kUd0^8-joPg# zIU(laIvQ!D2p<~3$&|q**+dZ*ivmNYrAFsByT0U*%7w`R!zf&pyfTsHs$Ipx$;~>R zo@Z?qgTa9(gFxKuA$117@%0Ut_(B9i=7`H_b{JQy!Vglvl?{=DT{8x|g~b9&wBA~e zmcnrft89i)OChz~+AOJ)Xg2pp+mj%Uv3>lNMBr)rE&_U9S9cd9pfwu)8O#|avy&gK zc-`d_t@wn?)H0%RvqrPWm>g}S5XkrV5>~s*VuNtE`|~tf((2vV9GREH(%`QRd`SjKafez;u< z9}>rcuHW6H^f9fx^*p_;Jq$9>Lf0>5h9I*P81gLd!!N)4{iz5Iq0e`@9ZsY z4*Y-><7*IF5>SkJNQ(_Gs$Ij4aR1&^+Uc;&gA`4;bvlX5r@ZUc*PmX>PUb&i%xL`wAq7}#c&a^VO|qY#^C0V%wR9Bzead1e~vHB{&UvnQ@HCg z=)vaUZ`Ze&uiV6DI^7&QZl%Tz^&NXS{&QQes>ylj+t{A90%VixAf^+C*tJc z55T5cySx_@YN%qEZOw32+g~5NB3w_h7qM1vCdT7b*UU~UGuD-zU25S^)k32 z@83Ca+sf%JV;xSSuQH6S!T#jvgt^CNbOsRqnMRw8aN?}b61`o(7v)0{Aw!K77UiJH zv5o-S)z;9%;R^pDzeQSiR$i9TSnH8Pc6;Gv;N+`-(yht}JtV|GRLCn9 z79BOWY^bw3=CoJio=24m7p90!N!{c#I*`%XxS8Gy@M7tJ;op|z9qDdNs>K=&$t*Jt zuJRHof>8Kr9NMl1A5(SG``0sVQc6mBrV~{CMcYj5Slo&`0+U!99#R7H)QOn|bLl{{ zgsF*+8x)3tmEcf_IbpZcF%KAo+c%_dry+m^&#S$Cb`I0&Eif%nq!9 zr?$hTlte1wJ;}09#iay8{gGo}sEW;^g!rET|)5NqzM7D z2-eD9{S#aQ7OhYGBO7iMw{}v21rcL3+BmBP#cjKHSoeIw!=>u27NI<*2U(+&Xye88 z?X{>lz41b9cb^C}7b$I1bwB94(>2uQc`d?jOD zrJ}2}Qh3`jq2$qMZE}CgY$mbw7N?+rmB6l&sM15(?bN}x6|V5zMg|Z*veLX`g)6Jr zo?z?BTC*z^cgc(XqH@iDl!G?5`CAYV0LS{D-*K1y1K|pihFb zv5~@X@8sS-t^IoOJ9mvbw*i$PeY>BLSR$dYAk{fcmudT9PLGHs@F9e2W@EhQ)pg0P z;&|MDPV4dacelBY+t}LWIAHg-%^wx&Gb0m3I6pjM+N>FQX4F=ORh#8{^i5kUU{g!I zxP9Yz-~rN4#k+E}>G+VOU3hmvE0oJf5a26g!>4a6Ri-R!rd6q{!7=5l%&Qr2(nA3` zPyc}Vm5%D)wq?F)RX_x@F)nOpbxxXoZ-dzwmCRn@9FrpylJg^h zuj`qRsIuYOB{CA$#V?<(A0)u8CO`yKOz>_&cG*ZTj=JE$g|U9z7xmxhA=3r|Ok<^S zPD1{8@unPSD=NaasAx0+6OS~^$y66HWtdhs6$#D^u$5eJYpz_h_O6MCQR&oBK&g?O zEL``q8b6Wk`P(CntH-2+nn01-VQ|a@L+#lB?_g1B?$PgU@?%%w14xp6R60lvD?Ops zb;amHWT&)WJbw%4T*n#Ck8*k|EGfIkXIF>tHfNWB&QTOriMwXYJN+t&kh~!y{Fun;u za7H_|gZam~{?@t_vLTd|6T{b7NtB76!FfqxI8D#_EmDX~7UxLS9TmAOAT+CV99doJ zlHyaAqbkCO6irbWBN3RN*;mJG(!yjgz1Rgppv%qb=l0&KJ{~;wC8wkB|KFto%B%x>B3EvsJI`(nD|W z%qEYpFB?$6)2osvuwSM*v|jf=1zTi$OerUc7Bu@It&-zxY7pdxCQPeMoKSVwT&aNsJ!YeEzE z>5#c&P?t}2Ii+S;dYs2PnQNI?O_o&EPjbR&&YgK?2+IEr?8}jMI1dVT*#V84Vx1dY zUM*Cai`I1;VUaI|ZbSPhjBO7EO-hq)u-kX(aLT!8ts>yRf7M@SM4HBTSoZ8b_sFTM zdMgapHIs*n7$V}f(7FxBFdE~Rn*=gqjw_)DrN1)@1BD zdps*&B}OJFJLBg$=eQYM7cJ|jHUYQj*mO(lhR${w+Gp9-L-D!KO$vQgF4M>E4-rY8 zE@3QipEd9L%W*_6IR?&pz&jt0nLsc`8sfN_X9hE5%~))#w0Rj=I)_)~pu=-QoSzP( zQ%aLN_*b1FNo)j)2Ap@1NhjvCbUoA>=0=fs3_eZE!nVzznk`mhs}da0pDpOXG5NTLmfQ0n?Ud9o`L?--bai~j4|_hR6~-{N9uCW0 zjkQbvp(ln-oZ}@}_+;#nK0Pft5ftnS#^8P7B3O17>cyMgxl=4v zmg*3!I2bHbcSapK9Yk(h-&E#@5@fX9!XS0g4@|~V1X5MNhfA7k3o%V6OWm0x_g|8> z)NC8J=WZ!aJ7~0_dugq$ps3xPUt4L`o$b}fx1yX;@}Y@h>+DgNhY$2!RCZ`Xwf+pA zI-ILQ(0`Mw>O>XISfPEtVK`N>rIZVZ@XhQGOA?83Rq71$b8K zMSs+RuQnvvXNzJ}jWvjhCt@euWx^*Ik%Xtt?%ydLx>@~otz&EyZGT#M z{NPCCn_fZmCZ2@s;@Sf)VmNOZ@{LVWM0a6J`7s2&i~ces5bB;ibIll7~nGJZUFCymFW!hdHQ?k6F!`XQ$*-?y1 z7Mu1{I4|mmg$%LN!kJr^dupZlaJ$kexd!f^R)5DGGpbxSP{*Yq$Id{>&xjHjIk-&g zf)`1B=SX9jk!Mj|3k@H>mI#}2SX^hB?yAjtKeDfDx1~akhf{LQA-vjpM-LsD;FQhr zFcWMWnxb+~HP&2a)#d2EWeiV1amsI9wFwp`$Nx(uoT*9fam(6t97`+$4NM3K=|(qH zFVzy&=6IcdY=O*Un@?YQrz(WTI0e-ha>rY1$Eicn_wLswJsDb7wJX?z;0qS$E4R(XZg|sTDaa>gI3x*}n7=!hx#VthJ;W}^t&l`R4lz)nN-Q*;> zAeSQ~Qu4!*4;X7yCmhf`GMBYcy>VqHcHWk zg-ON(9jVJxDvXQGT^-MULXK?Hx%(G!MfB83!*e2a<*RQZxZ*uiMr&!;j>GhWbK9{f zY8ByMjZURP=_`pTiG)yVr=93;^DY4(d`XR1i`Rd+!t8F~GTZR$RYE!5x$H8-5%noi zK*sS!+}I>3)ryxn6#jCvRr^>*nNX(tYjpmUY`K5i96>zU+I&xI`WhnZL2#4h=-=1p z1JPJP4|kEA2!K#({jp7tH1H>M+|Z)zp-eu}**<3{@G$x}2(=AV+Z_K%sd&Rrur_hQ z?1|Ah(o)d=qM`(sWydYk(&T+jP@3+VLrAgl+8%rAEXFu=5>rU-tb{hTh^mwuoJ%VQ zv-yFge{))AKA=K|Q6IsV_+FKl;YgoyOXiB>VY5~@Th50rMWsz69FOwBhxr+rC2d<; zDc+w@WHf3fowFy06uYwWY#NzQZpnLTq0|{JmXr3wc`YYC^(>^5ZDp-O09x7@Cdot0HYl z6k`y7swE>)8NzJRlQbYg9OJcDn3|&W$lQ{8ZE^2mV9siLCTD5;UR1|LTd*XG`Esxh zxrb#}ojwdkAc`^Fz8Uhe*)PX8DM|fm^v1jB3o`$87O~%K{*wRkqYA7HVQ>jl_%7q- z02W)tb0Y@`Zz4IV-V;v9IOdgIPQ%H3!zAxO%b@n;FCb|8qq=iR14XoVS5z(mN}p68 zE%S$Zvrz|CtqjA$DHi~2ya5`(pb>3uYvggFJ}*)NGZ|MrIFDKZTM0KgQ$wPQAXQYA z5v7tOtrpnu8?l*KCGAd7!MhUHwfsPQ^C{L%LBYx#X5gj5i&+VCOpyJXA&Xb6x8xnO~UG~0ZV&_v^?qD{;#jJ2*?8$NvWN6|>>xR!3jf`rA)bAaPW zx|yLqTKmWq$WVaWGJ<_+8sVF^=UizMf)H`5!E&un4vqB^p3Wrj=b6bwmp)y%oLV)m z*HBSj^M25RP{zJf*=@VdnWvr=>6TzVUPSCpqlz#e^a6S8a2pM>E}~Ph=!uaUNTRKNV&a|tT*AR`1&kEvd*t|gzutgW8zLoW6DpboG@4x* z7*zt1c3OEB{qJ~d3cys=IIXyb1<#h5wQOpyqCAn4aQA#P(;~{u=J_*o$6OW_;eXnM z=@D^Oj(%H~@;rA_(F7V#MVUk|zY|WH-NQ$gET^UY&`2dPwFu;a-=iON)hhhjnmHVX zqT%VHg+h<%MOy{7U~|R!B{{K{GAp+;FuhM)x^)~!WC;+OZm<6eKhg?o#J5{AM|(D58f;id1yvZBvd^7_ga# z7W7Qx4iSV`w#lJ1JzPrg11)URY{k;>>5e-im>m{7qhwc@U1csRyroXHni~9ASO;|R z8p7uAhC%cbx`c_Czf_alvYH7G-*~=ojqMe#(~KH6P3Q8H{1yBEmZ9Nz`Ab#rtj}_) zKs>WP5^SYl$rtD)Jyx%^_{5+>twDGi5}2ydP3D6BmU|S>6{+1Qs?@~b-oGlggxz;C z+H7u3i(hxRf)H40 zowkemAh*|V6lJh8bP=?JsYB@u_>Cu-UrfkFZVO$A zi*}&qAfHT~Mto&@E#wf`^_v5U+zwQ9md0Yz)XRgA(3tEE11gE%>F&o?r=X%i+gqA7 z3`jaVv+XGJL{9~`Bo{*lo~!!Fl}4jl`naQ7*T`&_c5>T@L%YjkoleBmMd?{)gk21-2rqm~K{2V|8#~pfm6%*!0UDVCAySaK$ub`VGJj=NGq#~&GXB#- z(9v!B5}INR)L?{5LdJ(x#9^r^eiI;Rj+!-_NUnSm2mzR9W{F&aTFx6BV2_JLiVKn) zh;UERikIf&gU3Y4qA71Gd9~I^Lqm-0dH>H{Ok|bBW zHb-SRVgHHktXVLtWtEwfuqSGmtkr5XDj=p2R8_j-LSVzr$#n8ox^0wNS6)~Dxl}FB zxFD+{`;dARk5d7Ja3i|0R7ql{>&tf0FtI<#Ea9Fh4wbEzS0dQS`Jm}+2ZuiPhq+YNs13e_DQ!Sod&E z{M3X3rJZ9qQ@c?y5|J4+h_eYwHi|W?KR4AmYLJ#C!!M!}j3WX=R2QFA(Vrow7?`|= z1y{QXdNtbeT{)X}6cH9T)!J80`~H>|4;!m>(pTHzAQj1wvsn{}Bcv&h{)w`T$<$p6 zh614xBIpYgMhB0`RmiQ|urfBw#a;Eo&7cOHZZUDCdBgYYK(*-@cAOmjT8B+JjhWww zW4)mCUFn+eiqES0M<3|+y{`D2n6Mz)+zQ`Cni6rfwr*-0_|XRhr8q=atSDmr}- z{Tp0&%5LOgypsoEjQNs8)DORGS^Mr?V;sQYAf8^F4*dN zrGb#_Sjng^m<#~C6}npeKrjnBcnhJ^vA5B!@SNm}j#ou# zz~=x5uoj6XSr;ykL5uIR(jvXBQd#TjWNG^ke^PllcYPLsX^c9@ z^u1xya8Nu?p$)+6HYHe0)u9{+ZI+3U={S@DX?P7~ zEQbDf*?`uOb9%I*%Tzps+US``zEN<0+V1J#I(k`;*0t->(V z)?lzicX&|0rQ!)QE=)Wu{>bd`w?Il0kx6c}JNe6`&g8g+vP3LZf_T;|HT~>5>zFz^ z*H1%^?i$IaRK|g(DSAq?q$e_w2LVU(mvOz_>oKN%t~wFHWPJh8koGpyyCXn zd&>WHu%MNyBn>0507DgH7Sg1te(eZ%N`tgMnMln?82tA*GT3Fkp+JUb;GPz}`Xq)! zw<1+Lv-2enJ0yI<>%Di3?nYw!0z~JSrSfP~FVcp;%&A8;5ki;o=H`PiF_Iy%Ay-G! zBtNy3&+c@v)YW@M@gTiTyKCesmKGx+YciEZ`swk^{cfMXTc&I>^EegIvQnWj8NG~N zH}hNpr?R?A4E|KETk(53>v3V>@vAMKFa~Q%Hurw9%BMpHU4W13IGq!kw7^T6d(`&a z3_&4I__nW)65~}@DTqbrxW&{qnhNwYUN;EumrMD) zc6T?J>haGbG@!_ba;$MZvYA$o8ToZ>lYE`Sx_#l<<9)}lb4c*`m`dJ%PCqtb35P)m z`Kz^>g>$&EnpN*Q&r^|r!k|#7U$0|(YP}PbidM3ZK|x~PAEMetkL;`&AQ7MAxsI!yzXAFq z<2sxeCjn`0*U|@Bb10{dp|-z4$Nlb6fs#+qLt3 zIeU9DTN6z975{y>^Kp5w+V^=%==X%wC!+ZM^1ky`=O60!g47c7%_RE0a|7?^^PhLT z*f#kMs}eND$8(*rhUp4eH@khD6!RPB927rF%H0;1ykW8Wq@?xe<++x`s~&IrJtPTu zWyPz$OTru^vg$KFS-hUq2>7p@NfJC6Mo#c3#A^v?|G8u~`N*i@cLER+myL}-l8(ID za^H#eAfB&npFb9F^dDgn7MG6Mfz=Tb_`e)n`#-x2e(i_%!Lo;BJo~?7*7?GZ^?gj& zecfame11Lmz0LN$6oyG62!4EYvN1orCfc5LtgkJyjuw=j5c|Ss-`Ng@y+jOs`4;KD zNw&Hn+zzQbl|3of2SCP)Wm5>G3OacWbG%EA$6Hk^PkM~wH&C3!n$n1B%;T zjBtY-!DOfsVf z7)PN)`kvIoDGb_*Q&T2+CZXL*xJ*?r`!@bWnFsKgr=kRsOluNSE9&&TR+Re0SRT~t z;k3dGQIW4bU$({TH&_>&TuexLz}p<732Zby*oK%z?-cPrTV}+We`ZXWv+!(O{^R1u z5VZH$1^sAX6WH}_9JE^3eJXvc<#jyxr;;mhK>o~*{qxDqApUXwLYFCfd*Bdj z@VPfOR`(5)lDU8sZ-C2=gB=?GHgxd(RA=Y%4kyL7m;ZrkwdS9k|MIBV_xXfrk+`gVB5^uC$sW9OX!U%C)Ht~9t!KmH>9Liz4$ zeTDfN+2QMLcJJ@&xdIo6d&u{@UnKPZm<;SiO~o(J>?h$oSjLBL1ge*^w3_RdKmn7L z2FH9_jpRrJsDxDS=Ow*3rp-__^NCZSbgp~`X) zX2ZtyeSTbwRueIIqJU79<4(AF_iCK4eEF^sH8w2UUpPN};YlP>w7#rcowG$dCR?AI z4mG1}FxjRQI%<~U;KE3t!Pp%vfLoAYnF$ExBg-)t5yAsbm=)+H+W0d^n-}Xj%OX_n%(%jj+%|4}Ip{8Nt_IUjGH-{frUv~N^&O^S)@ z%ih4g*wl7o1U>!Zt$0JY+4Y;Mm1F(L{!gQ;foOIy!gxp_j3h7$)F^^^?bn9Hj47?X zY@}Ojegmr=-*XvC;-%`*?5JFQB837=xbE*i!MPKb@wlR+A^i?^gA@gDJGHGpxgH;j zg|Q(2VS@y#FUN=?H#%}ILEUtrL*ngx2;;470V^1G$*#WDkU>+O@VC*omEG*X6M=@J zku_Oh*6lmkD~`&JSHI?K*hIf2&^T#P-4u(xC6j~HQir7Y)M_@BKFvDXf;ZjyV8AauEN*i0_fLb?O8% zIzRRe3LU}-< z`aK_M9=6X{nfiOm^*3UZND@|GqbS!U8{}LDzNU%nBBIV9S`2Owe7~F!1thPrLv{%w zm+43xs2^wR&q_Az_r}~zqVNUr@6pQ(!#GBXNdw~N@0V)9kF5jBV)wbvS>u=W>wjiM z|Cdt-zYncV2Pi?lo2kC<_xvwQ_Za_=q4>UU_wSo(gYOsr&(FSZ@LB>2)gn8SI6*!l zkLXAB%gZhAx>hv*ld3}%PcL}NcI6coMoxzgRgmms`ypCu*UMlmlk-~hU{tR z)Ab0DKZyLm++nx!Mhhm*_bjXGR#Ax`j~B#am5X|%wB&id`UoU{=Udv|g~o?**VvAc z%!U;xaL|wOhtElxI`8Vb8H=>giX^}u#$sdd$1tf$(J7Ld^U9YlRx~UOI!{}6W>jF zLb!@@Wd!WYGu-n6;fg-vp2vxy|2DVquB<7f3KF!dp?FcPY-*BlnUpPvki#pE{n6tX zl|V`7PKyEGdgjhK|7}ntVvgY(X-;7Q$ntnghym;i8*)wjMRbox*rBfg|H4w8f{(O= z=Sk=nS`04l+pnIkwU+cRtIRMKtR!34uqEU70)Mu?BejjBU$E5cTdP{*Fn7o)_TPD* zq3xwGXPI_E)v-V%0lq7JKRF!1?AtGgtJzkDQR72C`^Alz2RN4%u5W?Rq?sG0D7_XI z?b!Yv{jprZr5zk%62D?imOiB5)Vkp4MY>D+Mc_7YMDQ7nj8*0scSg!@@z|P7p<=to z`{D#?@We5NUj_~Y1qUxnODvE`|@fod5$vM;L14pS`zu3)@+E*3WUKY5fzjKv4h`vqQY#YM2c1%^O7g}?ulh(1z_es0gE!yj9ivk*)G2RqBI?Vrg{a*M8hbd zo^Pq*>;APnN2LOfUXqU`F*Bv=O6ZeLT589qqTZu2A?Hy|Q0@kG!z+|8R4#L%#wifi zkC1=ChQ3C~f>sNW`^Q0sOe)N9;=19Dfi95PWLSf6rk3zRhr%qL7b#OV5;~RWCKc*t zVD&SImv(Z>qN9M^-yUAap{!h|X3Ay1kOZ45Q>45!&HSqC+O zZVZ(Y4Tx#TGhe))w&AyJKd~ATW~L|Vj(O&bwdCTO4q%@_ASvFZwtAyyEx$&5;#OG3 ze9E0wAP8EQDd_qE@W=dA4FY629RQZ`98Bb0IFGNUz*ZNmx@d847TQ!f6E!46YlT)j z5H4#Ka|)GlSumR)1-{Lw9u)CE{o2NY+HkRo_|-j@NK`M3WX^_1;w|W-=-r(1LcEbp zwTm)m1vXiMd{rY-^H=;s5nT@zDn`wrPrG?$`Wy8uFm8CwMnTMKS#JX@@7Ff>jGEa5 zrmsalW8$zseUh%^W*}N($An(%cK@`~W~{XZsvc;u`D8M{rj}DMIW_Y#{<75AgpoT_ zXyMf7|!7k9B8lenX5t6A1o z3`g<#pD%(+#yMCIO&yt(h)%uyl_COLpU2;1tUgYPam0dXO}N)`2v%91XnvQ`4r3aI zeWf|W=qHA?_|^oLEF!3)aiS}Rwkj=-Q_cohFA{KD0AG9fLJxH@=Vi&R>r5M6J}U8f z=zJZ7a_j(AmS*^_3`1Igb7+WKxRb?F46G-cdu(-j*lR6q)wnNxGZ|+dm z?Z`iIP(gmmc597pnFgwp@t!MDjZlZ3)oj>Ln_{|DsrL+t2<0{|Eg{AEV0pPA(TKAfAs62+ZmKqk zRlqYdG?zN-A7KiUP_xq3w}+pdK*v6g5^YP#t__;Y-Tup42^aQiew1VQ@wwMu(S3yl zaOggN)Z4gjCV!i1;;ohceik@rb|io2HOMAUSp3J#@%R0nQ%=dtpq};xC-z|V_KxQHMlwJDjm&D!%PVU1EH>p})A0p+jL^Rp- z$Zs4BEp=@d4mn&yS8f9C?3k|c;O#1-ls<*G%N3hnd5lB$aVDvMPap^8j=|{zTF+)e zL+!HQ@EmjUZB@!7?I1SLUL*qK>qK$-jR(p{rgz%{^yb}C!A3%q%Y&&WmL+BD`BWqQ zA_E9t+!l%r1au7)@J4R%Dp}JD+C^S1vR(` zv9wPGnWPa0r$)=pmabti7U)8u?BXOwQ!434hMxvfE7UG?G+zqH`CikE_S;KE*}*}f zPINs862UY_gk%8J6EODGa=2JnaPA|7wbnkWpDR^a8_e_!ZtX7zE)eZ45tprmp8fMp=)|$^B^Yl#)`4Il*)vE=pIT;apo?>TjaO)?ZDY~xE|}) z@Gs|R@@VK9iIDcFkB|&g+3*PN_}utxhsGe#%DsYNc_fkjaoS4XK%7rzo0z9;%S=0! zrM^ul1ZQI&S`%*4VgYQpm~qAaqPgXAhp0!!3i~8aUYH_d@%p23KTRT zS1)r{Y=B{A<$nsD#ndW@RT%T@1-cajISUCKjjXrWUA1mD>`%ri(sf+3%W?G5Vm5#8 znz@d7$F2_M4STnT#QSw?%~foN+G!WTjQb~-GKy>Iz1UiQt&0FDNrE4Wdw|^CqwY;m z`5&k74!Q?N2df*FT;jv12KH<@WxYrp<2t-(iJ`8x@tr!cEIu_RgwQ^9_sU(&anhug zM!3CBO6*0o$k4_yWMfoae11@pp%f4@1LwbUlr768?d&*h1^{6Ig9N)uBh8i$K=9TZ zMD)D0_yx+e3iZ3UG?Xr`k82-D&M1eE4oIyEdzeLfDG%Sv)CR}Oh5B9q9NyXR?h4ow@`Y^cUU#c)FexuFZLz zD9h=u;)=*ZWBYE0dWz>>+y&ORocEv1AiMM7ayLJiPJ7OBu%vU!;U1K+m5H;rh=gZ) z))&@&7KVL4(T(VGhx3?Tvd%k#ZU{J44j-cJ6n_;!!obS*_@lY|# zO+M}M-j*z2V-L>%g`SJ##>3IrzBLC4IP5IjatC{_@P!I5&FmK&hk8XP^#hY{yejP{ z4puSx#t!lA28@2GaTN3fyuaD(N~PC%-FLWqeaQ`V_IYEUcP*9M;4Q7~(S+;TCK@qz zv~LdiLBB-gl4sTjWcI93)u3WHd?c0@t%%i0{l%w{#~!8?k;z*UF>)J?t$$VfN#VbV zHiAb?8{;LfN~zEp<0=oMs;lW7xdbx+tpl?W#2fIS|rIL2=7LFhZQA#$|Qn>ZbQ zJ|7xp!M$`0CEiw~_;rf{FwI#4jmQ&#e3v#hy3?g>d)0isdjLNiR5iSMXxX%?BV}Da zHQT1_(zNdxXg@VUX4$nw;KCjx63`*XufK+yJ~uYgGNfiMC@AX3S7l6;A=alCuNvh! z7U&*L+_(nkf;3GmM!l@b+sutewRIQ9tPf&WA#8c>!!jOgx5^uwm3)h^)+FYjl_i~J zl)xHm11ypVPMH1UrUoRK{~VEs^$=C@ovSS&)9v-_CEoe{4yT11*lVdZHl$JH)3yz@ ziQpb(mpD)cJy9g@UXe^^ym1z4igGvV$u+?-jFE#Djn${B5M_tV`dOlhM>=U$z80pl z%SYXM3hS&yw~;Za&|oPV?Gh!q+rg!fB>r4bnQMxzqKTMP`qz^3zW`}KmcPk@ zKec$0EEGzdznx^kI>5qrlEv?%pCpU-M>}a2-$!>l&0@G*Jf~Rv3fC|G~4LW zJ!ux&NXRG6VskDei)L&m$zm^iI!U%MFz_H*P=cQTk}TT%x|3|f?X?^v+Z2#;kSyXg zXFo|6?NUyXZIJTqBw0+Z){|_K*I z6+vSRM;O%LOx>qDJbJ(bRY*wy_|qwLvwTSY3#^Tm6zCpkdFG2>Y6_x*c*l_I2{I6{a_aEHDJY2ZK~4a#;&;U}%?=n^66P?TVj;v^XKT$ALZi*xUz?qYYg{Ws`~ zgMkt5_GWYm7D^MDMUs8;qJ16fyZxM9?!hPCgy$bucGxkih+Zqg$dUbySVCY!0&MDR zXI}NE!ZwcJ6U6lL4v#qILLq}oeub$=Fe3z2h(*GUvWfIkQ-&ptAZEokvKK# zY`D@tsQ?}E0QhQ>jd~sP`$6I2$LMz<*AfQ@)T%T(KD_Nq#LzoLGF(6Lwqik{ zH>O-~bjnCwk%9=#c%uUtgl42Y3Icl0SKi&MK`}4t_cFK*(Qs@wA63>MoBw*g`8LEv zJ-!=1iD7QMO}of4GC-RqCURZGx!84!n~d0+#NV&)zgtxh8NX9LBHP)FVm$r4n4rlc z6i!aGH$c;!q9N=@lOayW7Uc5)W6so{+k37la>{Uhw<`hgn*YI&L=}VmL z9RE9eG7gY=X{a#5S0k~k8)l(*u);>dE9NYIt3`lNKzwfHrHvY%T~aF}0}9<(GVy?= zQ1j;drrg2nl0Sk*$}3G7^p|jr5F=fXwv-tORtMbDLwN)f=e>GpmS$5UIhexmr|gUC zbTrwYBVPBvS8VK&b@SKw?|+<7*>8^P|L@4zZ!gmKK-%{}+GE9x%+mPFjjKK8`ET*x z|9oM#`~2r$T?;JuA^xQVKz{Qo z^*>WQdUwA0!H|NecM&SJ_sF8{^F^qwAjgBVUkoX!1 z6o>?aMcJ+|zdmtU+oKVnl};MS0}L)>yZ-nhqB1v@x5+P^L4f#E_K440Op0PufbDH7 zSlYP9tl))vP)dddgLcMAS$?+1*O(c(*V)bhB)-Sg;DuYz44HXjctnF&Z~guCd5h{% zln+^G9@Ya-1=}4q`So|M(HcjDH8pA&^s&zE_WSD|rv%W#w6_C64A)4W z&ztKXTsF#UQQ`NxhX(M4)%Rb30S@anEX8fR{r>vA#w8#~Au5spxXN(}TEL^XxCBHC zH9eg1^71pDUm_;3#Zit>Bi(insNnN!#02KZ!PpMt``4dI5cdF$D2Gt-$t=IWZt))? z7`jYK=F+TT65>g*YHhJuCc^1!1d?}Q`}#Xym~x}or65sQ1o>zhTz%W^cfK$bfdVTa z7qrWD0dRASX!#wxyO_!)_l!beD>sp}QICSH8fTz_JeKEQyT`&!(i<_WC(ZVW%p}q$ z2BT8%IOEr+UkZNMEgJBdfxfAIqeeEkp%7O>1YuMGe!?z7M?3UH88}jB zI5Ty9+}Va$%(Xj?equT_CHL}Vd^B`wm@B~~OVp(eZJLxY{lw=-1GZ|E832xb#sMmr z0k-GKsE`m0&p(p6x}1ndDOT@YvlHvv49uqET?LOk2pnxcUa zFpc1f1{_<~aS7DH@f`kW@y6+$b;bTPR?Mf;MiFSjpXcE`K$nnX(3rl548D%@l*^NRYk$v0uo>WMo zA2MKvre9{51bAlm7^i;k3g~(ZIb>rK4%o zu-_GxF+rPd((aSO4TE7yj2yr{k!2_l#YBG{NS)5ktV=T@-bk`kZ_s^)+a2vHL;l1j z7geC@G~@C8K?@pq7MZJ30}u`os1Y|>AF(PwKo&>3--@_g6WAYTRwkJ(H@z3W@lAgVMpSkJzyRJL8I>{Kc48s750E1g#* z6Iw4`Ky`~=-nC*pKUF0ojJu9X%FWV(zoz>g?Oea6K<}@*a()g&2LO2mQyLH+&6CMW ziFrhqUYD;baib2t8B12EeAI+k#p-Kn|Jk!EdFK-ACT3(bP*jTUa+tW3E0MuLzoxby zEB4eykIk5Q&tu{Re7%gZz3<=BxvO|51qsX@D^WnaMfXT76dml|UI=C(h$q{q5d>AT zyG>678JinxmMg{5z26W{ihXh?g4%OLUAI$WW=Y+z-wP2eMDk?YhJy%PC43ENNH_qU zu@PUnfSlc9JPK|Z2zL!x;hzN$z&RcD0W25jCrW`EQOnh&z+t*@A&{d{^W}C7=&4MT ziQM~;m?fyy?I;99j>pg&WMvIT-6Bo{tBpXR;t4>VxiTR|4;da@&O*ix7Kk(_)I_V! z^6YoeG%v@??0osp0nx3<4pH)nLa{L_ap0b=nB)Qlc1#q+V$5=7@(wI}acAjHtz7R$ z%gR7Cr|K-d+hGaHSZd6>4 z@SBiwMiS*DrySf-c$pUE^d`y)q8z9>o##rFgQ0?Qf>REJO=R+(mS!{!r})wgMo%Dx zPn0u?C?`7QfJ1hA5{yZ zW&?(h`zd`YkGGzu7-obz&r@C%qknJ#TH)KtCD85{F2d*QNxHaYVeiE<$;4yl08BiLCx<}0TsR2Yv+o>6Dbyzi!ut%NIXD!Cn%lv^urrWO zJ9~q9D2|i;VWz2^?6IOo%7uNxV!}h=?3MP6cCz1fr?%V5@xEPG(n(__og7!v$$2H6 zTvyVu_Ch*JX*o#;Q4d$rL0rp~bV^-G2T>Cj(otEmlXPItyOK_>E9orLqscO_q=V?- zE9thx$o63a>gz$A)?(og7!v zf&2AJIytYTlgmmvxviuFh=eQYEIYN`R*sq=V>C>wgO%>x_}HSG+L{{|@5aOH>(p~S zQHFQpubN6#nhpl>{59+4^?kC5oAop*rvRA`@!ir}gBueOYT9nbS8~~)fN=z-kFQua zv+nQ+5D(?uFucCc4_*iKq&riM$NF1Y+xhZnrq|RnwGi@?y`8-c72Dd3e6LZNU1%2{ zNL0J~@2%+hzW+Y__jqex7Gj;~ld_GG`H0m^l4lI`XHCk-R~G)d4&1ow&WkGsPnvDc zHAxAVHYWfbh0gupiGnf#U3c=HOp^YQAD zZ9E_ECvZ7ocy}t#z_ZBcBV;>$@b37P6Th#+zAgs`P!c%P6teG&TlSDd5%S~hK&=N( z!l1Rit&1<0rYL2J7vH2d^GOSYiZ~9xUpQh zvEhxY>O4C)r?02T>{yxKgLYMA>zF*{6zPa}Ux+N*OmC@5O|2|T_F(F0)LM}U5m^DU zP-rAwCw#nmt|$rv`(82I1?{xm=CuWP7xU>H^Dh)$?(B+xctuJX{{hpp033pX}DTmG0hbE7v|N?HMX2 zC@D8f2?`zqIg0!YD1|M%q;Y7Q; z{i%D-b5GlCa-_@acqAK=7Ejp)P3#YgKeX7S1=x48>+?nJ?weB_?108I?4?hqyX<5} zX6vLCdUw5@)nuNRHR%(uc2tu^|8U!ETCDw$FxQxIg6_~I!>vXVA_Zl1>lC2PL@&66 zl3!%J-Kw5X{yw#3ydVAjs&@156+gq?q-+VzWr3iscv;D6D>};+0fY$nwUCcTos&23 z>vd~Lnc1fcnf9bSDZUx0Nrjc{3i|%tIqR9!D6XDGsgw_}6jbpvt%e*gG-XzekD)|M z_f9)!2bv!RM0cJV+L@;;3>=rm#ynj!&~mrqWK&bqVf>1Dj-sxXJQe ztwMWOt9HFHy4tl5mwMsYryo6Bp^3BXjBn7E!mIe+f6-NW*YbkjeL4K0M9Y;N?!J6j zlosFolM$z;Ix)SBCb3A6nF@#_g1p>)^I&*&ctOs>tTRNJDb5N@j5dvF1Y%=O8l9y} z$8@7#-TZQ+BLNPIFu6$Nis1vyczcgBAm2bf#;8*Xd%0^S3>S@*SjgWf$=gjci-?O@ z`=?jr>iB=M*5_3GX=KDFRQEmP7e?|)R}|v{o`N_~WzaxJRt7>CL-hD^R?Zt@qhk>Q z6`cBQs**W>hua;gl!Z~la?(RBi~9WTv?u5qJiGGJb8;}{C;IpyaA4qv>&xz?CD1~z zq>w#7Pe@YU{L+u)#2OT-us??I9FD2vCa+9N4A8Do>jPIFJcKm&m7;72;k>a~G(%s_ zq+e_ErxTl5Zcb+LGdLWvZr9{!?w{2_W_~ z>2WSTKF8Z;*t>HZ|J+v})YBElh<&CNy)m7tuf)@xc(g=3(AT&X9ca)b%)!|~Kwy^& zY4=PkOEAeFJJTM`shoyAc@&|caDby9`Q@+SFx#zLdY3NWmCYP5SVy;$H=6-D!yAs^ z6*?eIGB3tNO6W96WwBKBhx;8bA=iMIZ4H-E%sfW}t-#d+^=#8JQUb`z^NT-?aG(?M^ULuNV&oArfgp6KXvp-%w=WMflIQ|0y73`~`k)4N z@pk)G`|>*GafK~Kmhxyypvj$>rXOee(8lMqVzx3X=ILwCLvXCoFI+xijw0+Devc#- z14+~{x-E~t7EseIW~}`Y!L%(HqAqr-KWW0&5;%($$zy1e}Qyus1JKE_9f9vvQKm&GS2m8$s0%nOz+O|L7`EjS(K zh#)b>@OH=e0Or&k7?<+kz@t@c+=QVYrVY#@(bh7E^NPffSiktguLbdTQyf^bwyj4{ z(Afb4`?=!B3L1tAFc4xniij6BR z7b}dQG1$ioGZ=)chk!dMsfc(paj~n@=j$Y@a>CK(!A5fmDzuFy1d)g~8CzKV+4IHM zf`6+%?S=-QNN4cP1zz^^3SGPL=)yw_=>(Lh%a0(46A>2|N1?I+5vX=ILJ%q@>qkMi z;Eugu>GHgm3(W355s!x^QypqoXENB4gw)CvqnGP-0ky>{WZcfc86bZg^P?%#YGZ^U zpcG(EB+k(F?biaQyD`}pI#WU98WR~#RNBugK<*|R?*o#k$g6Yw##s0yRjqgu$7Bv> zMRRVqpFKzvHw9*_mS57RpK(I?@17u_jJ66OunPTKhyyvcZT*=ps4UGGk+ifBbHSm% zwL)CJ>+f{`ag`7bJCgfs5MKhk_5&WBEqr` z@gW5L0mzaobp83VBsAxyUouQ&S(1XhTB*y#-Ai=-Ln*UIxAkW-fhtf2JM0X4gMl?O zV%)Bq+wFH|v~=d@Id0CiasEPbRBSm?z$nqD?qM`6Z?~VFd_8rufi|+N4UKSobG!Y% z4+JV0cADu`N8|j3DIUu6giI%+0pQbMm}SGBuD^3h8i6K=bI1t2#uxA$gB+LNU!PYz zWobl69A@69LS=D}WY|gc&{?V2fz1DW_w{*2QQl?!w0SpjU|8^sv(%ah=Wc2ffQ0jcacY#-%<#&&5 zzCxVBzC0Xet!}rUT{fHmsuGnn=Q2-jyZ!Fhnkxb;f+1yJ54_2(zw?DF!mAFsPJl4% z*5A3LD?}_1e&{`hmynBk{hiv>6+Km4IXQIPOuzK@c6;u1hiR3zDX_po5Y8J+>E{hc zRq7+nyIG8N{oP+Ufm;1CfW;>dKN@YjJ;|%*6+l#gqC4lHn!Wt4YwZ<5G~*uPPV=mb z?fEm=(goj?cMJIq+LWRF`m=B272lLWu6mp*!tygo{RXFsJZq@d2%7c_#`*i}4)eM( zQ~?%x;Im@eZ-}UO)Kg4w$OQ^8%jVFL4|?W#<;y!XW9J3@22%NXLq*jBN5|ZRdwFT+ zTN?|!ypIpw;Yxul-<-X&Jq6ks9Q(4mpD`#XV|^bVT<}h%0+VKfya|9=ic@%}`k)-t zVKm+^*Y`Q)1AobTTtN244#cFf7R-rCFa z{J@G)iZh$lUn4aH|9LmwL>-^xy59A5|J;Ics;odlZ|eQ3K#3+qRK~d}?4#WgQh8Om zL!?e!RAD9a+$e{S@AVW0M~^Id6?8 zmZ}IOImWdF{`&q-+*hbrUAOPBZUW>?k`8^} zGoHRA{!mXKCul5Q@W3>fMw7Rbx8rtu-jDSH3tMGK!Li{B zXs1hidEU?6f+O3V4S~8h;^vW$;PM{DC+Izgit5Mid>!9A5o4j~44LC>TLI{oNrvYW zuNxSxlu$GYPU%*_N?5;2gJk4|0JxVq=WTuawb%D?Fw2dJGr+qTF5=N^)Z5H8EUXuT z9N<~D^=01A4!BKOK_+_k(5?a#FM(zojhRXIoXjw@^F_BdAM=B?+17%|26$~Stf?{S z5pSN);zqNgidOoK5Gg#>gh$S%HUrIEgI*?F6X$k)l{UKr^%OQb3Sr_B1-dp0F~$g+ z)phBDCl%RQSeDDnG{aw@S?$M0w=)n$TFjn*U5H51_;aV*68@&Z8fKTb@wF2Zc4IEK z5kEhPDP4Z_IXKkpMpOO}wrq=>LkCDL;@;_mDvZ6sVB*Z%_1)L!6$%$SfS`M}3*%!3 zQ*3}0rqsyE;$`rVP1+ac6GIl6HG+A&60uh7bs|0EH*Gc3XjVgP2~5tK(%(;{tZQsR-Q^%4>4jS36&h z*<~rt38Ht>9V`2FM~#&_gJppmSA3Z;;ba8OHEA$9q)=2J`~{iy^9{%qWy|C%k5ong z_}Xa}>(qV}J`N*VLSDr3I`?-4f*njQf}pqU`p-18=MO)h=gT_1D;6yBg$1+{nxhi~DgeCy zth4~A%}!-&dEKwO2bQd>LX)6_Id)w>5n=;#t)OR_&=S4cMoTRF#YbXUZOkYijQcU^OVe|1rf z%`eUlCrLYt6*K$|3Pwt8yS>iu-QZ&z9gd1*A z4^aMxox3J(l~#)Rf^aa6C^N$Trf>U#TwAm;w1Qw1`x&{m+uUx?`v+FY*||q+@lZgd5rWnaP4f^o zKU3@L{N4oX9P<4hp76k>HhGL43}^GL0)b9HWzw~?{%$H{0>=<$AV2*BI-Q?d6yy8M0)L5FaqJ7^m`s}QoX-`;ci|> z5z>@HL|G1aff0Etm=*!}m~P7%E^oh92wr7EV*W7YN6#WYKyN>(A1jgW} zPPh)Yly~9R$~%3&`ubckdN(D=3c$J&JLdYc`w~wuS*4|eA0gxFfcH9n=O(ZCt)18u zop>rq8q^f`o4XVMe*o4$x$*V&*Bd%)3Bv0^{w{?!f{0Yi!lPK&8$%1yb_0ez0D=$P z*bJ8gPD5s7MP~Io!g11?keWIxx}7g?pJNkz>lfmmDHO?+e%+Zm1C+-&hoXnMP7C%c z6mY6q@F8&>8fUV9l#hQoUtfS~h5P`7R$Py%@D7D5cL%cN<6r#o-Dkdo-ZDR@D|~`* zEt8?u2;igVWinkKtJs-~c|pJZe8BFWtUdC-W&zr+61$M zc+R1PYPgRuia{{5RBub9Xh|bq}lUT8WqY$%^ zM8kOi@JbOZ!OdvhL+#ny^=)qA4GS#A_W))9K1JY-2l3I@|wmzQ~(FTllzaD#au=`x`38L^IE>hUlB`0H~8 zB;J@@;Aez>VffipQl`^dgAl$*BU=w7w9DJHdfw2E8DY*Cnj)uhk6ztm%Bc(~7d_DT z`ZCsO!6=qgLu?M6ZbhMbI^JdU?e_TVj)|YUcQ2F?U)w8a_^>L4oU*hMV zkxD;dES2^F^m&$j7|g`s^YExP+%AeepFJWQN$2*nmHtUP08F#Rqlaz61EzivC^#j-S5 zN_qbqRv*jEw2nf!fw#1dq{L&E$9t|#Ed+Bj0JhcD<{6*Ly5qWWp;TN0ZH>eWQ7)Ub z-A4M_Q%?455ro&A3`iL!@yHQbQ%II9k>(Au@OnHbj(&OXwda}~Ni>x`rfYghIMYkk zl#zR02rik?b01FQ2$}61_mmSlq;82L_v{eh0|QYvDm=~fKu0q!YA^4<_FNNB6tUaP zmzdHuu_PSXA#3i)JwXH)A$ANWIyJiN11WO;FYi-Bxo429X(Gid`LbY=zCWjOOxkvP z+i&1Y7Rg(xi12S(RNi`_e*fT#Prss{@AE<)Yh*aVi$x?T@OGZ8#_sM>C%I?qbj*Y~s? z;K@VE7xtb4 zT>*`t9x&PrSOW+3=NUW+pLNps27hmgUj<5G5_&oGAGBE;KGE~6c2=7JU{SziL^~gP zo~dDpE=#pF+~luoI+eH|Y*$Tp{~V_iRdgF|4xiuyF)4U2NVy_PyR9{rh+qVfL<5?S zaVnGBbi7HA96AT*00l80`<~giZ2If-mP7ZXsYH?fx-JwiB92f(WNK1FI8N`j=FB~% zi|t3BuRB&4_$yVn;enh@l6C2xqWQX0PbJw9hF&O40>5PU#G|>V^d%*_1sv3>(nXPh z#=|$Z9G~xwpm7qycI*DN=b&ca$KU~7Cv(GP_spij@yhH=n@vD08J)#@^O}) zo+$ak#h}h9Zqyv^!_?+U$V+S<#Jc?slNVtnB4O|*^ju;{MS|W>g1S_P0};MrAc{kD z=wiSfG*K3TxySiC5N{#i3G5B4xTkVBA=b=hBBE7HLXU(MsC#!pHV(%jYC@#l(Mm?) za3W>pTdE_gc0)|YEX02%othFt-aS>A7}a)z^Poh)StD)L2^1V{V?}v~qXnJ;E6PvD z83jYCEG;MON{GJX97<@qtwptC<681UG?-R5wF3-Az?q9vRY1@-COg5e3vVopSH{i; zmP#GR&R33o9E1_8l#ZQlz&(ePm7)vQ)Y1z9x&iiFLoaVa$lyUfggi{)dlJI9P-G4Q z4HscsM=T+dS+bBQ0K*GM9BYk`4UHo}E|RMcrn`7~03fGA2_=e0C9=5em|_*cb0#VX zAts1dj8sOBjTbLs{&o`oW%sw+#9p7b!3g^f)HZ~iSRMEpIu`E)A?WA+!BUz8&te`@ zaT^6Xqw>frNfcXzdXCDYnH5V0(}$#IJF!$L#7K#}hoXSjiMAuZd2ez9R zlBVZr*;q1nRVbxv@L~E5io*@Up@7AMc*({OAl?{jmx#z8s7e=JhzDX0yPLBdUm4`Z zddZa#w!CG-u3ZR>&FdKQ1++~WvbHi2lK{9y6%XkIX9=t3Sj#6BY`2ZUHEx;hldFYP zJTOHWe3Yt(DsLhDP~MUF!J;{tc^4BtgyeTV zaAicm@U9=J=S~tXh$jg55F&?|T|*dU4Av*0+%0!|?4j_uXFVAt$yj}&jnlDAUSh+V z`|t+u3b8t^nu;|UpFTueU{wgSW>wtEZYKimoit7Rn683?a>3{VQQ=UGC+fDtPa~p9 zSoVX4xkgQ%0;797WfDdJoEF-?krOI9LExF0w#M)LyUh`W@REQYLNMeuatCdeAx_dNMd{fNe0 zaH6b?R2ZK#h&K}`j-DKN^eM3(a4D{Vc0ZpqRDXD%j99_mqDIu}>Loiv5I?A$H+imq;pSR&ZsbEgEXF6cK zkP|&we*qEDomk_6_VLMNfdTIw(F~(d=W$yd0yktK60E7}7?W?}E=;t-;sp|L*C0~n zPyvOCXeFWJVzVGy1?-zS8W!+S0JnEOy(mo3&#Vnz6+wu>c49MCBEq4ax{!P!5`hYo zcR1L}JnboXSVRPj9QKR?7}p0wkibI=>1-g)j6i@Gs(qX(DULx57%H?01gKi{Xjg|c z#=4^!9CkSQ&%J8qATxfBD@FhFAP{O1(yo7w2*`y9{$RNvdIIl8wS{ZWG~dDU;Y6{L zp2fGPP!6%q$QZBH@y0OtqQa-8NL6Aj_^NA16_HPx(-)%OZdCR9T-Wl+P#nl>2E$`E zjpiL3szxwtIQTOQWx!TI>=9(sBPyUvz6~YY6BM!ONGC+-VC_0Fm@yj?6qOE5q98a5L5!gc1ZR**MBA9ZMQ?D$iDvFWWfn`y z&80Q+Bm{Jcps_lMVbUSQtCT86+>dwz8+mf{z#BnGGh{eqy%7Zc9)v3!^qC>@oF@_q z608|JbOWp-(Qh7c=Se<$g>aY3#bO0MhD;BwJe;Y02XE}FHHEs8EeF5EnSBKGQi=bk0ZFPL`5RI zuH=(-l1xcJw!#qTFt1c-Cl+o*2AAm=#*} zj^bi}QCN=v25%57*SE2DZc04j~&oHnY>n^VvMJG13RK@?~EuY+t)CN&ev(4 zy@4N9se~E9Aai?10x}k(vk?+8Ev~P>K5yd@+nj0-c_`=tA~q=zl<)mtzyI_I-Xb(j z*m@DSMnEZS`)#gk-}`cFQJ-osuRO|6(-aXGTyMUv>auE2IYtzko-?g&T`{wC=q)>U z_Q=h;(u-fdlESU%iNezil539}ZJZSF^hVm{OxPth>kZ#&aP3n;kQbs9_Ha>6&Pb%@ zECmMI7%krS9bYKo$-G;nvH)s{~+0DkzWtZ+CK-RJfs1{kuJzroH~Rsuq3mL zVVwvrO(y-WOHC!zb0(@a@TCGzF-S&uQ!tZY7ngxiD_t7W*Ma4oC+`do+o+{+A}vl_|%4c{p zSgfW9%pKQ^&|No1&mD@(!Lu*%kny*}5`JP8;^Kx7z`rp^rqU-!!6OkIHEljZS> zl09aW?aTE~EKC%Y(}>s^r@)xuE6SQ2Q;>bw&qnfsZP|ujU8~8o6b-}|V04AlGu(Xz zM>2}}ApkA<%HFZmj=8;rr4}=bd=^2P(e5&ElpNyhig@H=8y$nN93AIbjbC|O`%j`sXeqauvDS-LnG>?;( zSrTJ!ei?JWF4U7S5T!>Ub&IOCA z6hh*|9a5_o|4CZY)Vvzc6=ZH%GiC`~MlG!A63qB^#X80=my6EPxK z#3J+xnDvDR-&9f%>Mu-ZU;wC7N88*G$>4Nht0^ZMF&9{uHaY`hdCcs!pBwj(wtK>k zXE=9oz0%W}YYWqos-7Zl0+SzvKnHx9Oax4wTG9HRd-Y*}G|`h(SPuu5r7DDc;?sZt z8*5n>78l1-_dfh=HjZ7d^Qy>_w~VQID=6Y4MuhBJTG|A6{Qv7K7G6+4ax`;6N)w`F>2trI-YBhS;N}g#$CEFV$RE# z5!P+eZ^b+%)(;|}(BmBhahV*046nm^k{+t##1VbI?6`5j-S9AZp_NesaqOHnJ^oW= zl32DSNuv-ZoI9>_@p4C9awr$ov{A7bR&(&5rGPlBN)xP;L*cV~o|Np!U0vmgz?!EQ zJyA?UI;w`L`a@P_DCE5;J%lw;aMy$6NDA_)(?dsw*B27{44~4o*YAmpDN;=*f+G6w zVedWa{oqJ%tX&tUmo!tba!EeAAw;9HS4TpS?Ne!3UIHb#8pM(`qsycZrJf~Fh6tx5 zxkM%d>7jkHQlHleTIp=NZM@&vj>YkBs`&q6=her6*Y<^++EgDRF682g3$9DLxsEhYFK*G)mgZ39?XQ}m{B=F59|bJW7`_%O{`4WlE!XNuA1=Ko$+IzJgJD zVeyJc%@4ZMI?boS7Z{EhFEFG^V+w&sLdi~@tkf903NnFO$;S42QB8837*qUFZJzqp z{NqC<-&$4WKaW#nbtOK3!$9@;Znhr-=H6RZ zp{ycQO!lUyaka(FN$7aHsn!qOutyC@UwDSON>OHfotHPHAZQw_Y9be}5eX}aHjW^2 z)oT}FfBS{#e4ne+Ciji4 z0bZeGmFg87+7ZL9JEz-g<+8F{S6my~s*N^2s;g9dd9O>iGit#t+&1(MdP_y~DpBwTSSkDX0)yer3Tz7O|=B!*maS>^u^nidJK)yOw zC&a1x2!Y{Mv!midlH=YwMPLBk-2en?kx{@b!O~R84W9T8o3xUXCQ4s33?VAE71_CT z+^?v+DyOY7CzI)}@QX9n30?)(;YHLDy%5ZMnNYhKQP9bRCs0jTMXj?=)ug+<$qO+N z!GKskdMT91g78M>T?k7L=!4TE5*)~qpa<6_QyTp~ZiTAQ#Si~AV=)Np#8{5F$97bz zR~->}u(&hK3&!552==HF!-K&Vm11nN+!R9&D37?NOabY<7EdIg}y%aoSd$+`3AAPLOWmIeW@lgVXK>f5#L~} zkv;2Jn&S=Ld3~DzCJSaWbh+sfAiu${}UV~zXDI@kYquuL1oA*nEAT zAH0r8ZkOiD`jkQ_@uXs)_x{)K<8|G4;#5h~;%aYXM*rJ<*WO>Bw*{BihB%zqSodO5 zNl0F@_qM?60zMgM*d3*^({ZDmL7_xHz6P;Q$l$bsR6j%yhLO_Qq6;8!@cJ@?@&U-iE2YIH+n< zH2oVM`n7k4uQU$^?;m?SGxJCi!(?bOEe_Jmz=kvrOychMLatSmhK+kZRjTNhhdZD* z9ny@trDL%)2TW#)vNUaF!BCBt!G>s_{Rp0RK-UM;B}m9Y`qqj&zTGBA8{Bm`Pgb)j zJ3_0Ic5_PTvaBj!qfvDs2u0QRXm+PP{y{|C-FZe;1_Xk|gu(bh1mnYgJk=h4FKB9( zq^GIJ!wTN@bwL^ncbvcP$Ap#9f+~|H6;Wo1yrQ-$aXO$lF1s6*WontIZ8TMfREaPi zxDcw)bhC1&S+Sh$NUl(W7t&76pI722yPtZWZMa=niL+=rjw1~zz~Mz*{V^WFe|w>4 zQjHR3XlY?voC9`eLa7tESLONyGkrdeogyKVaGb6ptURaY3GfZ|p#93+?A zPx&!85j~4L?$vsDTW?-IHznQHoAg+o_$+4-IYNrM4es@8k*48xmooSE7bY(8a#Cg3 zQTsu+ATOmQ>SPTuB{0b$QszZWSwOrW^XIHIsJ>sN;MkSTOl8kCN$6Nn&EYqzlUTNO z$=p+N4qDbgLM88$LbhDeBJkFqi%upMaf*e~w3Z0!&2#RgPFqym*Lct}hx{ATP7d0l zFb~?~MG&5~;kXF-%aCj&SrK7TJV5WOmU;SMv; zfonZJ6yfN&^fk!#g;L)`EIxV$i#OF>6DYGw0CwlMSf;SV-FP9S;u4jBg*7xg^6;^no0mc+F#sS*!g*P0u_4^n9o!Py&(htoIie38sTj`1H>7M}f zA`12O{nzKc_5=z)aD+^5-QFr?fElTV^JL8T^7>2A|1vsd!iv9Do*1&11{h3OGV)eg zV|kw`{MP{?yH>atQJ9WYx{BX-m@9c3z}mr+wG1fuhio5tKawto-b;gA`{#mPSNy4} zrMk|^j}u)#&#tduR(D-JRiACHo<|wAWIdYVHuue3x@P=|Fg`>cvR2oFoF2?)f;>d3 za+{BL>RG5mws>8zWvGGIzW0Zd0jm8Ud-qT-}unRx)|g z;LQ>Y)hp1?AsdNLY&|#od3gzUpWFiBz1@?k*{(#K$W10TnE8^o)y!TO<}5?vkR)PF z*=eJ@_$S!Ktw_q!HwSZmy=g4u_OVE~WYs~3f*qOI-JSC!l|hVN@d!b+;8almVj1*c%zukI&eXgHZR(^BEkO(bB=IEg4TO?p}u^@_~K37?^V=(#+*C8hE44oa+ zN0?DXHWJun>pI|0yGfm-oH}aJ#`kIpQ_s%S8I@@ z*5Plr?wQ+htvB-&$P3>uej8M>JMx?`y{t;~_*sa;u5t#sNpf)qDAQ1i#4>-Jf~MHF zD!kRYd41l#uEpkY95M)JL8ftX5WYmXiOQ;~-6@fa*CfNUnGa{8wSk_3``Ot9NhSL|+_UkQ;cvJ8IiPC?Pqw9k z2a$4gCaNGBejvJ$Bzm!;quh`-JNxagdjH9x5pdCXt8KJ&?+bK(U*plOEC>oEW~uy& z@#6Dj`fzah`cx@|ZD_lK+k8Yk#jD{=->_Ttq@{Zw&+&cXb&&BynE-(2vCo%TQ*YIi zMC`a@a5`CvD-={_Gw0-$S)@s<{zr?)`7K_xZtFd8T{$ zrMz1gnx9S?F%CJlypIpwD=OU!CRI6#@w@Q6vk+8Z>)CFvd*0eo0O_rsQP+vVP7+@? zIJ@YMSAKn;GrrX?x|Ju&LR(;MoFN!(-6@?tEw8^E&b_&;A~PT2Px}!p^Ei@BmoKUq zh4yp+lR#|0O6a%hM@#n{&-MFHwzD_{1vgM8vM7M;w+!bX zP3#ljKQ{Quyg(l-R2Dbz`u(Rv zaj8vp$qQBC1qz@R-NM%W_)bR_N{nbB@>f!SI-YK%O1gTk&S zHeDi4T?Be?lS=XW2+5s#&_y+&>PKWRV}IB&=i@ek?bbg9!nK1Z1p-wNznp{PtCXq$ z`re9*Rd;blPu;DqGO3;b+xs<*XKtCmcI*H3d8<~Y0Y&j!8i^buGP-f`tyWo0?)r#I zfk1+W+k^-SRz1Kj3J7T(|90!1r+yrWoiHXg;$|-ySs^E=@sg5rYt$W1R^mcw8!Hl#RFkj)(hUY2+I0xSy;? z6KR~pC&oEO42|%K17kap4S;ms=-Dzdjsf4e_PpI{+Q}Y{l4?9&m=5Fd+0J3goR0nw zi7MbTUOdrm0)S(74%(GhjY*k{b{JLgRdukx5d3%4M?*FSW#goI2N=0sz-Jg748>I+ z$7E;sH3{&3Ef6S2 zIVqznsSBUWY=$`HwLwujMt0JvL)=DSkWL!5=|JPp!J}TUr4E;=dD0WIjhRjE`4&jr zrkgV=F12zll^(8|ytG~<@>L5*jupKkoepr8y{daqW@F-FWl#lT|I}Ndo6hrtLFIHo zHU?=jASf%WwRAqtOw=MA6=aQ9Ixi|=Cva#QQvq(37?-&*ee*gTg*p<{yDD`F*&v`Z z!VNJK0#pUmudx(gR7@q(;YpDmHy#t;930s)(e2jrO9eB6((4;BCbUmTR%KRgVs00| zrvSo0KoJ63CC}MNq$vV50jPc`Lv%6(v}vE%{L&aJ&!7nJ>=BwhwNR6Y(U#Y}(UB~j(?7{US`$8*BO z4TK3|&4)b31iq?VBEd5)RW6@`91y8j#<7x0_`7E!(~{L#K&mJh5P%0mkc6ypI4?`Z zxp?!7&jE8Jlo-FVSIoQ=&;%B-a_v}H_ z6h;zQ3&G{ny@2SGZ9vSx-ODJ#qLKl4jZkLGY`0tgMDuFURXV`kz-*dA@H+t%9kdC6 z8x5C0d=R(q%-<`hyGfHq)~^6Iy7EsEK>(ErgoO%R2%Cn4BpnmerV`6pk-fmY2?U@T zOfW!tYsJ+KtO4n;xDrBO;t-;i1t4Yxhp$>KOiW^%XOjh33BA^63}sy*oSw#*q>d|V ziE1N_k~y!Sy%tsX4oDb7kW;bhcM`+BzU#7j#JIkWAJZKITmqKj6f!t#ai}iAP{E$y z>DgGEq+$om)5qe)NKQQ!&RQi?v+BXDC15pMY!0IMqpuD!>cbv#+^C*(;@0wc#y_*L ziV(b*oYEQP!}qVNzujhs>2}reV;#`q6NoIl6jfaysGh_SY$HYv?gX4B#`jWVCNCgF zC5tIc>Q7Apw8YehrqWg8_FBgFNlbEzt|CZGv|}N+t7?l?BWssnY@Ilz#M9#O=sv!n zbnds3yUYAA;blNi?jS@70vvkN4q*bY#o)q8`b>lZiHPVSE2u&s+*AeP18uGd&#VxOu+pZ5wlPa_7jGZK3&Yz!JYF}@jv8L| z---2CS<->uBYUg_d}bS(8HUU2OHo!Nlwab!6x~O#{N5gfPHgn=@K}?XH=4-tnMAC? zd)ee=`^nFlAl-=HLH-1j$b&^OX4VHm@Cfe-Ji)y9LWoe-5io>RSO=?rbcO+;wq4}< zbVA}m2T+bcLo&gG;+D!mqf-$P`i0nr$WiJKsu(O#Sg2AqW=V6qG~9669~6v17|3v8 z3GI*YOI_rI^8g2Iaq_FG8XKxV4{Zc?al{oifu=xaLT@H}L{(OWp}kd>UKWq5c^&@K zYl}Q8FR2V_XSiI2qQ*K3%pK?NjoV4^YgSKgFj=yEBuX#i&XEo{CxA%JxBAo4JfMdY zTeP|?S0(2xNc*6A)*a9W%4V=#VlNbCnR;a10e08b-)_@;dC5YQf-WB%J%escftdY0ULrKl@1-E<4AS0t0Gd zC%7wcX)<$2m{G%(4vfeg1PVcFNMyG3AP5);kBK?AO5fLsF-rR!%abAg#-osMO}LK& zZv4OqdB%}L*b;{p2-|Y4*ZpMmHPz%MVj;9|t_o{tKE75c{OH>6LR}wE2#H2wY(pt= zC;*<&h}UbDx{L@)tP@ByPr*tUgCO`7<7pBz@0lEqb@SR`_+Df9(NaR(16Yitn95od zA%}HGm^?H4!*!g4QmzRZvDSl0nP8OMzB<#2iJMu!~^!E8f}>(Zp>L}fG4X=J~{1Cyp= z3LsbuL_=0I3=D06m}Rw*&!R;z!qO+k%#vMi@l?gx%vrb0org%A@MZWo|i zF7Du*6ikz5!OmDc0=Olw5P#0j!#mF5Jof@hEE_~SrqFp&Whm3`SyUC0{?IOiZ_U(; zM|b;qkqscyeqVS`fu5SV)5~nHYJ6{hT7uLKAGs(DAU23bBqpeKE#pkjDg>Yx0 z8`PaUtdiWsg3%s&y2!T>RC^q@AO9WjV?|K~^bJMbC=rjHg<=Q<$f2d<)R4*|PYDBY zP>n4!s*BiGEUep75~Z+$9|HT`m&Pj=ZUAY!Ei|2R*U74Xm4hUJC43LSrGeL&wO*v~ zv*hMj$8-0j0icUW8w3p2VzDw;&ni%jHK;n(SX=n2 zxz=6xSr(}1YOC5|XLcBF^-+~2=`B#;KkJFoHBG!kq0A8un7Rkas5N&@7p`@RzEfRW zL6FugENX1k$nwiKZEWY@iz-GVv2pkr#_bq{Fnwo>Ha;=Du#$!`^|8~DQ`vUg7BXVp zykQC+S;$<`t?R=p1%V;r!j-&MjAP`fy}ZxdVAb}ek&g}P5?yL(6u1+OXizAR<`;na z_&Y-Q(KEQGGdrYvqk6H{=GCn)-*_@dcU-!tI1zjQZ0xVsLTJx+e!T)>IWA-K<`@4S zjhOA69UBRjjQKdarf2S)otj^8mG*aZuh#I;KOkSJ$d>EyT03VK{oQ>5k1nvfd;gbp z|78@Se68o#v8qSE`mQ&>`1d@(r^_yoC=Uwr2wo-?9(82EE-6XrORp$uiZ$H$u^LV+irFV*x>-V3E>7E3IBRr{Bbm|15Vw=}gFon#* z&zax@1i_=bJ2xFXN4@oMM%D+XxLd}*-TG&|(zOGH(!#2T>#76-BOZVg#u9e?U=*mE z`!m5OSZN|^eF*5sj5`R!EcCzB%i}is?bbP2?B(ln?*gL-Cy@f7tBwh4brBVuiPeAx zi;P!u6C}ZPl7n3`C z(S}V)u$9;MU#fST#5S8aQIIkbRF#<`N}je*lXuYAK_X{b-e<}^J%gxe-gTH*N*zvV zFqg#8bi#Gg=qFGEbSD#4a-Xe&#hbvs=#``eDY>SG8&lHfX;EU4TAAw`6~8zg-{xk>%VuukRKTO?`s~o8GGPd9bKX~Aq@SS0C zK#(<^13~bLEUJ_R!T|A|m3zjky|e+AnZK?a+0u3JPudSKcNF#!azd5)#BUG0+QfXl$uOW z$d!O?3{j>1^h&~r!MYQHssNgU$Q~?C^T2k|m5%E;+)#{&$+}2qT^N{R*_g@&6G#-4 zH8t8sm~VQuF8jLOR_^t=4*sbci29uf?5yNgXeSGl{jPDtQ%6U9Wz`HAs1>a41gr2Q zS*h`9vezanHLz_M!vHHdjpk_&9%=L(^Zx7pud1@Ss3-tIKo~SR&AEu!3TC)1i@vSX z+JpU$v1r^;7W2aUWjp*e!u)ST?i0U1;w(4$dkXvqxQ4lZWGLE@23A%N-lGxExo)@q zUn*4zrHWcIv(p&M1&0ao*t7gGENx3HRqB^C*em8BE5N}BTQ#g?e{Kp9X1s;MMJg+; z2Ock!Sjmj+R-q&?i=p@rRvO1Wrik}W#t?w!xKoVm>&$lH>M-1j?iTKb`!k?sLhLPb zqix|j9AT5fI*n{arhIot1;_2YD6bg)YUH&OUp-OzrrDBk@32%3-byR&iNq0ku#P6I zIWR84I*)55^OBo5HSQ3C#%C@B%*%5WS>3Y6hr0;Q6ttu|b-;PXD%*K@eG-QuCkQ1q zuSnvISp7;rIWN%x7DL!b;M-+kCa@obrVcSzf*AmFY|tD_!AbOj@=$doLL9QZ1?vgn zY|yqQVy}Hq!)~-NbPxxZvylhH>FJ+GyKT?w^EP1>1E>zuUX#4hS>Z&3 zHqB0SU6K#NhhPT7HM%Ptxytv5TQgTI0RV^-1TB|IX z8YnTTPJzGU-jWpQOBq%CRx~6;boZ|?P|`e{b5T;xTaTs5qDoeSZ;fwzw8x57LN(Nk~7?B5+piS8I?7>HM zQgEWpApY8f=A1vg4o#I4oUn(yI8Jwp`^So!jMzPUeyKcaY5wVT^OQdaN= z!V$SVg)wDb(Q#?@fIk#xTTB(JorEs3`*v{&5@rcI)5amd*~8`@qAR<-g_C zW-{2ORW~rPXaiAjWssUees4TpRb>uvrlXS|jDI*4)eYq51h!lMe!k8QM9+-w0h1_V zHn5ZSrnu)SOnaEonEOx}dCc*2G108yG(FC8S!`#2eII_@Zk=;9<75B&cpirbou}R0 zKZJ`fYA709^{kmDmJJXx*Pg2G&7HbjOFHXK(Rmzv^})w&?VY2!d|qcG3p1Q@i81D4 z>Vm#U41hJ^Tis)%D>+?l47n%bAdJG1oUc)rf?;zijpsW0ZS9?-Nm_b@2K&+7WlB+Z z*jeJ7-@Eseuk&^HP~d%3`eB-6lOoJ=d__4(5Id}c$kom202dn13p(HT0b+Mpo+&9$ z2b&EghiQ{VyG<6=m30BTccyl<-QMT5J*YSXrRJ0FXBb&rsN!Z8;wf{RauFzzH~FgL zF0Y^Z*hQYB?LwCF9_`w8sl44f=V(|L(&eU`5l*oRGXMeRUFE?DVV8mHjJO_G6hF4^!wUbI}W?j7uMy(ua5 z5c})+w_E=-|6V(IMuqU4k`-<2-Y$8YV2BUdh5^)zWNmVk9+G|kosz#jZWGvU{c}Lq z4iwl(KZ*-iya3_qvKMZ{I(Nye4MSlFNp6h?u7q8(^C~}1$-j<&yLC?jQrxSA=aY3w zTRCJaOf6}gq8IHtPT|(_QOS#fWICBrli`h`px?sZ{ zYxYyHg8autvNND7osxeY|90!%ckApx+Yd!`m#jFyW1f%WV}1#^uk&dQ*b;A@!HRZ)@Kg z%Puu>8Pt7am#VNha^qa;GJH9mat#}ag>$V>QiYT}J8stK{?dOm8 zvtu~2d+fKJT!ZU&e89+$?V7f@+s+?v$M5eTiDD_Z=5($%6d7^95Hug8-Qqf2#tw`5 z5$Z4RxPWN`O0pc3!I&2CMH_%TsIoPcZ&U2BsPZf5dEH=MyZ#mu0t(tx46I2)jXq$r zNI6J!I26LsNlZ!pTtdG#HWd>hNdNG8cx>qBZ$cR=h zyptn!iv%4#UchyeJIWWXP}1#Y^dGRK2cKOfdS*((Vg$S#%Q-mL z^vZ=IVo+|@#`LpcsUPN`TBpEcw0K+q#i zlZe>JKVCGe#SpI7iM!1iO@?QPgtISa92LuPF-b*Xj+apU3N>UZSB&~@l^DuG(RJqr zWhWTq6$HJv&wKmzQ-#ieA2*N9NivruL-m4UQ6(HE%H);@RXKk~Oc0OS44qN<$}t|$ z;&N10v%TMc?d9p^z#*+tC5R1z3krW&!z~TSFq^YKI_mP&a70=fJr{74qX@G% z3z$y=a~)+Xc9JAZIa5Z5TICui0rE;c!qY+yrTe#LHDQ%OrU{-p;@%b@piob-Kd%r2 z-A7a!2bL@%5?-3ky@+d`LnHx>1ZNd;h$xsTif!;#^(M9$`$bJy(a~nKq#g@#V=!2x zsNA*CS8kzTvb@&7Yk#2EtageBz<|3eYy=#T3Ls-c7)K}|eJB6fBBGr%R0<_>dM748 zc4}B3whx*O*8y$QGAu$6OG8~9T-VR;x1Od*WD> zkrLf}Ce=pU{Rx=);x_ZnoiWrar+VjaYe9pItaxiJ-hROQz;AgJ-;5l1B0jC0qI`0@ z$Y{WcIq#aSnl=6YF=zI3j>5-VL<0~g0miRg2jm@QkD}(TN7`InpWLbDIAlXrAOJ); zs^K;!Oo`}mqfFR*dYouqc~qT`!G$fGjT9iuP0scesPxzeAZfSans9r4h3!__tv%v< zb2M8$U{d?4VBAO!`IYb|B(z}Sz+Dkki)39IDY00Wz#-PyR&_iTGH}Gb%+sVaqqBuK z+@R$3=61;Al6u~S1a2<>`qNOcHc*x2%M(P`@$AG zUV@gM6A9a`=p&u#DVT?T*3+R7Rljcbcj**BYK6HO2A&5E`eoeWl>*(hQA)Wf&>eOZ z5)h5Fhqk;tecaoxAFE@P!|EM&8v*ulaUkuk5gx}$nmRj@P%JORWU7&f>dg0J++Cgq zCHd*bJ2HmyG8|Lh;Cgy$mdj%`ImQ|$t6%|&3?{l49Bi{lo&EYLxXblWJPkU7&x1PjDd1?cKGA{Z%rX=i@3qSyFjQYaRQCw7^BLYLC==- zYh|I#pbx&@8?d8>7i)P}+?(``92#Ct_3NAXHIDcxz}Csi&n}DI2V|b}brs6Mg+Gn! zl*$a{hx?fkfkGAvt$NHVdOqhG zM`nN?Wru{yP*TPyzTJO}(h?`#X*gbSD)_RK!E3d~ z8t$C%?~}2-E>HKf+1lx$40igic!iMXlkN$HVXdOpwlRoTz|0(SX}9~mdt*B*Ymoy+ zaX<=A_wN1_dP#mI{CDP!1pRN7*!%l~y(7ENYhyHfFR83EoMYG>W>UE}4{c?H*2~k) zaTrTJT}|ZPa=3IAg3q^29+z=c2gPQAf5zqMexPpCsT#6}A>$#}N)EGSV^XAxV+%#3 zYAG~8+PEeXT<9InlJJX6iW}5GGn=L(1tC?pu(!-&^33jE9w(&Rp?dKPw(N?>fZGd<*?(Dh1?`85bI!$)!=rw9#pYpk}T_(qLnrm*R>gmhdcIJ3dg6D;U*L^;Wz z>z)Dfhp=g7pT>ed;@T`xcoS8}qem_sq}#G#4K&m5B#UXCV5mg0nAE}G43YrSu!oLu zp7~Uf6HT{UF=mlNmsUmF`ptHgc2phdAKvZ_?(Xrn5|t<@_Ix}93jtt$AE8c?Otw_l z;h*b9^Pw9*2|H?}Hm2cBCSTfDJCr8I^6z5m0EMlP3IiXt5sRK{Vr*6EvD4{gn>^do zufzH>V>)klu{X-Y4!jze@9Aw$k(m{>AKvesPJAqZf;n*@a6T9v+3YZ!o*01l9~%Gi z)OZ@SmcwG5Ky0G>0EAd3_Di?%sm(rH%LT#`dFWumy1$Vz7}#e58ET z4y535dw_>h$Up*@X(6qt5f=G)TIt0npFn0=H&ra^o5VHO>kS7fYzeW1E5~!>NZsz|fgubeM{NL#TF`Qj z!1tseb-XH-gn}1gpojY-hj;S>m8_RCRwg|c(MeVsB*a=Lvz6e_pIdAuF?OS11IYOm`{x_z8(&}MdgyaMex z-5Tfd{s2IMRg4c1z=VKsd|&Ew7NL;dw#-lDc09Yl{TNd5XIetrAu z^!pFrefQ<7fB*Kw$M>&Je|q=hAHRI{Z$EtZtAG0b-N$dgNZS{G`L~Zhe)!${FVerZ zy8Y|g#;;%f=D+@@|DvByzx(pl*CcT@36h#oy=x!}hfje-DJdj0iFb0LQWgaJAYfo# z8Esc&_6pP>u92m3Iv)C!-*K(%Kjq)*zo&ZqqmTdOs=xioyOb4>f`f+tty{a57s%*1 zC9~+gI{o_{+NhwyjuTKyKI; z$SG+j4HP}stz*7YuH)IdDf@Mfm5S~C1k(`k_1oKip{dOWh0+$IT?I=*$&Gl>D6?zN z?F4}Csuv|RA9z_A0lB33Wq)-hXI7~M&~IH|@e7ryiW%fqZtu&Z{7hxO{z>H?YX0y| zP4VEPK6R@Ag>Xr*CmLlJTeh8X!Xq6LLInK05rxnshL0T+*;{ra#92-lin4}ss z8~{rW5Hjr=@uekV7t;AV+||;@UZnGj%aZI)n_KTHSdP4#F73#n`HYn~2w z+1@qzbq|?8ZkLm}`*N+Fn`kWjv%Jb%Hfn;W>GGoNO<#_hRWZx9$_UaF)0o#o-3pAU zseqB`3gUeEV5e2P9N@C5;3k$LJ5o>r8rFw?oIrOA$G*bn`MI-kQ!l0?u2;~pEEA@;VOIvLq5us`6SQ@yMGT|4}<{`=frDB?hF2N9Cv>S;dyla|qsD!@X0GFRK- zj45yy9;k~+lHZj{q91X68(pS}!0|fyUzvpp445Wwq#PlaJ1_#Q(jp?DNfScV}RxX~AS#5W} z4rj5*SIpf5Q_V?qpF2Epg6dX^f{aV@8i&)Xu2lLC8&_vW>!>e^ND>QizEQ4nk5{LI0uCYlz8|o? zfn%uRZSD$YsGH)ilm*FC5E>f~@nH>z%0QwI=uVd^*=Wevwf3v*1I# z1mF71(Jhq}%-Pa0o8i!#^H_+yzRXx(_7lUUOSu#y{&nD)htqZ$6&> zD%`o{_yR`FJHCo)#(S_uwI=${_yV4KmPtN zKm6&-S3msakfyi+{u*MHCAuXEt(!`@o@$9A0jbnRcid+-1I#mB#X z|NcL}`|kU1-}&75FMs~<@yGq}_~ZK@{>S(4zIp%O{`@aL?vM8uj`+NE_i63!)B3Cb z$6Mq#`o#V3AMVe{53Td-SC8|iqqwJi%44_VMVN#)7+P>>OzGEnIAg5OaqJvU5}Ts% zXa~ne$Lx%)qxg5Wx6hr_6K0B;kC(~EtjZp93o_2Va>3A{y@bm3S zTh+g}zoT-3KeSuJH8Liy?bi0S_u6P}-%PJ9*08dpxf&<*Yil*Ep}(i88oJZB+5m^T z)kbF8wKiJguC)>6*0na`DY&am{=AO+%^#k2{{6(6h=N$>9SJYl&5uNge z_9vr|k@FFsVmHzTg{wgdg=G?S#8g+G4J|=3*mChL&UL9lJ?gu;${e75*=;ub(xZdh!Mm%w@vm zF1h@1DI5ocLWYCU0~E}~Cw`pmASt`O{O>v( z9c}uBI4$=>$fQ*vI4$|ws=$fstzngC*t;9IKD6zh-hKSx!+-or_@ez_)lNF;?)&=b z3#EGIytjpjcXmUkI{;!WHetE`@og>rQgo4T{}ccQ5$q*jr$u8DM9b?YBd6m1QwC3BmL@gSMzQu zVl7$Fx;S(|*-06W6&)|rl7^a@fQr;D?(aw@H~U(ce0<6l;%b_VpI^6X`A3=gP61#A z9oF*&bi=b-R4t?iwc`+w1p99F_7e#ktQa#nYice0HY(Rob3{LHJJ~YP=?DO^YS-7@ zEUkp#n#qPsEcPW-V3$P>l}MyWbPrL#VFfmsI)~OfRXrp^_4^4wc8MbBqc+?yhy!~O zCH!U;`_@AuG2@vewi$|tMvJA;S3D_SOHWJE@h>LT>iEIV47y zbA_KUM_AO3xX`9lKdtlnD4;VpaEHUcy%+mY<@SELL!kWz(|gX21&dGc183x}`@&Q5uCF3{$o zrz$rNE|(Zf0&8ZERJw3jH@5bWBNjhYcU*SFa~7)xjsD-jy3qYm0w$|xpL=iab%+HI|GxUMzQpy_!KZc*lOx@lgUPm_JDRg~ zIdk@>X!<9kKp5^3)6dD6h%8>{%Qc{+)oV*0kl{*4X*hybdip`>(rhdD;JPXvA+I50 z>gC#vTrS5|#^YlbL7}aGreq$b5rXN}oaQ}{Ci#%drS{%MQJ`+#1jziV#hX}xBj!3^*t~-zj1^Ic zl@*+4*<}My>a{gJzkE_cfm#!!hMv1AQf`XZf|5d;lYMausaOn)SYPz5IRd1B5}Wx; z5-fu!%UvHsHW)S|`Wku*m?cVwfOROeu2Zp+aL=(MZmzn_mg$!u0uDR zJCmKpT)RcY2F-EP==(>(&8VJv*orG3@K}Yttvaf5Cuw2Dk@fR%OrRnQfOtu$pGbS< zh)O9(0qK~{zC_|9g8cyw;k5_;R}w6}9*(FI_hrY~I(jsAZVO?3YAr}}pidqM9QoGO zU>kPuZX+9|&4_b#a(od(a%3~zT{{E?fXl?c$*a@NUdNRR2~q@?%> zy@=+~)(Z07|5~c~wlx(<#csD2Y}x9?{zWXm7OxBc@9m)y3Yzd9*!QbwcJN@&ak%NC zC(O=a+2rnUt!KF|)AJQioweP?C?!)&#zCV2r_x6apT!WK&kbHzWjX_co`O zCJtSZjoL`fFpHxiTsragI4Z;0gR+Qstb{=6W-)drFCj=ue9=kG5~_lqo?$;$1hT(Tb1wk208X3W-4VYmf zec?gZtq>R?k#z$HD6Ze@5y-dRkQ6q&u7bZ%#MZ0wXhEDBS8qWP;9r#%VDcL;>Emv5 zXsi<>UJB(%GA%K@=%QFoN6-U)^#i-m@KK0i7y5}?bKRZHHvRXxC$oxOrwq)@KHNel zbiS@8Cq$Tz*m<{o7bVVF!H$dP1@jIOD$3h5$!m+mT66D~BRLM0J>Hfr>S~i|nG8$l zo*+P1q*{<@#&-=aG3DzOvu-M{1H!><`)ioTf&_Jb9}&q9l1?Y6_c)D};2f}Z=tM7N ziE~QT+f50xdUbgiSZiqw17npjG(y@axP8#*D{ukux{h*G&7Pdoij*q%d8BXq`XCDP z<@I1JSu?(+nbn}zW3rkTu$y7kLP*+dQz%1`mD9eWYE{)@}N9pR%sgN9CDs(?{hxuhXYnSm8QnOd7D2y zv{jDzqw=iR`GcNYzs(=5#Xa5TkIdeZZ}X=+@!>judN$4BF@JRbY_|!d=j(OH1XA_4 zbell%q>bAI>Q=bBP9R9)?j{h#ndLTttOs(PKRtPKJm!!3cI4aqIe1KC{yeRX2Du;n9THu{ij6HB0NaT3kbqp{ z?$>FYRu99WPNS9{;@*5z$;>j>eMigqQLMs&+YuF?Su9+xc3ffF_zF0C_7)VUHMa?+Trx_$d z?4kuZhv%)karNUj^`U9N1CV91l@f-SeE!`OYAFaJj=KIsA05;*Gu`rGIV>Gmn1ahi zps~Q0S;6eUmzn?Z_%&)Zuf=tH_Wz+_nI9>u@?oCNgX*by6})4_Ib0i6auC7>VQwui z{sni{y5l{fP@Hd~NDqu2j~qK!$Q{o_0LF{WmZWkI4^5>G;^pW z?0hlDg*6SIMd3j^;b7BaonQRC;O|H&4oef4LEqviH4hHa8=c4HXgp^*UmhRvJm6LM;xFI7 z`{u*P{TQla>ND&qo7B5R0_)=0Jq~YeyDvD!>srjlk4h#)qH&Lp`rL{D<4nzuCY#~- z?#nR|y@p>7awwmWF86o-(o27`tmS2HnC*4imgz;p(1L?ij1kM0R%ocyr004gQg4!2Z4+2?WtxaG<~0t z4K+MW(=?ddYDQ3G%R-UWF51f0!rcln<791CG`kjO#c%!+%V5h9JKct5IE%d+h~A*t znZZ|pK&(xS;;(JSwP)v9+wuSSIiJ}WMad^}a_-jW_1|L2+^y3h`%DV)djH;WC2hyQ z&qYK?5>UVX*7$q9_bBVR*MB#jcfA+E!{O)p-{7IpdY{+I0A0wwQ6V17(>$OaJ> zj`*q062s`=_qEhPqOEUqW@%@I>63J~hb-+z-)_?N9vt1&on;KGlBaxD#YV}9hU-{S zWcC;Tt~8AzM{99dptrPNFP}x`!}4nUzA=kKOGRbV%q;p;c@G0+L^Lw}>cwf}mPHfk7T#CQcBBFd!$5He z1atf4>Gl^-IayF8Pt~SycW$VVtGAnigkn4^q$5rhHo3J5Dr4CfZ;Q@ZT8^{jRx}@# zus}L$9{es%+}ucCFEDWGa(dE%*=)3|#!W79t@?>!l_RrNqfm$3c6zEeY9j#6<-e)u z&JP@hq|A>{7@zxxDe8uj@_@*l97=p}!!MM1ibva0ZcqZ?R%(1IZpa>SMP0uCL6N&} zeta`=V6pNWvD2K-heoL`TgXUv;A=d_GK2Tkf2)om#H+Ti$gOmsB!u)yqak?{!5XE% zXY25&Ionv5r`ul+7*99 zje8SlDqGPJ(L4ZqDfxIRLwOupyV|5wp0CY`DM?O7O zUkoRWtu%`W5Q^naP)+4dMws}z_61(E5QG`hrYB`JCo)qz9L|}nW8h23&1PZ1$uw>7 zg5)e8Z+EiHzLcq)6x6R;a|ZW!+QUQ}dVZt58t4_hpIK6^h@|>WGG!m?4@sV5+k!BP z$%Dw#ULl>ep@f0-IKwMn%y!=0KiTZ(_qV?|6u^;ZX5o~*CBWET71kH<4Nm&i^4o+L zN~;_TKoPa7z*$LUEqFk)iDj29`-CdcdW#KQt}TtJy(!rZ0PIZBFENT2pnzGu3W%37 zpF#6a7N-ih1O;8n19Znj^_fJBje?TPUcU@jmJ6`5RMxE29z9sFrd)NZ&s5s3R+$wG z8VjK1xKz%aRVisI==vnxLak!kWP#i?6taAR)3Z>i^o|i~YlR3tH}XZah`}(XNxTY+ zT+ZqARQ>&Xk~Lr1O+D)?^~X#|QTFdyfS)v%+jE%o|MC8phC&w3COKJL=0S$qzwKoQ z-evMA=u0yBk_n{QG52yqz&fKm+4pkBKFEnCI;{!_He+3oy)E-V90RlOSL@iDWEA0D zB)NO**hu@_-XA8jXE&)D{HROY%icZuS&rXj;lZb>?Fm)6zmN>{XELb zx)tzGAt+xD5Bz3ccs(!5uw3bV4VpyznW)Wvn&f)t-&bDbD~8E$>h*Hb>=N{uu3nDLSNL1C#;7MFGhv1hDp8y&1llVRa&< z_GpZ1070vOpaRc__kHu^(SShcRs(85`~o0glUqQM9|aGlzXUCxVcp!VB5n6neH{*! z$5lKz)#&m^$K2GilS~1V3dWw=)Y}+}G8_?WI*@UN-wW7L6Yge$YSSRdym)#tJQK`l zR_p_uDrnBVtms>SBzxVj&&*6U~5HBj*EsMT5Ji*<%`aq z*=W-R0~X3a&D|l2r^owW+z-SvHb=mv-O z#m+f$ByMPPlOKKy@a9_Vg&7R6#(ZX-S>90Kt$(Wh{yB<1IFm@J2p9Ih7)7fy2oj@8 zzC-N~yNw1UQm4ptdAj`K55V^+0UWBQKG!DS8LZ-u^rQhY^61>~Q z@jed$c>$UGVSjn}_mXbX%^F3nPkX9nn?A8!AJF@OfSP9I1Cs2_@tQws*nHhdh>aV9wm zwYi*OvhC3NswXN=7b6nJduNnvGlE*vr?Iq_U$+Kj6naP~pA3^y zs>ea*aS1Z0huY&eut!NKlr0YGa!3i}48xPE*Ey)?(d`%5_Xy7STlfunr3?uzV6(!( zzu-6+9!DCzb%kGI;W%hUQv+2h91U7H2JkcF8r7NMme>N`A{P>(m-+NmeFg&b!|K_( zO#@bz9R(BUcpt8x^6F=d1RqYJ`F^N92Y>FSJh zhN4#hYCx60IfasfPEv|ykwy4Wcf{~KKSeG(Ean=&R~XR})WdpRGB6bol4>&n&}{Gn ztF~Q(UMb8``?8@~n2y?KjWTKRX_R3=E4&b^kF=-I1>CSbi}aKbm)&4#g%W$@&_LYl zGqozU(_{5vRn2bu{@N&u>gvnI(xcq@nKEIfOjkLOc6ay7IHL-(NBlku?1^-9=1ECy zmO#ap=JyG9rE;QG23ZoPs=$w3g3jo-RD_^9atfZ{LEnaH2lu56rdJpa zNAu-!;K&>mAx}SPux(lk`2D1@xVCQKc0Dx+`h{}p(90vqrTx5v*x`3PI_>rz{^7Ub(z-(W;vp6-5m z6bw9mNV#n^8~Z*ISIm|{FikbB$Xq%pAGifdyo1>TM?;Qwo^Cjpc2&`RRGE)ov!PG? z-6ZQww;a#kXE*GPf=2nvs#_WjJS{+oRCT9VAOV7c=tKRntBI~P)myC33hk10AdHlb zIbLlDcF2GSYvbrfS69LKugn7{K#J|SCh`=plZKUj8$RHv%i;S|xpMvH$EzneR*QpA zj~6scr?9Y<+aSpB!|pyrSiR!r1z<&x`c9$1HZ zY}SIh**eq$%L*2>Us_;?S2S6NtN2TYl)SlqUBuK-OnsUtFo{`Y0*vDj^}!Vja5+# z7PhP?P4{_KkDn{VkN1;@7PgHE@lgGcv2EU)F%R{^l6b&Ucv6RU9QZ>^ZbTF*p|Xo8iR|)qiV1%CzZS+Op-} zF{~FFO&i|+Vp+>W@JWXKB7JEw#Fab>soEl=TIB(e2-$PuZWwn z?``)ZiY~jq5qnT_+dvws)|MwPUd9=|EDGoak z$C8IFU!LxNF~AHjK_d#9c1xbJbO>Yu$QIMtUolnntU|&FdQX?LLb3_jGs-#(S=5T# zyGul5C6!#yl)E_=vpN72mNKgLnV^M0A=G{IqpbL_JT%os+0P*_%IykSK2}~nWCf6$ z0U-F0Gmu6EGj!;eL!?+OL?<>mKo)?JVR(TE;j#f8%Ak=8gv;d{=q`#WP`Uu}XvoU7 zK88Hq+^rlDSZyXAjxCwWe&6iuj*-ZM$~xw%b|C|xu=!K%6)zuT+OQ7own0V}VHuwy zPm=hd>j(jlOayun;+A8#U!LxN(Q}l|&?VD*-%B&t?X{N`&nq14MiC!R!;7MmM-he9 z)VZ&oIT(rvcFH-{a3*Lfz%VrzCpj4b6PcgAp~3g<&zEUVSWd^0yq7aXv>Y6Z__8Xx z$yw%=h-(#|?D9Wo4^Oa;Zb|-z`|2BCBCoOn9s2@D`Ab|de*gPqh{Kw5gnE3LS< zswW$3foZLFUN!rL^)-*R-#-W2)y=tYeMAR3p%$8*=t0lEfA5xy+%5Ycp?UV-E>HKr zxFE=S-X}OTmu;W2+MD;q5LUI6yt(X~<$ZZ+Q}y+iGL7Z%n%2%L?*l@fmwlX{#80es z#R3+CvOYD+UsX^F?Of6G$=B=9)y%q2hys;|78p@j?{B#%Uv-7;S<)E=7bTKvMc)@% zY1Yk->8VTzewO8@(`+9Xv5iQ_S8%X7*IBVxEfWGB%WnjWvW$8WD0JN~SK0nN?Z

    D>BDJI`J| z>#xLcuGc~Mf9rOcFv2N$R9v1$*~`(5raa{&zq_JU!sIHbyOAN3#Jf80i$es_zIZp8 zJ6TqV^+h+!nD3@M2F=hBe@*s0scilxm%mCwf3J=`OYLU}jHh}HdF&OTNv`KW+$$;PQfJpZj^~*N zN5AX!&4dYA_ET1ynIb0lsIJ^^<-Tmn8DFmm1cs&`CwT(Wt!{72XsO?7Q;>X!+Uj<8 z|M;3SWnojUUt7#oaBYn;;&=W3iw|=BXw9<^KI^Wv)6uKZ8!7HTdQBX&ifdUL`gUD4 zDCOGw_2|{%Ub`P@FOSJ9hslK2Nl;jFTpf&{#^x1Sue*<4n@mIzyn5)J+!9)i=Tk ztti957fcw>SwY#5Rw2_HsvYN&k##SJOYUa^k?z9NCzbYg=3*9|XSB?PFV zBQl|Gh)m7Iqa&K2EaMa^E*DbuttcRH-8oYC$(-gyXZHOo6^CHDw;r7S%5>3* za+xtiWit5IbiQM;R)Q?Un*4jG-|vUrOC!{ZPl`)r!T8Rs%Q|T(h$jTE;#)eBU(0(< z<&pRGmj*q>05P&p^Rv7@8cqs$w_*QQm0c(e`HItM3gqGPS4a(~{kCRe|Lb+Y86vu* zJqfXM!VLRcF2Zx~#z9tZ>^mVUQ;Gv<-paM21C*i^q}uM4AVF+5pOi1O@1)A75I#M3 z0@i0#sT7j6OHZ;6dYK5Wvi&3q2B5&PpRy47+IPl`Uuu85!t)BZbjuiPi|qVAN<9iZ|8Gb-h51s&KNu<*anHp^!;@D-x(W!bDrh z{!%2(O?9buzC}Zx<%1Bc?`UWF2WPqU7hLZ1TK-D8QF8TG_Pg676-@SG81>4hVsIN!Oz)ey#z2& znbH>leir)gS^#yjlv$e{LR0`$iga4p@HD7w&L?qGa5BpdhT{j$AfM4UhDhn8gBm_n z%^SsAtRW5;ec8=-0wVAOZa^G_@R=@Zh)6sS0?h`8O4g!Bl9LwkdeH#w__sg+o;Bng z?+~1Szh4F>4k{C%2`|?w@eqY4FWNo_;%SQV>2PSEGwg+}6a2M~He?$*o8j;j@4h_R zY0<9iGc9%;QIuL3MHaYxt)75 zo6-JMnIg5A3rSu(Oo<$K@83Q*qXgui7KPoIAs?y}axw0W49H>I5NXYDwaV&!9Ci6QK>SKLIy-Ap5FM@0?WBZWxmyZ;&VAk1Q7{`4yp8%M{+^YaT8-r0+o__-Y9Q~n z=_%si%OGL*@%1MDo~!v{0KiT?T)Y@&)Kf`^+)R0{@+SVCE0R5O$%?9Le;L7=VQj{3 z`YBmYC?_~+w*Dsmo~vQCC#7e!se`{PvPpV|VioEQWxNz}?(&=XdlueZTa(Eg_xCA- zbJ=OTcg0B~Ea^B5<7j&mf6vHSDC(M#(7;z9ghYWhYkwZXlNC5{rcwBNmJeYCYFK{I zC5e&_=yy}dL+GgFtc>02dlP@paxDmVFe|@sA`x z(72wJ`8dH0>*%7^ydNKL{O1#f)V?N2P_tJxyv-k(Xw*bshRL>f_ue4tFr~L3#?mk9 zclD1J?R~90YcL5~tn%Is$UG}r)|{wB%DJLrLRi#%QL4VARvY{byZHm>-tgPy|Itw} zyLQU?7c(v{on}zA?$2^CG#m|#QMrb-rwE*ijP$18^>q~GN7N1`k9x(;Js}&LORw+v zTC`;)jaDI&(urYAl2*55!uC8@A{p5^POH&sw1`3+6y^cmlRo*SY zo@QPJ)Y5R-?3SmT-2^t})7Za#yIr63t<11)hBk$xsY+ z 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

    !gCaB|`XZ8D_sfBUmRfCr0A~v60vAx!!iS z@~kHb>kN;&k}&`coF$=v0r;-ayct`XM)@hr!yC0K51z*<7MNiXo+>FNPSTvN%xj77 z;!I^oIVG#quk;pw>QYaNSmf%>CoX4|t2W$svvL8YkwEGBYDjX=BXU@pA6c#>z?&T)<39E2m)D{tknj z6R5b5Z<7iL&e=F4(FP{;U}ljG(k!0yykG8QjFz?Imv>d+GH#KURu<3VWjUp-<%$nG zhCyiSr2nRH3URHkEPW^twAIBAht#Nyzr&jJ3hENq`-ztj;jPRUsi}WjudkLik$cdi zYkyJtJ+g&KHDC(KB6VNjBvN_O6>{J@Ptnv+b~{_9TG}-#3cZdcT{!#pb74 zB5h_%^7gFc8-MoBgzS-zMOpF~bqzB4YAg^;O$5AhnMTOvr1>kowM11?#jE7PHufaA z#BH{;C%l_5lW9dJB^2p*&ikCd*ubRiyf=4$P>$4aEUBC3sa_Ow>FL3rP2hu^~razM?H=mn=E&xAves) z+=JRZ5qr{PYv;rQub&?7aUdm20PfdOnSzwKG3YHCIdU}^ZWsB{)%0Xjc+B=CbT?Ou zcFHcazs~zu51AZ;`O#Rf`#l-tZ+{;gNycc5%>>lr2nYj6)@?G(FDqbl2SZe~vbo)x z3P0pwMnLpTHh!5xuNYD(@3>7yh_A`p=au>z|Aqk;BOcyO`v?)ljSiH4w5{+?&Smf= zh6?2UT?j{|Qe7{IyPJAUCRO6}je9W63!TX_4>XTkWIz{jXd@Z{8(+r%LG&;+FH^`( zSt&LH6d9loS}}HUn7BN=@)0XzWGUEtaWpXAXE$eH%!!4B2U_Q`2;D*QxE32&In>z~ zRk1<-h^R|8R01iZ_byheZ|apfGGwh78n3tj!dg*-AmfEmlHE2t z7I zFQ60(wd;_nD~@XmkWLaHzyN2W%}>u*)85n=QJ7 zlhb;#1{ZZFo{zUebYOVKeptebc>;#e1_n?GOd=^4M1+gw~3h{9{h^M6>}hP z8Kt)tSDol;pgk7ddYtHL81^Fn=%fAQpQG9yB`QKk|A02Asb#g#e}tfCC0--bUZgOhqyH-gN?r(5MZObVPt zbPof?84;Y+O@IwCW78R11YrX3Ux^*U%m>dS@=#xHX=l+`qZ_7n(PjXZd8^uCm9*Z| zTbv5Q@<9L2l}L-JA4j#)swz5TRUU*lgQ zB8%MdX2;;g4Zp@!0Db0Bw#F`6;#hozi{b^WBQuN&`9$rhHZer=Nme#SYL&b_lNd5* z42yS5jgKy)<2FkT53=0C_%@z;M+TmfkHC^3;GZUc>`57?nM18Bt#^A{Nu^>cjjDR9 z>YLYt&N0d$H#FDFyfDgl(6KsuwXsjqK1*L?3j{3_Z^6$G(}GleWTmf`cZnGnYW=jm zQ1}#H8BKp>6cWsc|+xlW>i=G@fe+T(^UdYZ1cpO)%t=&K_T?6K^RDKSDr zK13dVbLnH^69sGa2M$|KQ{8AQkoXn67FCn zHQ8JHuR2)OdQVTX` z7a-ryd%}r}GNEch`}2M?{I~1ihs703AYd72PoQ))c$p9%xoeNC{T2mac}KjT3}#%( z?yfo45*W|h$u}Z%y_#)b0C5v=HE9R8G|ZKq^m(PeTvP0lPztiFz&J=rqJ8w_etM!g z(H#0_?Zdeuu6GMNv{?Kg;1;65W@9SCy~La>C5iMIV z{aAUu*QBLl_w|?o$x21`0U0q1)RVnHJ1$(NzYMp-xZh!x=ZuByBBR%1$gQeQ^mx5j z?8bB1zJ#3gOOHvg*j&AJR2)yx_lvs+3qgWA1b3G}u;A{&gS!(*aM$4Ot_v(0EI@Es zoZzy+VvEbW`905l&%O7b&vy4r&CJg3In}4Sy1qF3hNQ5d)-33E#=}}Tie&$$dZ~`_ zD;MoNt~PkW>U(c$|1Rt0_I+hK;ypZGGW}4F-Vy+flr4Ryu1fh2h6UJ2TO|QUGso{D zFGM>3BWwHh`3LRJR_Sb~Mc0ovtNo(^Z{Po{_uY>4mj0s_;#PMTaG9l;wMX8y-tzYqR(FSXv;DD;6q8ADwJwv}W5Dmoz&yv^Uq=_c zel1Le^XfwMj3$gw8Tnq}7M;wNx`aikAZQ3dmoDd1O&uMFiHWeco*c#(@XmTbK!Pb6 zHToim1_h8iZC0i(-{CBxRCltGj4=Boj3hwg9h06#oy;zig-gjfis8JNz+4BD??LM0 z5+Y{hL1>RoeI$|=MQYZe{#M_{`a;qjq4q|LAxRn;#5BC%=R$`#=4;hR9MIif27M}fl8(?@jr{3~ z^kjHKXz_*mrlzQphWrtCwkv3U~t+X9&CW6PH5*+Vay!Ne; zI3SZ?Iw{hR#wj}AkDIE6wvFM-h>MOY7bZ_%9$?j=+(-IP4W`TB`o(t~HK`MB3$%Gj&s?w?Csv2aF*}vBJD8#B*KK}0aYs+SkH{6Os4ko8$xkh^rgdeyr|hV+ zYGEHz7@f+&WK?82Dg{0Yna=E#z{g^O{$t*lKOY*QViB^1O7%0uGvXZrp4Dy7AG;HS z-fMIj#>E6tuzQV~1Q?O5I`tvbjI@5ocZ*p_QA}0yx@hb^y|{0?Mr}LI%W2tmZ6mqt z9t6|5f2?DTY|p)YMBB)y7U-Up{rxv6h{`A77|{pE^z@=TawdJZvPIKCL82*5t=NyfWUPnp zs4;w;nK$NwH}9xn3#pfsInFk^rgwLOB}9wM^q|YV=Mo zFgWL{kOuVaV}5DFw$zgmv&7&<4RS`7Ht}Rto1{?tulyG_b$WHKG%B$642a`fdC`4=$!f+R~!`fnVh zgt677$10QN)2H+;*%|cOOSiKq$k%Ga^OT5Eu$ZR`eDFslvb6hLhdSfnOM!x80MY?E zDuU@`OLI4C$y}^>t1~o5+CFI;D&>CH;dyY#S4#I|O=#xH zOI<$Y;=c9RhwXlKgC*e#9XgK(ML9$hqGi+Aam=LIVpx&$#iK8ri|3gRUoeG%vMJBG zE4-4QH`-M9hQF{!(c=##BL8hzP5hqnRQ}uVRh5VF{Vf5+5bx)Yl9syn75z7+vfH&Y@!9;n+g0TIK~`Ymh`z!p2+>6D|o7lsJX65 z5tXvB={Ke*VngrFMPXV30l7U(TKb zrK89@N_4oR5kwDB*|{8L#F_R;>r?%mv?+Xv_lovs*=!Lktu6MZGVW{7abfa{&ZDqu z-oE{#K#+#fTTtPE?r|obdoes<5K4n$h}L%|ems@F#fBN1nt~Ht#XUoWlpFCQ5MhW5 zb4(Aivy!y3MXd7*+n-`-S}{iZjts7J#Eqzlx+Q=U+2K!tc7T$J=HA9&Gn=W9P))Lb z=?|5O5>=teE?mOBPk#vKYrx#y7AbP(D%Pk0!T~{g8fd=pcbg`B9E-Tq#d-?DzBuOa zL&lsYZ9sZzygp~?^BBGi>%T%q({ze5cR`31NeX2+Ceuh{nJi&Z^@B(A-*H~BXDyxIO$~b4R0;v~bnSnWM2I83jI5L1+QmRb0x*8?rt6D4X;njtYc0Kv?IRVqD~uOM zRr{kX`pS{jHj^O4uZEJO5U_}Zimm+Ech?Gf+w|q)YM*P~{-%pjpKqUk#Ef!d;NdNQ zKRY~2ym%p5aTp53ic*B{_^HqJqCXVy{cW-52Wr}u=kHy5vntJ%l=ZNEG($pn#0Ddg z{+Rc*@20u0S@1y6H!CY&C6iAyV02yd_Ycir+rf-e^tOHFAJ`sP!^sQYNF9%Zg zDXFAtvrj&fR}W|`H8$Em12xn?8GKb#_~m#U8X#Y zwVjaKsEdQ$ejDX5WSmGv`$rvhD{BlaQL_Mx5VUriKO&FdBwwGY+*arYiF?$3h$>pc z{wSTdW?@-%@PT6W&8B5nXdY6)j-Rqmk(GyysK_5GwPZ?)atHf59x3`f>UPpKAK`EO ziG}dW&33YU=}z}imX&-&{11(5pN$G9Hlnc&wB2YN6U(#qQwk_k_-#ksn%TK=C=2{I zIkSG3cNk}#!nBQ5jN4~0&t$Bfb1BIIIC;#3$_;-U+X@&mNng6F>pqB3MY-!WW=3No z?R*HDy`c7nyHAVuXu^eSU)Xq9RU3!$AqBBjsGDG{z%*P*XRvi7Sac(8c+Mwl_M+eK z3qLD6^EkDoG~MD=+07R$r+px~ZTG@54DK>x)8w*p-ifwBqeKCG6Hx-;D1pe@->5lU zqW3AQV=#O>N9zcPXKabucIt*Z${lrKdq?8PvwG5ogRdS{HX0opjJhlku(?a29GBBQ zjA2WCOkfcZV^osV35XncmYwu_jPpQ&Dpl>r%PgOMh>d%e`m@-N<% z@Gg%%Qm1MnzK_?z+@RItE1q{wM$EVpd?=$v>Kum4AV1xQ?+Rkc`+rE&@`;Zf&i$ME zQaq7zzTmkAsH*4mT-P>+GsuXG;`ka#m8YXhS(g;VKAu;KIE_qL*!rt%r0|RuP1{F$ zAolYrwKz9H$Hh1?--8KhZrRRQpQ=@^P`v|^$AbsCh5Hq+=FL^{)s%|(=|%B>?0x0< zVn(1BDx-+GLcj?pA96s(Zsx9>W(zZ$U55c5^*eExt% zAEQKi2uF)ggBHEOdZoL6tjDtbp&?vezbOV2@FJ;d!RCN8=c zlaU#xT!T#!-j^`1i=wH(_~?J>VTpPweN_4m&-~t6Z-vz^?(>gOE{MqB)%zvko$yY! zKXG}o$0ZmK{JI!g4v1y9sX8WP%K1s1tK5L9^~KILK8Df2$ospL4;rynO!^=8lCS|~ zCvDc)c3-9&#ZK>&3KIm}<_;N1Z7h?RYzX^>;dRF7ZAqU+A#Yw0mKe>d^-_Q_@rr&^ z5CQnF$<*m@HZ6)?2{6Qtx)%##QCce2)G!!^Y1ddAiFt%7zN!*}9TlM?m@skbSd&fN zqv|0#^nLV)t{eWNPUuK~DqF|ye3zYcyHkW@S}qz?Gn3(9mqEpL9bLpr&;NU z(9B!0Qmq&}k%jgRf~;;S0qLy8{lP{ZxrEBui~51IZ-1hs6ff}O*Dy79E*~X-IR0eQ z!#S_3^gu_u?$aAp^Y$e;<>(u93;=pP;J1SbT{3S}*GXOi$Q&-9sRS)AXl$7^X0<1Dd5hjD6IO}LZy-O#^Escf5~Zgf1G7)( zk2g6Stkda!o`Ri&A08ibjiM`;y#zQMF8Q*5!cr`xUU?;)UvCa1p2vgl*I`xpbzhGj z)LvJEU#9AV@4&rJTU4)4kDD+1JvqOE{T?GEUbakMvoill4uJDt?jSE1_bKoQz+OP^qd|RDOm+f`ir&2AEuEiWA7W zv7tftT7hK8BPTBl;bG9=XEh0m!1>bU+mWznvmS2*$-*Os?zQ|YqLy}F2J2A)0x$5M z*Sc?BtO+T5oyA0hlRA}cHPN}Buh`^-e{afurg3?fvwYL1H!c9v@`eJT+WrPm?#M-T zhgC(D34x~4NpG)@rNo`)#_8R&7xB&JI4^=+Yu|jfm`LH z(`ElmfG~x5a~LwZ5a|J1#?4~O20HhMdCXV6je2hyaAV8>>hBGa$b_EaqPqHrsAcA_z8W$cn?^0z*vM(=3nS)E8yUb6?NWTG3FBWmQQG>~= z1GTJ<9f{cDVxbg~qjfR!Q%?TLgK)2^q{)y+AR+1mK=VSsc%z|nT5p{N#{67nKgziXS})j{b3WlmHIxxpJIcc@2meyO@-E z`?fTqU*_o0Py}eo+m0I?$mznPt8r)&Rb=J;lWT9%=0)>1m`kSy%O7uQjAh8vJQ%t( z_f6imN`dqNOC~nl^fHB$=x08``^WL-r|AzeE5GjrzP#tYi?RClxTZC|fl7=)!ki8L z!pTb&<%7(6S2#J?UM1L3unD+D7(cVkn z2dX*fA&{}_YQvpnB1?Hvh(ljU%9HbgCdk{NzG|b(bdG!Dw4FHYOo}$n)o<3T-sFwj zsZ7)KHxb7x+s^<=LOJ@gc|%b*ozmcB zSLEj{U*_@KUNBxCWF+hvcv98d8~zgTl}x-lK-gIV8%iS3Kr(K5d}OD(z8@e8rJLn~ zNN!%G^7*^*Q(fe~o`HH^?{j(*+NvR!$&IbIxV~lexI*V+qLu4ODQUJt_50699W0Y# zw!^2tyo2a5h@Owef_wy;gC;Vmea=-+M|)I@DyC$fhk`1L&JrFU_*YGfJfEs2CSa&Q&r&?%kva`>>0&O{*ubV3BFfGEWX{LPh-e9yx?c4^`US-S?5FV*DW|9 zwqaos?ZjWR&aN3{>+`x_yEmmo(DCkj`J?j@Q)Hm%>o!P3o6f)d6n9;f~1I)1#KuwSBqP9LfwZJ)+$S(7}7# z8q{1ZFhtr>n}_c-Q+{yFqcMsy-O8Eh{bhd52V_JX*idZAD7f$1}_zZkj5!4^m^g?V#(;$I)v@iWc^I7WWtO`p-gutZBSi|Q)DyRN5~Mf`Ciok@;hHKWkcVIQ$=)eY?KdS8}Qd0eNXv&(SwMU z5)W$5g1nYsO7>`eB_P)qTV+SHko(O4D-JL}kBKF-P65!BNo4=i@9Mu@X@0cgFubK5 z#7R8RpioBAGI(<84hg=9GU=$f@jid)N_<#W>Uh)7m%v8pZR-Zj&V8adMeukz>X_mB zb=DZT<_AbKzT-z-0Bluf?JggX-203?}-!u202RBZF za*uirFHx6I?<5j?ac^~Pe6i!(XTmq%*Co=PW8BFqr8QNR7~)R70=fZ5jSK=!ysu+J zz$_D{n9UM_0=b1;W?TGUSRZWJTQrrHjisyUq%`kY0pahPAcuKbI6E2WY zfJZ%5Z}yl;fSgZ4;CWymzVghooN%*qjza_Cl2P_r`k`9+YGz(J6e ztuN>WSG;ZXd-J<;uDhN`d0gPvtz`$ri3&p(MUOT`t5x;YQH(jlLOdCX(27`z(bXS| z#>?3m{L&9y{^@U1rQ&_z3!QDKbBw7pgJYKQn$6#>U>axW(o8wNR_LZZJb4P_RyVmi zyu))~a3E+v@(7iv@kydABq;pZQp&O$>Zr(8<)F!E6Yo()S+AXfl;p6meN{$;0U~?H zx4zkmG;dTn(I)I^2Tb-%KYHBEdQD17XxsZRZ1W=zr^DIkIK#4Z^;(0}YGIfyOqEUH zXqzw&A$)pY4ILJH`&LbIN0Xh0Aj5EDym(sX3YSr?wEm{XT&SR<5x;ebX!NsQPAg4u zLxUR~hpf?N-n-YC#MI&pgUf=Xma=h`ba+3W(DrPs%0~3TziiE~&z=W!zp%zBxy8e# zu23}d6|G(BNd#({#oPrWRzI;H?`4IW=CD(DSpKs6`K) znk68LgeB8k4=UPw%(bQ9NG5#g?lBD=wuZ}0a*}_fdkb~g&ET7`K*DPFJ7mx|{b+I- z{ndIdCZ%ZTPhjrN_d3B`?6t`m@yQ>q@6jHD7A*B<<1Oo{vW$qKT`J-M;E%)`l*~iX zUi`P(zi9Y!T_?*iw|vNwGw5(G3s4BD4;?1l9(X;g7Y&P8((8>Ds z1S@h@>gV+Mk%|n1*|wVfi0u3d%rqX|n*sLJ>dr#lV!i^?ugXTf^{(FK%b{uwe=s#j zD^6ant}h|C);A9`;2XBD8D>tf=JP$pA8k6bkxBVsQ;Mxje&vF*=`uv3Ui1OkV^ViJnZe%$vl8OiCN?w*#7V0VeZwIo11QDsfle z`|tqjz3Z2F-6t`9JqUiuFn!+2=zU)34eEH_2S_~LbH1L}OFT6J|Bhe9PT;dKR@U(B zy7osgzb64yqmjj2$42M$&=EFoD*o|5;*~^wdQweIK;Xb!h8JeM6_9g7tK3dLP|2}G zRpH#+v!`SvBJT;^k&~n!Q)zg0Qk7{3hum$_ zKCW*p@Ji+U@%fb=U52$J{o2bc#%{Q0tfu;7>_+8JIYB-say&5b(a`WU=mK);bAQxw zzrJ-z^^CKnxAmY4rH_@7`6%?dVcG;Lc|E_~0|udw_{M_RWNsD>--Z`tE`0Y+YhA-f zu}UB{Mh;S$@m`E`bvbY&ztq?r331BVv$P$?4+cT#s}a}3E5xiP9y3L|zcRc_vw z^~@Ug{JK=R&xI1EE6k8yY0$N31x|j~M=mGWd&nz_4b+4>q}Ee@FdI|QvUrp<3*Bjz zwbVV9Csm1Yqj0P?l4_OtxcRA;En>~pf&C8O26e}ze(SQvji7XJ`L^_cRb1l*Y^xvb zZAJekN*0e>PM}+fOWHh3wQ35jT1YPNfV4;~e+!_qODU)Mf$*ZzOwP^49l0)jt+@zX z49g$=Rcz*{4cXL}+dYbrSc&1;y>I-=OH-fFc<&*_$_ z<_7JE0ELx_(|-Ow>^}T>NQ=CuW zERBIu_s$H=1CR8yb@b8&XKeN+E=`0!#Mp*571Yn0x;$<5OZx_!1J@m;)(COv{ATz2 zx|vn%QsOWqw!`z)4Y(3lu$}fB^iR?E_6Ag+M<#nA)0JztVVlpGO8xb(2cX`U3C^Gk zdUDXlv;2Voy*GB-d^c&>uu#&XKr6*Z$CYR$dPh_9pw)LPB;P8Vmqxy9icFAH)QK0; zDr3;4N$&a8{}P;{{=8dEGg+rs(j@!oWjWjWowqXramfqbuxz#*N84qUBofiEID0ry zNz>aX>HVz}#duA8MxV*CAzq3RLeh{4pB`(n^rc>#=r*3PG=o1ed$7#V%2y&Mc&a3H zimE>w?28Anh2*4GLMYCD!B5>OlXfao6F#}&YK{yh4$iSIO(z(y(sft4JoIvw_;os3 z>!R2aPB=hMgAv=*z8tax{LHd)~a4U_jwB}b`>@UYO(l0pqSz@1d)5gizTl9x9{#Y}0M68?6J^gFfp z)Rm)UI;3~clu0Y;m~km|FoNkY6Q1I~lzy0I#T3#be^j%wAJNuzRs9-uYdifY^kjht zwD3vGNBGPvX5{5rKnIZy_qO_#^r>~iF8LRRMmVxF$;1+AnIZ9se&&&fNh}UNJ-

      @Xh0^ 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≫+}c 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

      ( - IsarReader reader, - int propertyId, - int offset, - Map> allOffsets, -) { - switch (propertyId) { - case 0: - return (reader.readLong(offset)) as P; - case 1: - return (reader.readBool(offset)) as P; - case 2: - return (reader.readBool(offset)) as P; - case 3: - return (reader.readLong(offset)) as P; - case 4: - return (reader.readStringOrNull(offset)) as P; - case 5: - return (reader.readString(offset)) as P; - case 6: - return (reader.readString(offset)) as P; - case 7: - return (reader.readString(offset)) as P; - default: - throw IsarError('Unknown property with id $propertyId'); - } -} - -Id _lelantusCoinGetId(LelantusCoin object) { - return object.id; -} - -List> _lelantusCoinGetLinks(LelantusCoin object) { - return []; -} - -void _lelantusCoinAttach( - IsarCollection col, Id id, LelantusCoin object) { - object.id = id; -} - -extension LelantusCoinByIndex on IsarCollection { - Future getByMintIndexWalletId(int mintIndex, String walletId) { - return getByIndex(r'mintIndex_walletId', [mintIndex, walletId]); - } - - LelantusCoin? getByMintIndexWalletIdSync(int mintIndex, String walletId) { - return getByIndexSync(r'mintIndex_walletId', [mintIndex, walletId]); - } - - Future deleteByMintIndexWalletId(int mintIndex, String walletId) { - return deleteByIndex(r'mintIndex_walletId', [mintIndex, walletId]); - } - - bool deleteByMintIndexWalletIdSync(int mintIndex, String walletId) { - return deleteByIndexSync(r'mintIndex_walletId', [mintIndex, walletId]); - } - - Future> getAllByMintIndexWalletId( - List mintIndexValues, List walletIdValues) { - final len = mintIndexValues.length; - assert(walletIdValues.length == len, - 'All index values must have the same length'); - final values = >[]; - for (var i = 0; i < len; i++) { - values.add([mintIndexValues[i], walletIdValues[i]]); - } - - return getAllByIndex(r'mintIndex_walletId', values); - } - - List getAllByMintIndexWalletIdSync( - List mintIndexValues, List walletIdValues) { - final len = mintIndexValues.length; - assert(walletIdValues.length == len, - 'All index values must have the same length'); - final values = >[]; - for (var i = 0; i < len; i++) { - values.add([mintIndexValues[i], walletIdValues[i]]); - } - - return getAllByIndexSync(r'mintIndex_walletId', values); - } - - Future deleteAllByMintIndexWalletId( - List mintIndexValues, List walletIdValues) { - final len = mintIndexValues.length; - assert(walletIdValues.length == len, - 'All index values must have the same length'); - final values = >[]; - for (var i = 0; i < len; i++) { - values.add([mintIndexValues[i], walletIdValues[i]]); - } - - return deleteAllByIndex(r'mintIndex_walletId', values); - } - - int deleteAllByMintIndexWalletIdSync( - List mintIndexValues, List walletIdValues) { - final len = mintIndexValues.length; - assert(walletIdValues.length == len, - 'All index values must have the same length'); - final values = >[]; - for (var i = 0; i < len; i++) { - values.add([mintIndexValues[i], walletIdValues[i]]); - } - - return deleteAllByIndexSync(r'mintIndex_walletId', values); - } - - Future putByMintIndexWalletId(LelantusCoin object) { - return putByIndex(r'mintIndex_walletId', object); - } - - Id putByMintIndexWalletIdSync(LelantusCoin object, {bool saveLinks = true}) { - return putByIndexSync(r'mintIndex_walletId', object, saveLinks: saveLinks); - } - - Future> putAllByMintIndexWalletId(List objects) { - return putAllByIndex(r'mintIndex_walletId', objects); - } - - List putAllByMintIndexWalletIdSync(List objects, - {bool saveLinks = true}) { - return putAllByIndexSync(r'mintIndex_walletId', objects, - saveLinks: saveLinks); - } -} - -extension LelantusCoinQueryWhereSort - on QueryBuilder { - QueryBuilder anyId() { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(const IdWhereClause.any()); - }); - } -} - -extension LelantusCoinQueryWhere - on QueryBuilder { - QueryBuilder idEqualTo(Id id) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: id, - upper: id, - )); - }); - } - - QueryBuilder idNotEqualTo( - Id id) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ) - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ); - } else { - return query - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ) - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ); - } - }); - } - - QueryBuilder idGreaterThan( - Id id, - {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: include), - ); - }); - } - - QueryBuilder idLessThan(Id id, - {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: include), - ); - }); - } - - QueryBuilder idBetween( - Id lowerId, - Id upperId, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: lowerId, - includeLower: includeLower, - upper: upperId, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder walletIdEqualTo( - String walletId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'walletId', - value: [walletId], - )); - }); - } - - QueryBuilder - walletIdNotEqualTo(String walletId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )); - } - }); - } - - QueryBuilder - mintIndexEqualToAnyWalletId(int mintIndex) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'mintIndex_walletId', - value: [mintIndex], - )); - }); - } - - QueryBuilder - mintIndexNotEqualToAnyWalletId(int mintIndex) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [], - upper: [mintIndex], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [], - upper: [mintIndex], - includeUpper: false, - )); - } - }); - } - - QueryBuilder - mintIndexGreaterThanAnyWalletId( - int mintIndex, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex], - includeLower: include, - upper: [], - )); - }); - } - - QueryBuilder - mintIndexLessThanAnyWalletId( - int mintIndex, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [], - upper: [mintIndex], - includeUpper: include, - )); - }); - } - - QueryBuilder - mintIndexBetweenAnyWalletId( - int lowerMintIndex, - int upperMintIndex, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [lowerMintIndex], - includeLower: includeLower, - upper: [upperMintIndex], - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - mintIndexWalletIdEqualTo(int mintIndex, String walletId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'mintIndex_walletId', - value: [mintIndex, walletId], - )); - }); - } - - QueryBuilder - mintIndexEqualToWalletIdNotEqualTo(int mintIndex, String walletId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex], - upper: [mintIndex, walletId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex, walletId], - includeLower: false, - upper: [mintIndex], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex, walletId], - includeLower: false, - upper: [mintIndex], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'mintIndex_walletId', - lower: [mintIndex], - upper: [mintIndex, walletId], - includeUpper: false, - )); - } - }); - } -} - -extension LelantusCoinQueryFilter - on QueryBuilder { - QueryBuilder - anonymitySetIdEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'anonymitySetId', - value: value, - )); - }); - } - - QueryBuilder - anonymitySetIdGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'anonymitySetId', - value: value, - )); - }); - } - - QueryBuilder - anonymitySetIdLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'anonymitySetId', - value: value, - )); - }); - } - - QueryBuilder - anonymitySetIdBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'anonymitySetId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder idEqualTo( - Id value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'id', - value: value, - )); - }); - } - - QueryBuilder idGreaterThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder idLessThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder idBetween( - Id lower, - Id upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'id', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - isJMintEqualTo(bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isJMint', - value: value, - )); - }); - } - - QueryBuilder isUsedEqualTo( - bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isUsed', - value: value, - )); - }); - } - - QueryBuilder - mintIndexEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'mintIndex', - value: value, - )); - }); - } - - QueryBuilder - mintIndexGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'mintIndex', - value: value, - )); - }); - } - - QueryBuilder - mintIndexLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'mintIndex', - value: value, - )); - }); - } - - QueryBuilder - mintIndexBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'mintIndex', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - otherDataIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'otherData', - )); - }); - } - - QueryBuilder - otherDataIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'otherData', - )); - }); - } - - QueryBuilder - otherDataEqualTo( - String? value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataGreaterThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataLessThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataBetween( - String? lower, - String? upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'otherData', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'otherData', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'otherData', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - otherDataIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'otherData', - value: '', - )); - }); - } - - QueryBuilder - otherDataIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'otherData', - value: '', - )); - }); - } - - QueryBuilder txidEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder txidLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder txidBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'txid', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder txidEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder txidContains( - String value, - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder txidMatches( - String pattern, - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'txid', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'txid', - value: '', - )); - }); - } - - QueryBuilder - txidIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'txid', - value: '', - )); - }); - } - - QueryBuilder valueEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - valueGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder valueLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder valueBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'value', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - valueStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder valueEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder valueContains( - String value, - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'value', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder valueMatches( - String pattern, - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'value', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - valueIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'value', - value: '', - )); - }); - } - - QueryBuilder - valueIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'value', - value: '', - )); - }); - } - - QueryBuilder - walletIdEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'walletId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'walletId', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: '', - )); - }); - } - - QueryBuilder - walletIdIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'walletId', - value: '', - )); - }); - } -} - -extension LelantusCoinQueryObject - on QueryBuilder {} - -extension LelantusCoinQueryLinks - on QueryBuilder {} - -extension LelantusCoinQuerySortBy - on QueryBuilder { - QueryBuilder - sortByAnonymitySetId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'anonymitySetId', Sort.asc); - }); - } - - QueryBuilder - sortByAnonymitySetIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'anonymitySetId', Sort.desc); - }); - } - - QueryBuilder sortByIsJMint() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isJMint', Sort.asc); - }); - } - - QueryBuilder sortByIsJMintDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isJMint', Sort.desc); - }); - } - - QueryBuilder sortByIsUsed() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isUsed', Sort.asc); - }); - } - - QueryBuilder sortByIsUsedDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isUsed', Sort.desc); - }); - } - - QueryBuilder sortByMintIndex() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'mintIndex', Sort.asc); - }); - } - - QueryBuilder sortByMintIndexDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'mintIndex', Sort.desc); - }); - } - - QueryBuilder sortByOtherData() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'otherData', Sort.asc); - }); - } - - QueryBuilder sortByOtherDataDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'otherData', Sort.desc); - }); - } - - QueryBuilder sortByTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.asc); - }); - } - - QueryBuilder sortByTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.desc); - }); - } - - QueryBuilder sortByValue() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'value', Sort.asc); - }); - } - - QueryBuilder sortByValueDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'value', Sort.desc); - }); - } - - QueryBuilder sortByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder sortByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension LelantusCoinQuerySortThenBy - on QueryBuilder { - QueryBuilder - thenByAnonymitySetId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'anonymitySetId', Sort.asc); - }); - } - - QueryBuilder - thenByAnonymitySetIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'anonymitySetId', Sort.desc); - }); - } - - QueryBuilder thenById() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.asc); - }); - } - - QueryBuilder thenByIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.desc); - }); - } - - QueryBuilder thenByIsJMint() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isJMint', Sort.asc); - }); - } - - QueryBuilder thenByIsJMintDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isJMint', Sort.desc); - }); - } - - QueryBuilder thenByIsUsed() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isUsed', Sort.asc); - }); - } - - QueryBuilder thenByIsUsedDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isUsed', Sort.desc); - }); - } - - QueryBuilder thenByMintIndex() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'mintIndex', Sort.asc); - }); - } - - QueryBuilder thenByMintIndexDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'mintIndex', Sort.desc); - }); - } - - QueryBuilder thenByOtherData() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'otherData', Sort.asc); - }); - } - - QueryBuilder thenByOtherDataDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'otherData', Sort.desc); - }); - } - - QueryBuilder thenByTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.asc); - }); - } - - QueryBuilder thenByTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.desc); - }); - } - - QueryBuilder thenByValue() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'value', Sort.asc); - }); - } - - QueryBuilder thenByValueDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'value', Sort.desc); - }); - } - - QueryBuilder thenByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder thenByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension LelantusCoinQueryWhereDistinct - on QueryBuilder { - QueryBuilder - distinctByAnonymitySetId() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'anonymitySetId'); - }); - } - - QueryBuilder distinctByIsJMint() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isJMint'); - }); - } - - QueryBuilder distinctByIsUsed() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isUsed'); - }); - } - - QueryBuilder distinctByMintIndex() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'mintIndex'); - }); - } - - QueryBuilder distinctByOtherData( - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'otherData', caseSensitive: caseSensitive); - }); - } - - QueryBuilder distinctByTxid( - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'txid', caseSensitive: caseSensitive); - }); - } - - QueryBuilder distinctByValue( - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'value', caseSensitive: caseSensitive); - }); - } - - QueryBuilder distinctByWalletId( - {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); - }); - } -} - -extension LelantusCoinQueryProperty - on QueryBuilder { - QueryBuilder idProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'id'); - }); - } - - QueryBuilder anonymitySetIdProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'anonymitySetId'); - }); - } - - QueryBuilder isJMintProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isJMint'); - }); - } - - QueryBuilder isUsedProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isUsed'); - }); - } - - QueryBuilder mintIndexProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'mintIndex'); - }); - } - - QueryBuilder otherDataProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'otherData'); - }); - } - - QueryBuilder txidProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'txid'); - }); - } - - QueryBuilder valueProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'value'); - }); - } - - QueryBuilder walletIdProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'walletId'); - }); - } -} diff --git a/lib/models/isar/models/isar_models.dart b/lib/models/isar/models/isar_models.dart index 9de91fc84..ce7652a46 100644 --- a/lib/models/isar/models/isar_models.dart +++ b/lib/models/isar/models/isar_models.dart @@ -15,6 +15,5 @@ export 'blockchain_data/output.dart'; export 'blockchain_data/transaction.dart'; export 'blockchain_data/utxo.dart'; export 'ethereum/eth_contract.dart'; -export 'firo_specific/lelantus_coin.dart'; export 'log.dart'; export 'transaction_note.dart'; diff --git a/lib/models/lelantus_fee_data.dart b/lib/models/lelantus_fee_data.dart deleted file mode 100644 index 1ba930a29..000000000 --- a/lib/models/lelantus_fee_data.dart +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -class LelantusFeeData { - int changeToMint; - int fee; - List spendCoinIndexes; - LelantusFeeData(this.changeToMint, this.fee, this.spendCoinIndexes); - - @override - String toString() { - return "{changeToMint: $changeToMint, fee: $fee, spendCoinIndexes: $spendCoinIndexes}"; - } -} diff --git a/lib/models/models.dart b/lib/models/models.dart index 3f6aaa525..51282c824 100644 --- a/lib/models/models.dart +++ b/lib/models/models.dart @@ -9,7 +9,6 @@ */ export 'lelantus_coin.dart'; -export 'lelantus_fee_data.dart'; export 'paymint/fee_object_model.dart'; export 'paymint/transactions_model.dart'; export 'paymint/utxo_model.dart'; diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index e16ab5b0c..970614542 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -142,8 +142,6 @@ class _NewWalletRecoveryPhraseWarningViewState // ), // }, // ); - } else if (widget.coin is Firo) { - otherDataJson = {WalletInfoKeys.lelantusCoinIsarRescanRequired: false}; } if (ref.read(pDuress)) { @@ -184,7 +182,10 @@ class _NewWalletRecoveryPhraseWarningViewState // TODO: Refactor these to generate each coin in their respective classes // This code should not be in a random view page file - if (coin is Monero || coin is Wownero || coin is Xelis || coin is Salvium) { + if (coin is Monero || + coin is Wownero || + coin is Xelis || + coin is Salvium) { // currently a special case due to the // xmr/wow libraries handling their // own mnemonic generation diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index e09882a7c..5cc90beba 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -33,7 +33,6 @@ import '../../../../wallets/crypto_currency/intermediate/cryptonote_currency.dar import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/blue_text_button.dart'; -import '../../../../widgets/custom_buttons/checkbox_text_button.dart'; import '../../../../widgets/date_picker/date_picker.dart'; import '../../../../widgets/desktop/desktop_app_bar.dart'; import '../../../../widgets/desktop/desktop_scaffold.dart'; @@ -86,9 +85,6 @@ class _RestoreOptionsViewState extends ConsumerState { DateTime? _restoreFromDate; bool hidePassword = true; - bool enableLelantusScanning = false; - bool get supportsLelantus => coin is Firo; - @override void initState() { super.initState(); @@ -149,13 +145,12 @@ class _RestoreOptionsViewState extends ConsumerState { if (!_showViewOnlyOption) { await Navigator.of(context).pushNamed( RestoreWalletView.routeName, - arguments: Tuple6( + arguments: Tuple5( walletName, coin, ref.read(mnemonicWordCountStateProvider.state).state, height, passwordController.text, - enableLelantusScanning, ), ); } else { @@ -165,7 +160,6 @@ class _RestoreOptionsViewState extends ConsumerState { walletName: walletName, coin: coin, restoreBlockHeight: height, - enableLelantusScanning: enableLelantusScanning, ), ); } @@ -353,9 +347,6 @@ class _RestoreOptionsViewState extends ConsumerState { dateChooserFunction: isDesktop ? chooseDesktopDate : chooseDate, chooseMnemonicLength: chooseMnemonicLength, - lelScanChanged: (value) { - enableLelantusScanning = value; - }, ), if (!isDesktop) const Spacer(flex: 3), SizedBox(height: isDesktop ? 32 : 12), @@ -386,7 +377,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { required this.pwFocusNode, required this.dateChooserFunction, required this.chooseMnemonicLength, - required this.lelScanChanged, }); final CryptoCurrency coin; @@ -398,7 +388,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { final Future Function() dateChooserFunction; final Future Function() chooseMnemonicLength; - final void Function(bool) lelScanChanged; @override ConsumerState createState() => _SeedRestoreOptionState(); @@ -407,7 +396,6 @@ class SeedRestoreOption extends ConsumerStatefulWidget { class _SeedRestoreOptionState extends ConsumerState { bool _hidePassword = true; bool _expandedAdvanced = false; - bool _enableLelantusScanning = false; bool _blockFieldEmpty = true; @override @@ -669,17 +657,6 @@ class _SeedRestoreOptionState extends ConsumerState { color: Colors.transparent, child: Column( children: [ - if (widget.coin is Firo) - CheckboxTextButton( - label: "Scan for Lelantus transactions", - onChanged: (newValue) { - setState(() { - _enableLelantusScanning = newValue ?? true; - }); - - widget.lelScanChanged(_enableLelantusScanning); - }, - ), if (widget.coin is Firo) const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart index 2ad57cf02..606841139 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart @@ -48,8 +48,6 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { required this.walletName, required this.coin, required this.restoreBlockHeight, - this.enableLelantusScanning = false, - this.clipboard = const ClipboardWrapper(), }); @@ -58,7 +56,6 @@ class RestoreViewOnlyWalletView extends ConsumerStatefulWidget { final String walletName; final CryptoCurrency coin; final int restoreBlockHeight; - final bool enableLelantusScanning; final ClipboardInterface clipboard; @override @@ -111,12 +108,6 @@ class _RestoreViewOnlyWalletViewState final ViewOnlyWalletType viewOnlyWalletType; if (widget.coin is Bip39HDCurrency) { - if (widget.coin is Firo) { - otherDataJson.addAll({ - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: widget.enableLelantusScanning, - }); - } viewOnlyWalletType = _addressOnly ? ViewOnlyWalletType.addressOnly diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index d56a69a8c..b4aeb3693 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -77,8 +77,6 @@ class RestoreWalletView extends ConsumerStatefulWidget { required this.seedWordsLength, required this.mnemonicPassphrase, required this.restoreBlockHeight, - this.enableLelantusScanning = false, - this.clipboard = const ClipboardWrapper(), }); @@ -89,7 +87,6 @@ class RestoreWalletView extends ConsumerStatefulWidget { final String mnemonicPassphrase; final int seedWordsLength; final int restoreBlockHeight; - final bool enableLelantusScanning; final ClipboardInterface clipboard; @@ -245,11 +242,6 @@ class _RestoreWalletViewState extends ConsumerState { ).toMap(), ), }); - } else if (widget.coin is Firo) { - otherDataJsonString = jsonEncode({ - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: widget.enableLelantusScanning, - }); } // TODO: do actual check to make sure it is a valid mnemonic for monero + xelis diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart index ef959aa22..c562ec88e 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart @@ -117,12 +117,6 @@ class _VerifyRecoveryPhraseViewState final ViewOnlyWalletType viewOnlyWalletType; if (widget.wallet is ExtendedKeysInterface) { - if (widget.wallet.cryptoCurrency is Firo) { - otherDataJson.addAll({ - WalletInfoKeys.lelantusCoinIsarRescanRequired: false, - WalletInfoKeys.enableLelantusScanning: false, - }); - } viewOnlyWalletType = ViewOnlyWalletType.xPub; } else if (widget.wallet is LibMoneroWallet || widget.wallet is LibSalviumWallet) { diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index ac6d9863c..d34306cf4 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -150,10 +150,6 @@ class _ConfirmTransactionViewState } break; - case FiroType.lelantus: - txDataFuture = wallet.confirmSendLelantus(txData: widget.txData); - break; - case FiroType.spark: txDataFuture = wallet.confirmSendSpark(txData: widget.txData); break; @@ -364,11 +360,6 @@ class _ConfirmTransactionViewState } break; - case FiroType.lelantus: - fee = widget.txData.fee; - amountWithoutChange = widget.txData.amountWithoutChange!; - break; - case FiroType.spark: fee = widget.txData.fee; amountWithoutChange = diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index d2806d513..54a2f2f8c 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -498,7 +498,6 @@ class _SendViewState extends ConsumerState { late Future _calculateFeesFuture; Map cachedFees = {}; - Map cachedFiroLelantusFees = {}; Map cachedFiroSparkFees = {}; Map cachedFiroPublicFees = {}; @@ -514,11 +513,6 @@ class _SendViewState extends ConsumerState { return cachedFiroPublicFees[amount]!; } break; - case FiroType.lelantus: - if (cachedFiroLelantusFees[amount] != null) { - return cachedFiroLelantusFees[amount]!; - } - break; case FiroType.spark: if (cachedFiroSparkFees[amount] != null) { return cachedFiroSparkFees[amount]!; @@ -585,12 +579,6 @@ class _SendViewState extends ConsumerState { .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroPublicFees[amount]!; - case FiroType.lelantus: - fee = await firoWallet.estimateFeeForLelantus(amount); - cachedFiroLelantusFees[amount] = ref - .read(pAmountFormatter(coin)) - .format(fee, withUnitName: true, indicatePrecisionLoss: false); - return cachedFiroLelantusFees[amount]!; case FiroType.spark: fee = await firoWallet.estimateFeeForSpark(amount); cachedFiroSparkFees[amount] = ref @@ -621,9 +609,6 @@ class _SendViewState extends ConsumerState { case FiroType.public: availableBalance = wallet.info.cachedBalance.spendable; break; - case FiroType.lelantus: - availableBalance = wallet.info.cachedBalanceSecondary.spendable; - break; case FiroType.spark: availableBalance = wallet.info.cachedBalanceTertiary.spendable; break; @@ -783,16 +768,6 @@ class _SendViewState extends ConsumerState { } break; - case FiroType.lelantus: - txDataFuture = wallet.prepareSendLelantus( - txData: TxData( - recipients: [ - (address: _address!, amount: amount, isChange: false), - ], - ), - ); - break; - case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( @@ -953,9 +928,7 @@ class _SendViewState extends ConsumerState { case FiroType.public: amount = ref.read(pWalletBalance(walletId)).spendable; break; - case FiroType.lelantus: - amount = ref.read(pWalletBalanceSecondary(walletId)).spendable; - break; + case FiroType.spark: amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; break; @@ -1358,16 +1331,7 @@ class _SendViewState extends ConsumerState { ) .spendable; break; - case FiroType.lelantus: - amount = - ref - .read( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; + case FiroType.spark: amount = ref @@ -1616,11 +1580,7 @@ class _SendViewState extends ConsumerState { ), const SizedBox(height: 10), if (isStellar || - (ref.watch(pValidSparkSendToAddress) && - ref.watch( - publicPrivateBalanceStateProvider, - ) != - FiroType.lelantus)) + ref.watch(pValidSparkSendToAddress)) ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -1712,43 +1672,14 @@ class _SendViewState extends ConsumerState { if (_address == null || _address!.isEmpty) { error = null; } else if (isFiro) { - if (ref.watch( - publicPrivateBalanceStateProvider, - ) == - FiroType.lelantus) { - if (_data != null && - _data.contactLabel == _address) { - error = - SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: - coin.network == - CryptoCurrencyNetwork.test, - ) - ? "Unsupported" - : null; - } else if (ref.watch( - pValidSparkSendToAddress, - )) { - error = "Unsupported"; - } else { - error = - ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; - } + if (_data != null && + _data.contactLabel == _address) { + error = null; + } else if (!ref.watch(pValidSendToAddress) && + !ref.watch(pValidSparkSendToAddress)) { + error = "Invalid address"; } else { - if (_data != null && - _data.contactLabel == _address) { - error = null; - } else if (!ref.watch( - pValidSendToAddress, - ) && - !ref.watch(pValidSparkSendToAddress)) { - error = "Invalid address"; - } else { - error = null; - } + error = null; } } else { if (_data != null && @@ -1868,16 +1799,6 @@ class _SendViewState extends ConsumerState { ) .spendable; break; - case FiroType.lelantus: - amount = - ref - .watch( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; case FiroType.spark: amount = ref diff --git a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart b/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart index 912fad545..87c6da542 100644 --- a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart @@ -20,10 +20,7 @@ import '../../../utilities/text_styles.dart'; import '../../../wallets/wallet/impl/firo_wallet.dart'; class FiroBalanceSelectionSheet extends ConsumerStatefulWidget { - const FiroBalanceSelectionSheet({ - super.key, - required this.walletId, - }); + const FiroBalanceSelectionSheet({super.key, required this.walletId}); final String walletId; @@ -46,8 +43,9 @@ class _FiroBalanceSelectionSheetState Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final wallet = - ref.watch(pWallets.select((value) => value.getWallet(walletId))); + final wallet = ref.watch( + pWallets.select((value) => value.getWallet(walletId)), + ); final firoWallet = wallet as FiroWallet; final coin = wallet.info.coin; @@ -55,17 +53,10 @@ class _FiroBalanceSelectionSheetState return Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Padding( - padding: const EdgeInsets.only( - left: 24, - right: 24, - top: 10, - bottom: 0, - ), + padding: const EdgeInsets.only(left: 24, right: 24, top: 10, bottom: 0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -73,9 +64,10 @@ class _FiroBalanceSelectionSheetState Center( child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -84,9 +76,7 @@ class _FiroBalanceSelectionSheetState height: 4, ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -95,9 +85,7 @@ class _FiroBalanceSelectionSheetState style: STextStyles.pageTitleH2(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), GestureDetector( onTap: () { final state = @@ -120,15 +108,18 @@ class _FiroBalanceSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FiroType.spark, - groupValue: ref - .watch( - publicPrivateBalanceStateProvider.state, - ) - .state, + groupValue: + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state, onChanged: (x) { ref .read( @@ -142,9 +133,7 @@ class _FiroBalanceSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -156,13 +145,15 @@ class _FiroBalanceSelectionSheetState style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), - const SizedBox( - width: 2, - ), + const SizedBox(width: 2), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( firoWallet - .info.cachedBalanceTertiary.spendable, + .info + .cachedBalanceTertiary + .spendable, ), style: STextStyles.itemSubtitle(context), textAlign: TextAlign.left, @@ -176,97 +167,8 @@ class _FiroBalanceSelectionSheetState ), ), ), - if (firoWallet.info.cachedBalanceSecondary.spendable.raw > - BigInt.zero) - const SizedBox( - height: 16, - ), - if (firoWallet.info.cachedBalanceSecondary.spendable.raw > - BigInt.zero) - GestureDetector( - onTap: () { - final state = ref - .read(publicPrivateBalanceStateProvider.state) - .state; - if (state != FiroType.lelantus) { - ref - .read(publicPrivateBalanceStateProvider.state) - .state = FiroType.lelantus; - } - Navigator.of(context).pop(); - }, - child: Container( - color: Colors.transparent, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: FiroType.lelantus, - groupValue: ref - .watch( - publicPrivateBalanceStateProvider.state, - ) - .state, - onChanged: (x) { - ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state = FiroType.lelantus; - Navigator.of(context).pop(); - }, - ), - ), - ], - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Row( - // children: [ - Text( - "Lelantus balance", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - const SizedBox( - width: 2, - ), - Text( - ref.watch(pAmountFormatter(coin)).format( - firoWallet.info.cachedBalanceSecondary - .spendable, - ), - style: STextStyles.itemSubtitle(context), - textAlign: TextAlign.left, - ), - ], - ), - // ], - // ), - ), - ], - ), - ), - ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), GestureDetector( onTap: () { final state = @@ -288,15 +190,18 @@ class _FiroBalanceSelectionSheetState width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: FiroType.public, - groupValue: ref - .watch( - publicPrivateBalanceStateProvider.state, - ) - .state, + groupValue: + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state, onChanged: (x) { ref .read( @@ -309,9 +214,7 @@ class _FiroBalanceSelectionSheetState ), ], ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -323,11 +226,11 @@ class _FiroBalanceSelectionSheetState style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), - const SizedBox( - width: 2, - ), + const SizedBox(width: 2), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( firoWallet.info.cachedBalance.spendable, ), style: STextStyles.itemSubtitle(context), @@ -340,12 +243,8 @@ class _FiroBalanceSelectionSheetState ), ), ), - const SizedBox( - height: 16, - ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 16), + const SizedBox(height: 24), ], ), ], diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index 41cdac17e..2257af491 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -101,10 +101,6 @@ class _TransactionFeeSelectionSheetState fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, @@ -142,10 +138,6 @@ class _TransactionFeeSelectionSheetState fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, @@ -182,10 +174,6 @@ class _TransactionFeeSelectionSheetState fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart index 404490163..06c3774a4 100644 --- a/lib/pages/settings_views/global_settings_view/about_view.dart +++ b/lib/pages/settings_views/global_settings_view/about_view.dart @@ -177,45 +177,6 @@ class AboutView extends ConsumerWidget { ); }, ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox(height: 12), - if (AppConfig.coins.whereType().isNotEmpty) - FutureBuilder( - future: GitStatus.getFiroCommitStatus(), - builder: ( - context, - AsyncSnapshot snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - stateOfCommit = snapshot.data!; - } - return RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Firo Build Commit", - style: STextStyles.titleBold12(context), - ), - const SizedBox(height: 4), - SelectableText( - GitStatus.firoCommit, - style: GitStatus.styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ), - ); - }, - ), if (AppConfig.coins.whereType().isNotEmpty) const SizedBox(height: 12), if (AppConfig.coins.whereType().isNotEmpty) @@ -256,50 +217,7 @@ class AboutView extends ConsumerWidget { ); }, ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox(height: 12), - // if (AppConfig.coins.whereType().isNotEmpty) - // FutureBuilder( - // future: GitStatus.getMoneroCommitStatus(), - // builder: ( - // context, - // AsyncSnapshot snapshot, - // ) { - // CommitStatus stateOfCommit = - // CommitStatus.notLoaded; - // - // if (snapshot.connectionState == - // ConnectionState.done && - // snapshot.hasData) { - // stateOfCommit = snapshot.data!; - // } - // return RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: - // CrossAxisAlignment.stretch, - // children: [ - // Text( - // "Monero Build Commit", - // style: STextStyles.titleBold12(context), - // ), - // const SizedBox( - // height: 4, - // ), - // SelectableText( - // GitStatus.moneroCommit, - // style: GitStatus.styleForStatus( - // stateOfCommit, - // context, - // ), - // ), - // ], - // ), - // ); - // }, - // ), - // const SizedBox( - // height: 12, - // ), + const SizedBox(height: 12), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index 57643c43b..d0200b034 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -506,7 +506,9 @@ abstract class SWB { int restoreHeight = walletbackup['restoreHeight'] as int? ?? 0; if (restoreHeight <= 0) { - if (wallet is EpiccashWallet || wallet is LibMoneroWallet || wallet is LibSalviumWallet) { + if (wallet is EpiccashWallet || + wallet is LibMoneroWallet || + wallet is LibSalviumWallet) { restoreHeight = 0; } else { restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0; @@ -791,13 +793,6 @@ abstract class SWB { ); } - 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 - otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = false; - } - final info = WalletInfo( coinName: coin.identifier, walletId: walletId, diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart deleted file mode 100644 index accd91416..000000000 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; - -import '../../../../providers/db/main_db_provider.dart'; -import '../../../../providers/global/wallets_provider.dart'; -import '../../../../themes/stack_colors.dart'; -import '../../../../utilities/logger.dart'; -import '../../../../utilities/show_loading.dart'; -import '../../../../utilities/text_styles.dart'; -import '../../../../utilities/util.dart'; -import '../../../../wallets/isar/models/wallet_info.dart'; -import '../../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../../widgets/background.dart'; -import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; -import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; -import '../../../../widgets/desktop/primary_button.dart'; -import '../../../../widgets/desktop/secondary_button.dart'; -import '../../../../widgets/stack_dialog.dart'; - -class LelantusSettingsView extends ConsumerStatefulWidget { - const LelantusSettingsView({super.key, required this.walletId}); - - static const String routeName = "/lelantusSettings"; - - final String walletId; - - @override - ConsumerState createState() => - _LelantusSettingsViewState(); -} - -class _LelantusSettingsViewState extends ConsumerState { - bool _isUpdatingLelantusScanning = false; - - Future _switchToggled(bool newValue) async { - if (_isUpdatingLelantusScanning) return; - _isUpdatingLelantusScanning = true; // Lock mutex. - - try { - // Toggle enableLelantusScanning in wallet info. - await ref - .read(pWalletInfo(widget.walletId)) - .updateOtherData( - newEntries: {WalletInfoKeys.enableLelantusScanning: newValue}, - isar: ref.read(mainDBProvider).isar, - ); - if (newValue) { - await _doRescanMaybe(); - } - } finally { - // ensure _isUpdatingLelantusScanning is set to false no matter what - _isUpdatingLelantusScanning = false; - } - } - - Future _doRescanMaybe() async { - final shouldRescan = await showDialog( - context: context, - builder: (context) { - return StackDialog( - title: "Rescan may be required", - message: - "A blockchain rescan may be required to fully recover all " - "lelantus history. This may take a while.", - leftButton: SecondaryButton( - label: "Rescan now", - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - rightButton: PrimaryButton( - label: "Later", - onPressed: () => Navigator.of(context).pop(false), - ), - ); - }, - ); - - if (mounted && shouldRescan == true) { - try { - if (!Platform.isLinux) await WakelockPlus.enable(); - - Exception? e; - if (mounted) { - await showLoading( - whileFuture: ref - .read(pWallets) - .getWallet(widget.walletId) - .recover(isRescan: true), - context: context, - message: "Rescanning blockchain", - subMessage: - "This may take a while." - "\nPlease do not exit this screen.", - rootNavigator: Util.isDesktop, - onException: (ex) => e = ex, - ); - - if (e != null) { - throw e!; - } - } - } catch (e, s) { - Logging.instance.e("$e\n$s", error: e, stackTrace: s); - if (mounted) { - // show error - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: - (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of( - context, - rootNavigator: Util.isDesktop, - ).pop(); - }, - ), - ), - ); - } - } finally { - if (!Platform.isLinux) await WakelockPlus.disable(); - } - } - } - - @override - Widget build(BuildContext context) { - return Background( - child: Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Lelantus settings", - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo( - widget.walletId, - ).select((value) => value.otherData), - )[WalletInfoKeys.enableLelantusScanning] - as bool? ?? - false, - onValueChanged: _switchToggled, - ), - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.smallMed12(context), - ), - // Text( - // detail, - // style: STextStyles.desktopTextExtraExtraSmall(context), - // ), - ], - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index 8cae6d217..a1f9f19dc 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -22,7 +22,6 @@ import '../../../../wallets/isar/models/wallet_info.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; -import '../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; @@ -35,7 +34,6 @@ import '../../../../widgets/stack_dialog.dart'; import '../../../pinpad_views/lock_screen_view.dart'; import 'delete_wallet_warning_view.dart'; import 'edit_refresh_height_view.dart'; -import 'lelantus_settings_view.dart'; import 'rbf_settings_view.dart'; import 'rename_wallet_view.dart'; import 'spark_info.dart'; @@ -356,40 +354,6 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is LelantusInterface && !wallet.isViewOnly) - const SizedBox(height: 8), - if (wallet is LelantusInterface && !wallet.isViewOnly) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - LelantusSettingsView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, - ), - child: Row( - children: [ - Text( - "Lelantus settings", - style: STextStyles.titleBold12(context), - ), - ], - ), - ), - ), - ), if (wallet is SparkInterface && !wallet.isViewOnly) const SizedBox(height: 8), if (wallet is SparkInterface && !wallet.isViewOnly) @@ -424,7 +388,8 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) const SizedBox(height: 8), + if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) + const SizedBox(height: 8), if (wallet is LibMoneroWallet || wallet is LibSalviumWallet) RoundedWhiteContainer( padding: const EdgeInsets.all(0), diff --git a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart index c2fc747ad..bbe90033e 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../../models/balance.dart'; import '../../../providers/wallet/public_private_balance_state_provider.dart'; import '../../../providers/wallet/wallet_balance_toggle_state_provider.dart'; @@ -22,20 +23,10 @@ import '../../../utilities/text_styles.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; -enum _BalanceType { - available, - full, - lelantusAvailable, - lelantusFull, - sparkAvailable, - sparkFull; -} +enum _BalanceType { available, full, sparkAvailable, sparkFull } class WalletBalanceToggleSheet extends ConsumerWidget { - const WalletBalanceToggleSheet({ - super.key, - required this.walletId, - }); + const WalletBalanceToggleSheet({super.key, required this.walletId}); final String walletId; @@ -54,42 +45,23 @@ class WalletBalanceToggleSheet extends ConsumerWidget { ? _BalanceType.available : _BalanceType.full; - Balance? balanceSecondary; Balance? balanceTertiary; if (isFiro) { - balanceSecondary = ref.watch(pWalletBalanceSecondary(walletId)); balanceTertiary = ref.watch(pWalletBalanceTertiary(walletId)); - switch (ref.watch(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: - _bal = _bal == _BalanceType.available - ? _BalanceType.sparkAvailable - : _BalanceType.sparkFull; - break; - - case FiroType.lelantus: - _bal = _bal == _BalanceType.available - ? _BalanceType.lelantusAvailable - : _BalanceType.lelantusFull; - break; - - case FiroType.public: - // already set above - break; - } - - // hack to not show lelantus balance in ui if zero - if (balanceSecondary?.spendable.raw == BigInt.zero) { - balanceSecondary = null; + if (ref.watch(publicPrivateBalanceStateProvider.state).state == + FiroType.spark) { + _bal = + _bal == _BalanceType.available + ? _BalanceType.sparkAvailable + : _BalanceType.sparkFull; } } return Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: LimitedBox( maxHeight: maxHeight, @@ -107,9 +79,10 @@ class WalletBalanceToggleSheet extends ConsumerWidget { Center( child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -118,9 +91,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { height: 4, ), ), - const SizedBox( - height: 36, - ), + const SizedBox(height: 36), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( @@ -129,9 +100,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { textAlign: TextAlign.left, ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), BalanceSelector( title: "Available${isFiro ? " public" : ""} balance", coin: coin, @@ -153,9 +122,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { value: _BalanceType.available, groupValue: _bal, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), BalanceSelector( title: "Full${isFiro ? " public" : ""} balance", coin: coin, @@ -177,62 +144,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { value: _BalanceType.full, groupValue: _bal, ), - if (balanceSecondary != null) - const SizedBox( - height: 12, - ), - if (balanceSecondary != null) - BalanceSelector( - title: "Available Lelantus balance", - coin: coin, - balance: balanceSecondary.spendable, - onPressed: () { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.available; - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.lelantus; - Navigator.of(context).pop(); - }, - onChanged: (_) { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.available; - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.lelantus; - Navigator.of(context).pop(); - }, - value: _BalanceType.lelantusAvailable, - groupValue: _bal, - ), - if (balanceSecondary != null) - const SizedBox( - height: 12, - ), - if (balanceSecondary != null) - BalanceSelector( - title: "Full Lelantus balance", - coin: coin, - balance: balanceSecondary.total, - onPressed: () { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.full; - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.lelantus; - Navigator.of(context).pop(); - }, - onChanged: (_) { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.full; - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.lelantus; - Navigator.of(context).pop(); - }, - value: _BalanceType.lelantusFull, - groupValue: _bal, - ), - if (balanceTertiary != null) - const SizedBox( - height: 12, - ), + if (balanceTertiary != null) const SizedBox(height: 12), if (balanceTertiary != null) BalanceSelector( title: "Available Spark balance", @@ -255,10 +167,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { value: _BalanceType.sparkAvailable, groupValue: _bal, ), - if (balanceTertiary != null) - const SizedBox( - height: 12, - ), + if (balanceTertiary != null) const SizedBox(height: 12), if (balanceTertiary != null) BalanceSelector( title: "Full Spark balance", @@ -281,9 +190,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget { value: _BalanceType.sparkFull, groupValue: _bal, ), - const SizedBox( - height: 40, - ), + const SizedBox(height: 40), ], ), ), @@ -331,33 +238,28 @@ class BalanceSelector extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, value: value, groupValue: groupValue, onChanged: onChanged, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), + Text(title, style: STextStyles.titleBold12(context)), + const SizedBox(height: 2), Text( ref.watch(pAmountFormatter(coin)).format(balance), style: STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ], diff --git a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart index 1929a1ca4..7661bffdd 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart @@ -109,11 +109,6 @@ class WalletSummaryInfo extends ConsumerWidget { balanceToShow = _showAvailable ? balance.spendable : balance.total; break; - case FiroType.lelantus: - final balance = ref.watch(pWalletBalanceSecondary(walletId)); - balanceToShow = _showAvailable ? balance.spendable : balance.total; - break; - case FiroType.public: final balance = ref.watch(pWalletBalance(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 61bf31037..2c8c6a301 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -22,7 +22,6 @@ import '../../app_config.dart'; import '../../frost_route_generator.dart'; import '../../models/isar/exchange_cache/currency.dart'; import '../../notifications/show_flush_bar.dart'; -import '../../pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart'; import '../../pages_desktop_specific/spark_coins/spark_coins_view.dart'; import '../../providers/global/active_wallet_provider.dart'; import '../../providers/global/auto_swb_service_provider.dart'; @@ -100,7 +99,6 @@ import '../send_view/send_view.dart'; import '../settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import '../settings_views/wallet_settings_view/wallet_settings_view.dart'; import '../spark_names/spark_names_home_view.dart'; -import '../special/firo_rescan_recovery_error_dialog.dart'; import '../token_view/my_tokens_view.dart'; import 'sub_widgets/transactions_list.dart'; import 'sub_widgets/wallet_summary.dart'; @@ -145,36 +143,6 @@ class _WalletViewState extends ConsumerState { late StreamSubscription _nodeStatusSubscription; bool _rescanningOnOpen = false; - bool _lelantusRescanRecovery = false; - - Future _firoRescanRecovery() async { - final success = - await (ref.read(pWallets).getWallet(walletId) as FiroWallet) - .firoRescanRecovery(); - - if (success) { - // go into wallet - WidgetsBinding.instance.addPostFrameCallback( - (_) => setState(() { - _rescanningOnOpen = false; - _lelantusRescanRecovery = false; - }), - ); - } else { - // show error message dialog w/ options - if (mounted) { - final shouldRetry = await Navigator.of( - context, - ).pushNamed(FiroRescanRecoveryErrorView.routeName, arguments: walletId); - - if (shouldRetry is bool && shouldRetry) { - await _firoRescanRecovery(); - } - } else { - return await _firoRescanRecovery(); - } - } - } @override void initState() { @@ -196,13 +164,7 @@ class _WalletViewState extends ConsumerState { isSparkWallet = wallet is SparkInterface; - if (coin is Firo && (wallet as FiroWallet).lelantusCoinIsarRescanRequired) { - _rescanningOnOpen = true; - _lelantusRescanRecovery = true; - _firoRescanRecovery(); - } else { - wallet.refresh(); - } + wallet.refresh(); if (wallet.refreshMutex.isLocked) { _currentSyncStatus = WalletSyncStatus.syncing; @@ -267,7 +229,7 @@ class _WalletViewState extends ConsumerState { // DateTime? _cachedTime; Future _onWillPop() async { - if (_rescanningOnOpen || _lelantusRescanRecovery) { + if (_rescanningOnOpen) { return false; } @@ -491,7 +453,6 @@ class _WalletViewState extends ConsumerState { } try { - // await firoWallet.anonymizeAllLelantus(); await firoWallet.anonymizeAllSpark(); shouldPop = true; if (mounted) { @@ -553,46 +514,41 @@ class _WalletViewState extends ConsumerState { eventBus: null, textColor: Theme.of(context).extension()!.textDark, - actionButton: - _lelantusRescanRecovery - ? null - : SecondaryButton( - label: "Cancel", - onPressed: () async { - await showDialog( - context: context, - builder: - (context) => StackDialog( - title: "Warning!", - message: - "Skipping this process can completely" - " break your wallet. It is only meant to be done in" - " emergency situations where the migration fails" - " and will not let you continue. Still skip?", - leftButton: SecondaryButton( - label: "Cancel", - onPressed: - Navigator.of( - context, - rootNavigator: true, - ).pop, - ), - rightButton: SecondaryButton( - label: "Ok", - onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(); - setState( - () => _rescanningOnOpen = false, - ); - }, - ), - ), - ); - }, - ), + actionButton: SecondaryButton( + label: "Cancel", + onPressed: () async { + await showDialog( + context: context, + builder: + (context) => StackDialog( + title: "Warning!", + message: + "Skipping this process can completely" + " break your wallet. It is only meant to be done in" + " emergency situations where the migration fails" + " and will not let you continue. Still skip?", + leftButton: SecondaryButton( + label: "Cancel", + onPressed: + Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + rightButton: SecondaryButton( + label: "Ok", + onPressed: () { + Navigator.of( + context, + rootNavigator: true, + ).pop(); + setState(() => _rescanningOnOpen = false); + }, + ), + ), + ); + }, + ), ), ), ], @@ -1161,22 +1117,6 @@ class _WalletViewState extends ConsumerState { ); }, ), - if (wallet is FiroWallet && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.advancedFiroFeatures, - ), - )) - WalletNavigationBarItemData( - label: "Lelantus coins", - icon: const CoinControlNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - LelantusCoinsView.routeName, - arguments: widget.walletId, - ); - }, - ), if (wallet is FiroWallet && ref.watch( prefsChangeNotifierProvider.select( @@ -1296,7 +1236,9 @@ class _WalletViewState extends ConsumerState { ); }, ), - if ((wallet is LibMoneroWallet || wallet is LibSalviumWallet) && !viewOnly) + if ((wallet is LibMoneroWallet || + wallet is LibSalviumWallet) && + !viewOnly) WalletNavigationBarItemData( label: "Churn", icon: const ChurnNavIcon(), diff --git a/lib/pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart b/lib/pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart deleted file mode 100644 index c08891aef..000000000 --- a/lib/pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; - -import '../../models/isar/models/isar_models.dart'; -import '../../providers/db/main_db_provider.dart'; -import '../../themes/stack_colors.dart'; -import '../../utilities/assets.dart'; -import '../../utilities/text_styles.dart'; -import '../../utilities/util.dart'; -import '../../widgets/background.dart'; -import '../../widgets/conditional_parent.dart'; -import '../../widgets/custom_buttons/app_bar_icon_button.dart'; -import '../../widgets/desktop/desktop_app_bar.dart'; -import '../../widgets/desktop/desktop_scaffold.dart'; -import '../../widgets/isar_collection_watcher_list.dart'; - -class LelantusCoinsView extends ConsumerWidget { - const LelantusCoinsView({ - super.key, - required this.walletId, - }); - - static const title = "Lelantus coins"; - static const String routeName = "/lelantusCoinsView"; - - final String walletId; - - @override - Widget build(BuildContext context, WidgetRef ref) { - return ConditionalParent( - condition: Util.isDesktop, - builder: (child) { - return DesktopScaffold( - appBar: DesktopAppBar( - background: Theme.of(context).extension()!.popupBG, - leading: Expanded( - child: Row( - children: [ - const SizedBox( - width: 32, - ), - AppBarIconButton( - size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.arrowLeft, - width: 18, - height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: Navigator.of(context).pop, - ), - const SizedBox( - width: 12, - ), - Text( - title, - style: STextStyles.desktopH3(context), - ), - const Spacer(), - ], - ), - ), - useSpacers: false, - isCompactHeight: true, - ), - body: Padding( - padding: const EdgeInsets.all(24), - child: child, - ), - ); - }, - child: ConditionalParent( - condition: !Util.isDesktop, - builder: (child) { - return Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: AppBarBackButton( - onPressed: () => Navigator.of(context).pop(), - ), - title: Text( - title, - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: child, - ), - ), - ); - }, - child: IsarCollectionWatcherList( - itemName: title, - queryBuilder: () => ref - .read(mainDBProvider) - .isar - .lelantusCoins - .where() - .walletIdEqualTo(walletId) - .sortByMintIndexDesc(), - itemBuilder: (LelantusCoin? coin) { - return [ - ("TXID", coin?.txid ?? "", 9), - ("Value (sats)", coin?.value ?? "", 3), - ("Index", coin?.mintIndex.toString() ?? "", 2), - ("Is JMint", coin?.isJMint.toString() ?? "", 2), - ("Used", coin?.isUsed.toString() ?? "", 2), - ]; - }, - ), - ), - ); - } -} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart index 5f4dcf574..73a6bd742 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart @@ -17,13 +17,9 @@ import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/enums/wallet_balance_toggle_state.dart'; import '../../../../utilities/text_styles.dart'; -import '../../../../wallets/isar/providers/wallet_info_provider.dart'; class DesktopBalanceToggleButton extends ConsumerWidget { - const DesktopBalanceToggleButton({ - super.key, - this.onPressed, - }); + const DesktopBalanceToggleButton({super.key, this.onPressed}); final VoidCallback? onPressed; @@ -86,10 +82,6 @@ class DesktopPrivateBalanceToggleButton extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final currentType = ref.watch(publicPrivateBalanceStateProvider); - final showLelantus = - ref.watch(pWalletBalanceSecondary(walletId)).spendable.raw > - BigInt.zero; - return SizedBox( height: 22, width: 80, @@ -97,32 +89,14 @@ class DesktopPrivateBalanceToggleButton extends ConsumerWidget { color: Theme.of(context).extension()!.buttonBackSecondary, splashColor: Theme.of(context).extension()!.highlight, onPressed: () { - if (showLelantus) { - switch (currentType) { - case FiroType.public: - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.lelantus; - break; - - case FiroType.lelantus: - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; - break; - - case FiroType.spark: - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; - break; - } + if (currentType != FiroType.spark) { + ref.read(publicPrivateBalanceStateProvider.state).state = + FiroType.spark; } else { - if (currentType != FiroType.spark) { - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; - } else { - ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; - } + ref.read(publicPrivateBalanceStateProvider.state).state = + FiroType.public; } + onPressed?.call(); }, elevation: 0, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 609f1d757..206e7ce6d 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -168,9 +168,6 @@ class _DesktopSendState extends ConsumerState { case FiroType.public: availableBalance = wallet.info.cachedBalance.spendable; break; - case FiroType.lelantus: - availableBalance = wallet.info.cachedBalanceSecondary.spendable; - break; case FiroType.spark: availableBalance = wallet.info.cachedBalanceTertiary.spendable; break; @@ -367,16 +364,6 @@ class _DesktopSendState extends ConsumerState { } break; - case FiroType.lelantus: - txDataFuture = wallet.prepareSendLelantus( - txData: TxData( - recipients: [ - (address: _address!, amount: amount, isChange: false), - ], - ), - ); - break; - case FiroType.spark: txDataFuture = wallet.prepareSendSpark( txData: TxData( @@ -849,9 +836,6 @@ class _DesktopSendState extends ConsumerState { case FiroType.public: amount = ref.read(pWalletBalance(walletId)).spendable; break; - case FiroType.lelantus: - amount = ref.read(pWalletBalanceSecondary(walletId)).spendable; - break; case FiroType.spark: amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; break; @@ -1056,30 +1040,6 @@ class _DesktopSendState extends ConsumerState { ], ), ), - if (ref.watch(pWalletBalanceSecondary(walletId)).spendable.raw > - BigInt.zero) - DropdownMenuItem( - value: FiroType.lelantus, - child: Row( - children: [ - Text( - "Lelantus balance", - style: STextStyles.itemSubtitle12(context), - ), - const SizedBox(width: 10), - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - ref - .watch(pWalletBalanceSecondary(walletId)) - .spendable, - ), - style: STextStyles.itemSubtitle(context), - ), - ], - ), - ), DropdownMenuItem( value: FiroType.public, child: Row( @@ -1531,32 +1491,13 @@ class _DesktopSendState extends ConsumerState { if (_address == null || _address!.isEmpty) { error = null; } else if (coin is Firo) { - if (firoType == FiroType.lelantus) { - if (_data != null && _data.contactLabel == _address) { - error = - SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: coin.network.isTestNet, - ) - ? "Lelantus to Spark not supported" - : null; - } else if (ref.watch(pValidSparkSendToAddress)) { - error = "Lelantus to Spark not supported"; - } else { - error = - ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; - } + if (_data != null && _data.contactLabel == _address) { + error = null; + } else if (!ref.watch(pValidSendToAddress) && + !ref.watch(pValidSparkSendToAddress)) { + error = "Invalid address"; } else { - if (_data != null && _data.contactLabel == _address) { - error = null; - } else if (!ref.watch(pValidSendToAddress) && - !ref.watch(pValidSparkSendToAddress)) { - error = "Invalid address"; - } else { - error = null; - } + error = null; } } else { if (_data != null && _data.contactLabel == _address) { @@ -1590,13 +1531,9 @@ class _DesktopSendState extends ConsumerState { } }, ), - if (isStellar || - (ref.watch(pValidSparkSendToAddress) && - firoType != FiroType.lelantus)) + if (isStellar || ref.watch(pValidSparkSendToAddress)) const SizedBox(height: 10), - if (isStellar || - (ref.watch(pValidSparkSendToAddress) && - firoType != FiroType.lelantus)) + if (isStellar || ref.watch(pValidSparkSendToAddress)) ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 154955148..1eb046484 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -8,7 +8,6 @@ import '../../../../providers/wallet/desktop_fee_providers.dart'; import '../../../../providers/wallet/public_private_balance_state_provider.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/amount/amount.dart'; -import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../../utilities/eth_commons.dart'; import '../../../../utilities/text_styles.dart'; @@ -72,9 +71,7 @@ class _DesktopSendFeeFormState extends ConsumerState { (cryptoCurrency is ElectrumXCurrencyInterface && !(((cryptoCurrency is Firo) && (ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.lelantus || - ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.spark)))); + FiroType.spark)))); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -195,17 +192,6 @@ class _DesktopSendFeeFormState extends ConsumerState { .state, ) .state == - FiroType.lelantus) { - ref - .read(feeSheetSessionCacheProvider) - .average[amount] = await firoWallet - .estimateFeeForLelantus(amount); - } else if (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state == FiroType.spark) { ref .read(feeSheetSessionCacheProvider) @@ -260,36 +246,6 @@ class _DesktopSendFeeFormState extends ConsumerState { } }, ) - : (cryptoCurrency is Firo) && - ref - .watch(publicPrivateBalanceStateProvider.state) - .state == - FiroType.lelantus - ? Builder( - builder: (context) { - final lelantusFee = ref - .watch(pAmountFormatter(cryptoCurrency)) - .format( - Amount( - rawValue: BigInt.parse("3794"), - fractionDigits: cryptoCurrency.fractionDigits, - ), - indicatePrecisionLoss: false, - ); - return Text( - "~$lelantusFee", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveText, - ), - textAlign: TextAlign.left, - ); - }, - ) : Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index c5e40a234..2456a909c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -44,7 +44,6 @@ import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet.dart' show Wallet; import '../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; -import '../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; @@ -60,7 +59,6 @@ import '../../../cashfusion/desktop_cashfusion_view.dart'; import '../../../churning/desktop_churning_view.dart'; import '../../../coin_control/desktop_coin_control_view.dart'; import '../../../desktop_menu.dart'; -import '../../../lelantus_coins/lelantus_coins_view.dart'; import '../../../ordinals/desktop_ordinals_view.dart'; import '../../../spark_coins/spark_coins_view.dart'; import '../desktop_wallet_view.dart'; @@ -75,7 +73,6 @@ enum WalletFeature { "Coin control", "Control, freeze, and utilize outputs at your discretion", ), - lelantusCoins("Lelantus coins", "View wallet lelantus coins"), sparkCoins("Spark coins", "View wallet spark coins"), ordinals("Ordinals", "View and control your ordinals in ${AppConfig.prefix}"), monkey("MonKey", "Generate Banano MonKey"), @@ -86,7 +83,6 @@ enum WalletFeature { // special cases clearSparkCache("", ""), - lelantusScanOption("", ""), rbf("", ""), reuseAddress("", ""); @@ -136,12 +132,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { ).pushNamed(DesktopCoinControlView.routeName, arguments: widget.walletId); } - void _onLelantusCoinsPressed() { - Navigator.of( - context, - ).pushNamed(LelantusCoinsView.routeName, arguments: widget.walletId); - } - void _onSparkCoinsPressed() { Navigator.of( context, @@ -236,7 +226,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { } try { - // await firoWallet.anonymizeAllLelantus(); await firoWallet.anonymizeAllSpark(); shouldPop = true; if (mounted) { @@ -417,13 +406,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { _onCoinControlPressed, ), - if (firoAdvanced && wallet is FiroWallet) - ( - WalletFeature.lelantusCoins, - Assets.svg.coinControl.gamePad, - _onLelantusCoinsPressed, - ), - if (firoAdvanced && wallet is FiroWallet) ( WalletFeature.sparkCoins, @@ -443,7 +425,8 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (!isViewOnly && wallet is CashFusionInterface) (WalletFeature.fusion, Assets.svg.cashFusion, _onFusionPressed), - if (!isViewOnly && (wallet is LibMoneroWallet || wallet is LibSalviumWallet)) + if (!isViewOnly && + (wallet is LibMoneroWallet || wallet is LibSalviumWallet)) (WalletFeature.churn, Assets.svg.churn, _onChurnPressed), if (wallet is NamecoinWallet) @@ -482,9 +465,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (wallet is SparkInterface && !isViewOnly) (WalletFeature.clearSparkCache, Assets.svg.key, () => ()), - if (wallet is LelantusInterface && !isViewOnly) - (WalletFeature.lelantusScanOption, Assets.svg.key, () => ()), - if (wallet is RbfInterface) (WalletFeature.rbf, Assets.svg.key, () => ()), if (!isViewOnlyNoAddressGen) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart index dc09c757d..84c52c870 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart @@ -109,11 +109,6 @@ class _WDesktopWalletSummaryState extends ConsumerState { balanceToShow = _showAvailable ? balance.spendable : balance.total; break; - case FiroType.lelantus: - final balance = ref.watch(pWalletBalanceSecondary(walletId)); - balanceToShow = _showAvailable ? balance.spendable : balance.total; - break; - case FiroType.public: final balance = ref.watch(pWalletBalance(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart index ecc80aa28..2de6daf39 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart @@ -85,8 +85,6 @@ class _WFiroDesktopWalletSummaryState _showAvailable ? balance0.spendable : balance0.total; final balance1 = ref.watch(pWalletBalanceSecondary(walletId)); - final balanceToShowLelantus = - _showAvailable ? balance1.spendable : balance1.total; final balance2 = ref.watch(pWalletBalance(walletId)); final balanceToShowPublic = @@ -116,19 +114,7 @@ class _WFiroDesktopWalletSummaryState ), ], ), - if (balanceToShowLelantus.raw > BigInt.zero) - TableRow( - children: [ - const _Prefix(type: FiroType.lelantus), - _Balance(coin: coin, amount: balanceToShowLelantus), - if (price != null) - _Price( - coin: coin, - amount: balanceToShowLelantus, - price: price, - ), - ], - ), + TableRow( children: [ const _Prefix(type: FiroType.public), @@ -167,8 +153,6 @@ class _Prefix extends StatelessWidget { switch (type) { case FiroType.public: return Assets.png.glasses; - case FiroType.lelantus: - return Assets.png.glasses; case FiroType.spark: return Assets.svg.spark; } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 5a013787a..ab48068b4 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -14,7 +14,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; import '../../../../../db/sqlite/firo_cache.dart'; import '../../../../../providers/db/main_db_provider.dart'; @@ -22,10 +21,7 @@ import '../../../../../providers/global/wallets_provider.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../themes/theme_providers.dart'; import '../../../../../utilities/assets.dart'; -import '../../../../../utilities/logger.dart'; -import '../../../../../utilities/show_loading.dart'; import '../../../../../utilities/text_styles.dart'; -import '../../../../../utilities/util.dart'; import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; @@ -35,7 +31,6 @@ import '../../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../../widgets/desktop/primary_button.dart'; import '../../../../../widgets/desktop/secondary_button.dart'; import '../../../../../widgets/rounded_container.dart'; -import '../../../../../widgets/stack_dialog.dart'; import '../desktop_wallet_features.dart'; class MoreFeaturesDialog extends ConsumerStatefulWidget { @@ -53,30 +48,6 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { } class _MoreFeaturesDialogState extends ConsumerState { - bool _isUpdatingLelantusScanning = false; // Mutex. - - Future _switchToggled(bool newValue) async { - if (_isUpdatingLelantusScanning) return; - _isUpdatingLelantusScanning = true; // Lock mutex. - - try { - // Toggle enableLelantusScanning in wallet info. - await ref - .read(pWalletInfo(widget.walletId)) - .updateOtherData( - newEntries: {WalletInfoKeys.enableLelantusScanning: newValue}, - isar: ref.read(mainDBProvider).isar, - ); - - if (newValue) { - await _doRescanMaybe(); - } - } finally { - // ensure _isUpdatingLelantusScanning is set to false no matter what - _isUpdatingLelantusScanning = false; - } - } - bool _switchRbfToggledLock = false; // Mutex. Future _switchRbfToggled(bool newValue) async { if (_switchRbfToggledLock) { @@ -98,119 +69,6 @@ class _MoreFeaturesDialogState extends ConsumerState { } } - Future _doRescanMaybe() async { - final shouldRescan = await showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 700, - child: Column( - children: [ - const DesktopDialogCloseButton(), - const SizedBox(height: 5), - Text( - "Rescan may be required", - style: STextStyles.desktopH2(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 16), - const Spacer(), - Text( - "A blockchain rescan may be required to fully recover all lelantus history." - "\nThis may take a while.", - style: STextStyles.desktopTextMedium(context).copyWith( - color: Theme.of(context).extension()!.textDark3, - ), - textAlign: TextAlign.center, - ), - const Spacer(), - Padding( - padding: const EdgeInsets.only(left: 32, right: 32, bottom: 32), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Rescan now", - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), - const SizedBox(width: 16), - Expanded( - child: PrimaryButton( - label: "Later", - onPressed: () => Navigator.of(context).pop(false), - ), - ), - ], - ), - ), - ], - ), - ); - }, - ); - - if (mounted && shouldRescan == true) { - try { - if (!Platform.isLinux) await WakelockPlus.enable(); - - Exception? e; - if (mounted) { - await showLoading( - whileFuture: ref - .read(pWallets) - .getWallet(widget.walletId) - .recover(isRescan: true), - context: context, - message: "Rescanning blockchain", - subMessage: - "This may take a while.\nPlease do not exit this screen.", - rootNavigator: Util.isDesktop, - onException: (ex) => e = ex, - ); - - if (e != null) { - throw e!; - } - } - } catch (e, s) { - Logging.instance.e("$e\n$s", error: e, stackTrace: s); - if (mounted) { - // show error - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: - (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of( - context, - rootNavigator: Util.isDesktop, - ).pop(); - }, - ), - ), - ); - } - } finally { - if (!Platform.isLinux) await WakelockPlus.disable(); - } - } - } - late final DSBController _switchController; bool _switchReuseAddressToggledLock = false; // Mutex. @@ -370,40 +228,6 @@ class _MoreFeaturesDialogState extends ConsumerState { cryptoCurrency: wallet.cryptoCurrency, ); - case WalletFeature.lelantusScanOption: - return _MoreFeaturesItemBase( - child: Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo( - widget.walletId, - ).select((value) => value.otherData), - )[WalletInfoKeys.enableLelantusScanning] - as bool? ?? - false, - onValueChanged: _switchToggled, - ), - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.w600_20(context), - ), - ], - ), - ], - ), - ); - case WalletFeature.rbf: return _MoreFeaturesItemBase( child: Row( diff --git a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart index 98a7dec34..179ce7650 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart @@ -38,14 +38,8 @@ class DesktopAboutView extends ConsumerWidget { isCompactHeight: true, leading: Row( children: [ - const SizedBox( - width: 24, - height: 24, - ), - Text( - "About", - style: STextStyles.desktopH3(context), - ), + const SizedBox(width: 24, height: 24), + Text("About", style: STextStyles.desktopH3(context)), ], ), ), @@ -85,55 +79,63 @@ class DesktopAboutView extends ConsumerWidget { TextSpan( text: "By using ${AppConfig.appName}, you agree to the ", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark3, + ), ), TextSpan( text: "Terms of service", - style: STextStyles.richLink(context) - .copyWith(fontSize: 14), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/terms-of-service.html", - ), - mode: - LaunchMode.externalApplication, - ); - }, + style: STextStyles.richLink( + context, + ).copyWith(fontSize: 14), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/terms-of-service.html", + ), + mode: + LaunchMode + .externalApplication, + ); + }, ), TextSpan( text: " and ", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark3, + ), ), TextSpan( text: "Privacy policy", - style: STextStyles.richLink(context) - .copyWith(fontSize: 14), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/privacy-policy.html", - ), - mode: - LaunchMode.externalApplication, - ); - }, + style: STextStyles.richLink( + context, + ).copyWith(fontSize: 14), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/privacy-policy.html", + ), + mode: + LaunchMode + .externalApplication, + ); + }, ), ], ), @@ -142,8 +144,10 @@ class DesktopAboutView extends ConsumerWidget { ), const SizedBox(height: 32), Padding( - padding: - const EdgeInsets.only(right: 10, bottom: 10), + padding: const EdgeInsets.only( + right: 10, + bottom: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -182,33 +186,29 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Version", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, - ), - ), - const SizedBox( - height: 2, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), + const SizedBox(height: 2), SelectableText( version, style: STextStyles.itemSubtitle( - context, - ), + context, + ), ), ], ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: @@ -216,33 +216,29 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Build number", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, - ), - ), - const SizedBox( - height: 2, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), + const SizedBox(height: 2), SelectableText( build, style: STextStyles.itemSubtitle( - context, - ), + context, + ), ), ], ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: @@ -250,27 +246,25 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Build commit", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, - ), - ), - const SizedBox( - height: 2, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), + const SizedBox(height: 2), SelectableText( GitStatus.appCommitHash, style: STextStyles.itemSubtitle( - context, - ), + context, + ), ), ], ), @@ -286,27 +280,25 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Build signature", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, - ), - ), - const SizedBox( - height: 2, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), + const SizedBox(height: 2), SelectableText( signature, style: STextStyles.itemSubtitle( - context, - ), + context, + ), ), ], ), @@ -317,74 +309,16 @@ class DesktopAboutView extends ConsumerWidget { spacing: 64, runSpacing: 32, children: [ - if (AppConfig.coins - .whereType() - .isNotEmpty) - FutureBuilder( - future: GitStatus - .getFiroCommitStatus(), - builder: ( - context, - AsyncSnapshot - snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - stateOfCommit = - snapshot.data!; - } - - return Column( - mainAxisSize: - MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - Text( - "Firo Build Commit", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, - ), - ), - const SizedBox( - height: 2, - ), - SelectableText( - GitStatus.firoCommit, - style: GitStatus - .styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ); - }, - ), if (AppConfig.coins .whereType() .isNotEmpty) FutureBuilder( - future: GitStatus - .getEpicCommitStatus(), + future: + GitStatus.getEpicCommitStatus(), builder: ( context, AsyncSnapshot - snapshot, + snapshot, ) { CommitStatus stateOfCommit = CommitStatus.notLoaded; @@ -406,29 +340,26 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Epic Cash Build Commit", - style: STextStyles - .desktopTextExtraExtraSmall( + style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textDark, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), SelectableText( GitStatus .epicCashCommit, - style: GitStatus - .styleForStatus( - stateOfCommit, - context, - ), + style: + GitStatus.styleForStatus( + stateOfCommit, + context, + ), ), ], ); @@ -498,14 +429,17 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Website:", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), CustomTextButton( text: "https://stackwallet.com", @@ -514,8 +448,9 @@ class DesktopAboutView extends ConsumerWidget { Uri.parse( "https://stackwallet.com", ), - mode: LaunchMode - .externalApplication, + mode: + LaunchMode + .externalApplication, ); }, ), @@ -532,14 +467,17 @@ class DesktopAboutView extends ConsumerWidget { children: [ Text( "Tezos functionality:", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ), ), CustomTextButton( text: "Powered by TzKT API", @@ -548,8 +486,9 @@ class DesktopAboutView extends ConsumerWidget { Uri.parse( "https://tzkt.io", ), - mode: LaunchMode - .externalApplication, + mode: + LaunchMode + .externalApplication, ); }, ), diff --git a/lib/providers/ui/preview_tx_button_state_provider.dart b/lib/providers/ui/preview_tx_button_state_provider.dart index 196fe298d..35daf888f 100644 --- a/lib/providers/ui/preview_tx_button_state_provider.dart +++ b/lib/providers/ui/preview_tx_button_state_provider.dart @@ -20,31 +20,26 @@ final pValidSparkSendToAddress = StateProvider.autoDispose((_) => false); final pIsExchangeAddress = StateProvider((_) => false); -final pPreviewTxButtonEnabled = - Provider.autoDispose.family((ref, coin) { - final amount = ref.watch(pSendAmount) ?? Amount.zero; - - if (coin is Firo) { - final firoType = ref.watch(publicPrivateBalanceStateProvider); - switch (firoType) { - case FiroType.lelantus: - return ref.watch(pValidSendToAddress) && - !ref.watch(pValidSparkSendToAddress) && - amount > Amount.zero; - - case FiroType.spark: - return (ref.watch(pValidSendToAddress) || - ref.watch(pValidSparkSendToAddress)) && - !ref.watch(pIsExchangeAddress) && - amount > Amount.zero; - - case FiroType.public: +final pPreviewTxButtonEnabled = Provider.autoDispose + .family((ref, coin) { + final amount = ref.watch(pSendAmount) ?? Amount.zero; + + if (coin is Firo) { + final firoType = ref.watch(publicPrivateBalanceStateProvider); + switch (firoType) { + case FiroType.spark: + return (ref.watch(pValidSendToAddress) || + ref.watch(pValidSparkSendToAddress)) && + !ref.watch(pIsExchangeAddress) && + amount > Amount.zero; + + case FiroType.public: + return ref.watch(pValidSendToAddress) && amount > Amount.zero; + } + } else { return ref.watch(pValidSendToAddress) && amount > Amount.zero; - } - } else { - return ref.watch(pValidSendToAddress) && amount > Amount.zero; - } -}); + } + }); final previewTokenTxButtonStateProvider = StateProvider.autoDispose((_) { return false; diff --git a/lib/providers/wallet/public_private_balance_state_provider.dart b/lib/providers/wallet/public_private_balance_state_provider.dart index 8fa012edb..7484db9f0 100644 --- a/lib/providers/wallet/public_private_balance_state_provider.dart +++ b/lib/providers/wallet/public_private_balance_state_provider.dart @@ -10,11 +10,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -enum FiroType { - public, - lelantus, - spark; -} +enum FiroType { public, spark } -final publicPrivateBalanceStateProvider = - StateProvider((_) => FiroType.spark); +final publicPrivateBalanceStateProvider = StateProvider( + (_) => FiroType.spark, +); diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 629a3a1a7..55f6964b3 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -143,7 +143,6 @@ import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_setting import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart'; -import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart'; @@ -179,7 +178,6 @@ import 'pages_desktop_specific/desktop_buy/desktop_buy_view.dart'; import 'pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart'; import 'pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart'; import 'pages_desktop_specific/desktop_home_view.dart'; -import 'pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart'; import 'pages_desktop_specific/my_stack_view/my_stack_view.dart'; import 'pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart'; import 'pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart'; @@ -1512,7 +1510,7 @@ class RouteGenerator { return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreWalletView.routeName: - if (args is Tuple6) { + if (args is Tuple5) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: @@ -1522,7 +1520,6 @@ class RouteGenerator { seedWordsLength: args.item3, restoreBlockHeight: args.item4, mnemonicPassphrase: args.item5, - enableLelantusScanning: args.item6 ?? false, ), settings: RouteSettings(name: settings.name), ); @@ -1535,7 +1532,6 @@ class RouteGenerator { String walletName, CryptoCurrency coin, int restoreBlockHeight, - bool enableLelantusScanning, })) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, @@ -1544,7 +1540,6 @@ class RouteGenerator { walletName: args.walletName, coin: args.coin, restoreBlockHeight: args.restoreBlockHeight, - enableLelantusScanning: args.enableLelantusScanning, ), settings: RouteSettings(name: settings.name), ); @@ -2045,16 +2040,6 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); - case LelantusSettingsView.routeName: - if (args is String) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => LelantusSettingsView(walletId: args), - settings: RouteSettings(name: settings.name), - ); - } - return _routeError("${settings.name} invalid args: ${args.toString()}"); - case RbfSettingsView.routeName: if (args is String) { return getRoute( @@ -2232,16 +2217,6 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); - case LelantusCoinsView.routeName: - if (args is String) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => LelantusCoinsView(walletId: args), - settings: RouteSettings(name: settings.name), - ); - } - return _routeError("${settings.name} invalid args: ${args.toString()}"); - case SparkCoinsView.routeName: if (args is String) { return getRoute( diff --git a/lib/utilities/git_status.dart b/lib/utilities/git_status.dart index 0a3f081a6..c89cf2439 100644 --- a/lib/utilities/git_status.dart +++ b/lib/utilities/git_status.dart @@ -2,9 +2,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_libepiccash/git_versions.dart' as epic_versions; -// import 'package:flutter_libmonero/git_versions.dart' as monero_versions; import 'package:http/http.dart'; -import 'package:lelantus/git_versions.dart' as firo_versions; import '../../../themes/stack_colors.dart'; import '../../../utilities/logger.dart'; @@ -18,37 +16,11 @@ const kGithubHead = "/repos"; enum CommitStatus { isHead, isOldCommit, notACommit, notLoaded } abstract class GitStatus { - static String get firoCommit => firo_versions.getPluginVersion(); static String get epicCashCommit => epic_versions.getPluginVersion(); // static String get moneroCommit => monero_versions.getPluginVersion(); static String get appCommitHash => AppConfig.commitHash; - static CommitStatus? _cachedFiroStatus; - static Future getFiroCommitStatus() async { - if (_cachedFiroStatus != null) { - return _cachedFiroStatus!; - } - - final List results = await Future.wait([ - _doesCommitExist("cypherstack", "flutter_liblelantus", firoCommit), - _isHeadCommit("cypherstack", "flutter_liblelantus", "main", firoCommit), - ]); - - final commitExists = results[0]; - final commitIsHead = results[1]; - - if (commitExists && commitIsHead) { - _cachedFiroStatus = CommitStatus.isHead; - } else if (commitExists) { - _cachedFiroStatus = CommitStatus.isOldCommit; - } else { - _cachedFiroStatus = CommitStatus.notACommit; - } - - return _cachedFiroStatus!; - } - static CommitStatus? _cachedEpicStatus; static Future getEpicCommitStatus() async { if (_cachedEpicStatus != null) { @@ -78,59 +50,24 @@ abstract class GitStatus { return _cachedEpicStatus!; } - // - // static CommitStatus? _cachedMoneroStatus; - // static Future getMoneroCommitStatus() async { - // if (_cachedMoneroStatus != null) { - // return _cachedMoneroStatus!; - // } - // - // final List results = await Future.wait([ - // _doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit), - // _isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit), - // ]); - // - // final commitExists = results[0]; - // final commitIsHead = results[1]; - // - // if (commitExists && commitIsHead) { - // _cachedMoneroStatus = CommitStatus.isHead; - // } else if (commitExists) { - // _cachedMoneroStatus = CommitStatus.isOldCommit; - // } else { - // _cachedMoneroStatus = CommitStatus.notACommit; - // } - // - // return _cachedMoneroStatus!; - // } static TextStyle styleForStatus(CommitStatus status, BuildContext context) { final Color color; switch (status) { case CommitStatus.isHead: - color = Theme.of( - context, - ).extension()!.accentColorGreen; + color = Theme.of(context).extension()!.accentColorGreen; break; case CommitStatus.isOldCommit: - color = Theme.of( - context, - ).extension()!.accentColorYellow; + color = Theme.of(context).extension()!.accentColorYellow; break; case CommitStatus.notACommit: - color = Theme.of( - context, - ).extension()!.accentColorRed; + color = Theme.of(context).extension()!.accentColorRed; break; default: - return STextStyles.itemSubtitle( - context, - ); + return STextStyles.itemSubtitle(context); } - return STextStyles.itemSubtitle( - context, - ).copyWith(color: color); + return STextStyles.itemSubtitle(context).copyWith(color: color); } static Future _doesCommitExist( diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index a436c8483..087aaa631 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -1270,7 +1270,7 @@ class Prefs extends ChangeNotifier { true; } - // Show/hide lelantus and spark coins. Defaults to false + // Show/hide spark coins. Defaults to false bool _advancedFiroFeatures = false; bool get advancedFiroFeatures => _advancedFiroFeatures; set advancedFiroFeatures(bool advancedFiroFeatures) { diff --git a/lib/utilities/wallet_tools.dart b/lib/utilities/wallet_tools.dart index 8d869ea63..b38578370 100644 --- a/lib/utilities/wallet_tools.dart +++ b/lib/utilities/wallet_tools.dart @@ -2,7 +2,6 @@ import 'package:isar/isar.dart'; import '../db/isar/main_db.dart'; import '../models/isar/models/blockchain_data/v2/transaction_v2.dart'; -import '../models/isar/models/firo_specific/lelantus_coin.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; import '../wallets/isar/models/spark_coin.dart'; import '../wallets/wallet/impl/firo_wallet.dart'; @@ -20,10 +19,11 @@ abstract class WalletDevTools { maxDecimals: 8, ); - final all = MainDB.instance.isar.transactionV2s - .where() - .walletIdEqualTo(wallet.walletId) - .findAllSync(); + final all = + MainDB.instance.isar.transactionV2s + .where() + .walletIdEqualTo(wallet.walletId) + .findAllSync(); final totalCount = all.length; @@ -47,14 +47,11 @@ abstract class WalletDevTools { fractionDigits: 8, ); - final lelantusCoinsCount = MainDB.instance.isar.lelantusCoins - .where() - .walletIdEqualTo(wallet.walletId) - .countSync(); - final sparkCoinsCount = MainDB.instance.isar.sparkCoins - .where() - .walletIdEqualToAnyLTagHash(wallet.walletId) - .countSync(); + final sparkCoinsCount = + MainDB.instance.isar.sparkCoins + .where() + .walletIdEqualToAnyLTagHash(wallet.walletId) + .countSync(); final buffer = StringBuffer(); buffer.writeln("============= ${wallet.info.name} ============="); @@ -63,7 +60,6 @@ abstract class WalletDevTools { buffer.writeln( "balanceAccordingToTxns: ${amtFmt.format(balanceAccordingToTxHistory)}", ); - buffer.writeln("lelantusCoinsCount: $lelantusCoinsCount"); buffer.writeln("sparkCoinsCount: $sparkCoinsCount"); buffer.writeln("=================================================="); diff --git a/lib/wallets/api/lelantus_ffi_wrapper.dart b/lib/wallets/api/lelantus_ffi_wrapper.dart deleted file mode 100644 index 3ee60d994..000000000 --- a/lib/wallets/api/lelantus_ffi_wrapper.dart +++ /dev/null @@ -1,551 +0,0 @@ -import 'package:bip32/bip32.dart'; -import 'package:bitcoindart/bitcoindart.dart' as bitcoindart; -import 'package:flutter/foundation.dart'; -import 'package:lelantus/lelantus.dart' as lelantus; - -import '../../models/isar/models/isar_models.dart' as isar_models; -import '../../models/isar/models/isar_models.dart'; -import '../../models/lelantus_fee_data.dart'; -import '../../utilities/amount/amount.dart'; -import '../../utilities/extensions/impl/string.dart'; -import '../../utilities/extensions/impl/uint8_list.dart'; -import '../../utilities/format.dart'; -import '../../utilities/logger.dart'; -import '../crypto_currency/intermediate/bip39_hd_currency.dart'; -import '../models/tx_data.dart'; - -abstract final class LelantusFfiWrapper { - static const MINT_LIMIT = 5001 * 100000000; - static const MINT_LIMIT_TESTNET = 1001 * 100000000; - - static const JMINT_INDEX = 5; - static const MINT_INDEX = 2; - static const TRANSACTION_LELANTUS = 8; - static const ANONYMITY_SET_EMPTY_ID = 0; - - // partialDerivationPath should be something like "m/$purpose'/$coinType'/$account'/" - static Future<({List spendTxIds, List lelantusCoins})> - restore({ - required final String hexRootPrivateKey, - required final Uint8List chaincode, - required final Bip39HDCurrency cryptoCurrency, - required final int latestSetId, - required final Map setDataMap, - required final Set usedSerialNumbers, - required final String walletId, - required final String partialDerivationPath, - }) async { - final args = ( - hexRootPrivateKey: hexRootPrivateKey, - chaincode: chaincode, - cryptoCurrency: cryptoCurrency, - latestSetId: latestSetId, - setDataMap: setDataMap, - usedSerialNumbers: usedSerialNumbers, - walletId: walletId, - partialDerivationPath: partialDerivationPath, - ); - try { - return await compute(_restore, args); - } catch (e, s) { - Logging.instance.i("Exception rethrown from _restore(): ", error: e, stackTrace: s); - rethrow; - } - } - - // partialDerivationPath should be something like "m/$purpose'/$coinType'/$account'/" - static Future<({List spendTxIds, List lelantusCoins})> - _restore( - ({ - String hexRootPrivateKey, - Uint8List chaincode, - Bip39HDCurrency cryptoCurrency, - int latestSetId, - Map setDataMap, - Set usedSerialNumbers, - String walletId, - String partialDerivationPath, - }) args, - ) async { - final List jindexes = []; - final List lelantusCoins = []; - - final List spendTxIds = []; - int lastFoundIndex = 0; - int currentIndex = 0; - - final root = BIP32.fromPrivateKey( - args.hexRootPrivateKey.toUint8ListFromHex, - args.chaincode, - ); - - while (currentIndex < lastFoundIndex + 50) { - final mintKeyPair = root.derivePath( - "${args.partialDerivationPath}$MINT_INDEX/$currentIndex", - ); - - final String mintTag = lelantus.CreateTag( - mintKeyPair.privateKey!.toHex, - currentIndex, - mintKeyPair.identifier.toHex, - isTestnet: args.cryptoCurrency.network.isTestNet, - ); - - for (int setId = 1; setId <= args.latestSetId; setId++) { - final setData = args.setDataMap[setId] as Map; - final foundCoin = (setData["coins"] as List).firstWhere( - (e) => e[1] == mintTag, - orElse: () => [], - ); - - if (foundCoin.length == 4) { - lastFoundIndex = currentIndex; - - final String publicCoin = foundCoin[0] as String; - final String txId = foundCoin[3] as String; - - // this value will either be an int or a String - final dynamic thirdValue = foundCoin[2]; - - if (thirdValue is int) { - final int amount = thirdValue; - final String serialNumber = lelantus.GetSerialNumber( - amount, - mintKeyPair.privateKey!.toHex, - currentIndex, - isTestnet: args.cryptoCurrency.network.isTestNet, - ); - final bool isUsed = args.usedSerialNumbers.contains(serialNumber); - - lelantusCoins.removeWhere( - (e) => - e.txid == txId && - e.mintIndex == currentIndex && - e.anonymitySetId != setId, - ); - - lelantusCoins.add( - isar_models.LelantusCoin( - walletId: args.walletId, - mintIndex: currentIndex, - value: amount.toString(), - txid: txId, - anonymitySetId: setId, - isUsed: isUsed, - isJMint: false, - otherData: - publicCoin, // not really needed but saved just in case - ), - ); - debugPrint("serial=$serialNumber amount=$amount used=$isUsed"); - } else if (thirdValue is String) { - final int keyPath = lelantus.GetAesKeyPath(publicCoin); - - final aesKeyPair = root.derivePath( - "${args.partialDerivationPath}$JMINT_INDEX/$keyPath", - ); - - try { - final String aesPrivateKey = aesKeyPair.privateKey!.toHex; - - final int amount = lelantus.decryptMintAmount( - aesPrivateKey, - thirdValue, - ); - - final String serialNumber = lelantus.GetSerialNumber( - amount, - aesPrivateKey, - currentIndex, - isTestnet: args.cryptoCurrency.network.isTestNet, - ); - final bool isUsed = args.usedSerialNumbers.contains(serialNumber); - - lelantusCoins.removeWhere( - (e) => - e.txid == txId && - e.mintIndex == currentIndex && - e.anonymitySetId != setId, - ); - - lelantusCoins.add( - isar_models.LelantusCoin( - walletId: args.walletId, - mintIndex: currentIndex, - value: amount.toString(), - txid: txId, - anonymitySetId: setId, - isUsed: isUsed, - isJMint: true, - otherData: - publicCoin, // not really needed but saved just in case - ), - ); - jindexes.add(currentIndex); - - spendTxIds.add(txId); - } catch (_) { - debugPrint("AES keypair derivation issue for key path: $keyPath"); - } - } else { - debugPrint("Unexpected coin found: $foundCoin"); - } - } - } - - currentIndex++; - } - - return (spendTxIds: spendTxIds, lelantusCoins: lelantusCoins); - } - - static Future estimateJoinSplitFee({ - required Amount spendAmount, - required bool subtractFeeFromAmount, - required List lelantusEntries, - required bool isTestNet, - }) async { - return await compute( - LelantusFfiWrapper._estimateJoinSplitFee, - ( - spendAmount: spendAmount.raw.toInt(), - subtractFeeFromAmount: subtractFeeFromAmount, - lelantusEntries: lelantusEntries, - isTestNet: isTestNet, - ), - ); - } - - static Future _estimateJoinSplitFee( - ({ - int spendAmount, - bool subtractFeeFromAmount, - List lelantusEntries, - bool isTestNet, - }) data, - ) async { - debugPrint("estimateJoinSplit fee"); - // for (int i = 0; i < lelantusEntries.length; i++) { - // Logging.instance.log(lelantusEntries[i], addToDebugMessagesDB: false); - // } - debugPrint( - "${data.spendAmount} ${data.subtractFeeFromAmount}", - ); - - final List changeToMint = List.empty(growable: true); - final List spendCoinIndexes = List.empty(growable: true); - // Logging.instance.log(lelantusEntries, addToDebugMessagesDB: false); - final fee = lelantus.estimateFee( - data.spendAmount, - data.subtractFeeFromAmount, - data.lelantusEntries, - changeToMint, - spendCoinIndexes, - isTestnet: data.isTestNet, - ); - - final estimateFeeData = LelantusFeeData( - changeToMint[0], - fee, - spendCoinIndexes, - ); - debugPrint( - "estimateFeeData ${estimateFeeData.changeToMint}" - " ${estimateFeeData.fee}" - " ${estimateFeeData.spendCoinIndexes}", - ); - return estimateFeeData; - } - - static Future createJoinSplitTransaction({ - required TxData txData, - required bool subtractFeeFromAmount, - required int nextFreeMintIndex, - required int locktime, // set to current chain height - required List lelantusEntries, - required List> anonymitySets, - required Bip39HDCurrency cryptoCurrency, - required String partialDerivationPath, - required String hexRootPrivateKey, - required Uint8List chaincode, - }) async { - final arg = ( - txData: txData, - subtractFeeFromAmount: subtractFeeFromAmount, - index: nextFreeMintIndex, - lelantusEntries: lelantusEntries, - locktime: locktime, - cryptoCurrency: cryptoCurrency, - anonymitySetsArg: anonymitySets, - partialDerivationPath: partialDerivationPath, - hexRootPrivateKey: hexRootPrivateKey, - chaincode: chaincode, - ); - - return await compute(_createJoinSplitTransaction, arg); - } - - static Future _createJoinSplitTransaction( - ({ - TxData txData, - bool subtractFeeFromAmount, - int index, - List lelantusEntries, - int locktime, - Bip39HDCurrency cryptoCurrency, - List> anonymitySetsArg, - String partialDerivationPath, - String hexRootPrivateKey, - Uint8List chaincode, - }) arg, - ) async { - final spendAmount = arg.txData.recipients!.first.amount.raw.toInt(); - final address = arg.txData.recipients!.first.address; - final isChange = arg.txData.recipients!.first.isChange; - - final estimateJoinSplitFee = await _estimateJoinSplitFee( - ( - spendAmount: spendAmount, - subtractFeeFromAmount: arg.subtractFeeFromAmount, - lelantusEntries: arg.lelantusEntries, - isTestNet: arg.cryptoCurrency.network.isTestNet, - ), - ); - final changeToMint = estimateJoinSplitFee.changeToMint; - final fee = estimateJoinSplitFee.fee; - final spendCoinIndexes = estimateJoinSplitFee.spendCoinIndexes; - debugPrint("$changeToMint $fee $spendCoinIndexes"); - if (spendCoinIndexes.isEmpty) { - throw Exception("Error, Not enough funds."); - } - - final params = arg.cryptoCurrency.networkParams; - final _network = bitcoindart.NetworkType( - messagePrefix: params.messagePrefix, - bech32: params.bech32Hrp, - bip32: bitcoindart.Bip32Type( - public: params.pubHDPrefix, - private: params.privHDPrefix, - ), - pubKeyHash: params.p2pkhPrefix, - scriptHash: params.p2shPrefix, - wif: params.wifPrefix, - ); - - final tx = bitcoindart.TransactionBuilder(network: _network); - tx.setLockTime(arg.locktime); - - tx.setVersion(3 | (TRANSACTION_LELANTUS << 16)); - - tx.addInput( - '0000000000000000000000000000000000000000000000000000000000000000', - 4294967295, - 4294967295, - Uint8List(0), - ); - final derivePath = "${arg.partialDerivationPath}$MINT_INDEX/${arg.index}"; - - final root = BIP32.fromPrivateKey( - arg.hexRootPrivateKey.toUint8ListFromHex, - arg.chaincode, - ); - - final jmintKeyPair = root.derivePath(derivePath); - - final String jmintprivatekey = jmintKeyPair.privateKey!.toHex; - - final keyPath = lelantus.getMintKeyPath( - changeToMint, - jmintprivatekey, - arg.index, - isTestnet: arg.cryptoCurrency.network.isTestNet, - ); - - final _derivePath = "${arg.partialDerivationPath}$JMINT_INDEX/$keyPath"; - - final aesKeyPair = root.derivePath(_derivePath); - final aesPrivateKey = aesKeyPair.privateKey!.toHex; - - final jmintData = lelantus.createJMintScript( - changeToMint, - jmintprivatekey, - arg.index, - Format.uint8listToString(jmintKeyPair.identifier), - aesPrivateKey, - isTestnet: arg.cryptoCurrency.network.isTestNet, - ); - - tx.addOutput( - Format.stringToUint8List(jmintData), - 0, - ); - - int amount = spendAmount; - if (arg.subtractFeeFromAmount) { - amount -= fee; - } - tx.addOutput( - address, - amount, - ); - - final extractedTx = tx.buildIncomplete(); - extractedTx.setPayload(Uint8List(0)); - final txHash = extractedTx.getId(); - - final List setIds = []; - final List> anonymitySets = []; - final List anonymitySetHashes = []; - final List groupBlockHashes = []; - for (var i = 0; i < arg.lelantusEntries.length; i++) { - final anonymitySetId = arg.lelantusEntries[i].anonymitySetId; - if (!setIds.contains(anonymitySetId)) { - setIds.add(anonymitySetId); - final anonymitySet = arg.anonymitySetsArg.firstWhere( - (element) => element["setId"] == anonymitySetId, - orElse: () => {}, - ); - if (anonymitySet.isNotEmpty) { - anonymitySetHashes.add(anonymitySet['setHash'] as String); - groupBlockHashes.add(anonymitySet['blockHash'] as String); - final List list = []; - for (int i = 0; i < (anonymitySet['coins'] as List).length; i++) { - list.add(anonymitySet['coins'][i][0] as String); - } - anonymitySets.add(list); - } - } - } - - final String spendScript = lelantus.createJoinSplitScript( - txHash, - spendAmount, - arg.subtractFeeFromAmount, - jmintprivatekey, - arg.index, - arg.lelantusEntries, - setIds, - anonymitySets, - anonymitySetHashes, - groupBlockHashes, - isTestnet: arg.cryptoCurrency.network.isTestNet, - ); - - final finalTx = bitcoindart.TransactionBuilder(network: _network); - finalTx.setLockTime(arg.locktime); - - finalTx.setVersion(3 | (TRANSACTION_LELANTUS << 16)); - - finalTx.addOutput( - Format.stringToUint8List(jmintData), - 0, - ); - - finalTx.addOutput( - address, - amount, - ); - - final extTx = finalTx.buildIncomplete(); - extTx.addInput( - Format.stringToUint8List( - '0000000000000000000000000000000000000000000000000000000000000000', - ), - 4294967295, - 4294967295, - Format.stringToUint8List("c9"), - ); - // debugPrint("spendscript: $spendScript"); - extTx.setPayload(Format.stringToUint8List(spendScript)); - - final txHex = extTx.toHex(); - final txId = extTx.getId(); - - final amountAmount = Amount( - rawValue: BigInt.from(amount), - fractionDigits: arg.cryptoCurrency.fractionDigits, - ); - - return arg.txData.copyWith( - txid: txId, - raw: txHex, - recipients: [ - (address: address, amount: amountAmount, isChange: isChange), - ], - fee: Amount( - rawValue: BigInt.from(fee), - fractionDigits: arg.cryptoCurrency.fractionDigits, - ), - vSize: extTx.virtualSize(), - jMintValue: changeToMint, - spendCoinIndexes: spendCoinIndexes, - height: arg.locktime, - txType: TransactionType.outgoing, - txSubType: TransactionSubType.join, - // "confirmed_status": false, - // "timestamp": DateTime.now().millisecondsSinceEpoch ~/ 1000, - ); - - // return { - // "txid": txId, - // "txHex": txHex, - // "value": amount, - // "fees": Amount( - // rawValue: BigInt.from(fee), - // fractionDigits: arg.cryptoCurrency.fractionDigits, - // ).decimal.toDouble(), - // "fee": fee, - // "vSize": extTx.virtualSize(), - // "jmintValue": changeToMint, - // "spendCoinIndexes": spendCoinIndexes, - // "height": arg.locktime, - // "txType": "Sent", - // "confirmed_status": false, - // "amount": amountAmount.decimal.toDouble(), - // "recipientAmt": amountAmount, - // "address": arg.address, - // "timestamp": DateTime.now().millisecondsSinceEpoch ~/ 1000, - // "subType": "join", - // }; - } - - // =========================================================================== - - static Future _getMintScriptWrapper( - ({ - int amount, - String privateKeyHex, - int index, - String seedId, - bool isTestNet - }) data, - ) async { - final String mintHex = lelantus.getMintScript( - data.amount, - data.privateKeyHex, - data.index, - data.seedId, - isTestnet: data.isTestNet, - ); - return mintHex; - } - - static Future getMintScript({ - required Amount amount, - required String privateKeyHex, - required int index, - required String seedId, - required bool isTestNet, - }) async { - return await compute( - LelantusFfiWrapper._getMintScriptWrapper, - ( - amount: amount.raw.toInt(), - privateKeyHex: privateKeyHex, - index: index, - seedId: seedId, - isTestNet: isTestNet - ), - ); - } -} diff --git a/lib/wallets/isar/models/wallet_info.dart b/lib/wallets/isar/models/wallet_info.dart index f943ea5aa..bb4dd4ab2 100644 --- a/lib/wallets/isar/models/wallet_info.dart +++ b/lib/wallets/isar/models/wallet_info.dart @@ -497,9 +497,6 @@ abstract class WalletInfoKeys { static const String bananoMonkeyImageBytes = "monkeyImageBytesKey"; static const String tezosDerivationPath = "tezosDerivationPathKey"; static const String xelisDerivationPath = "xelisDerivationPathKey"; - static const String lelantusCoinIsarRescanRequired = - "lelantusCoinIsarRescanRequired"; - static const String enableLelantusScanning = "enableLelantusScanningKey"; static const String firoSparkCacheSetBlockHashCache = "firoSparkCacheSetBlockHashCacheKey"; static const String enableOptInRbf = "enableOptInRbfKey"; diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 96882d428..28b985be4 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -52,15 +52,9 @@ class TxData { final BigInt? chainId; // wownero and monero specific final lib_monero.PendingTransaction? pendingTransaction; - final lib_salvium.PendingTransaction? pendingSalviumTransaction; - // firo lelantus specific - final int? jMintValue; - final List? spendCoinIndexes; - final int? height; - final TransactionType? txType; - final TransactionSubType? txSubType; - final List>? mintsMapLelantus; + // salvium + final lib_salvium.PendingTransaction? pendingSalviumTransaction; // tezos specific final tezart.OperationsList? tezosOperationsList; @@ -113,12 +107,6 @@ class TxData { this.chainId, this.pendingTransaction, this.pendingSalviumTransaction, - this.jMintValue, - this.spendCoinIndexes, - this.height, - this.txType, - this.txSubType, - this.mintsMapLelantus, this.tezosOperationsList, this.sparkRecipients, this.otherData, @@ -303,12 +291,6 @@ class TxData { pendingTransaction: pendingTransaction ?? this.pendingTransaction, pendingSalviumTransaction: pendingSalviumTransaction ?? this.pendingSalviumTransaction, - jMintValue: jMintValue ?? this.jMintValue, - spendCoinIndexes: spendCoinIndexes ?? this.spendCoinIndexes, - height: height ?? this.height, - txType: txType ?? this.txType, - txSubType: txSubType ?? this.txSubType, - mintsMapLelantus: mintsMapLelantus ?? this.mintsMapLelantus, tezosOperationsList: tezosOperationsList ?? this.tezosOperationsList, sparkRecipients: sparkRecipients ?? this.sparkRecipients, sparkMints: sparkMints ?? this.sparkMints, @@ -347,12 +329,6 @@ class TxData { 'chainId: $chainId, ' 'pendingTransaction: $pendingTransaction, ' 'pendingSalviumTransaction: $pendingSalviumTransaction, ' - 'jMintValue: $jMintValue, ' - 'spendCoinIndexes: $spendCoinIndexes, ' - 'height: $height, ' - 'txType: $txType, ' - 'txSubType: $txSubType, ' - 'mintsMapLelantus: $mintsMapLelantus, ' 'tezosOperationsList: $tezosOperationsList, ' 'sparkRecipients: $sparkRecipients, ' 'sparkMints: $sparkMints, ' diff --git a/lib/wallets/wallet/impl/firo_wallet.dart b/lib/wallets/wallet/impl/firo_wallet.dart index 75d7290a9..233bfd344 100644 --- a/lib/wallets/wallet/impl/firo_wallet.dart +++ b/lib/wallets/wallet/impl/firo_wallet.dart @@ -23,7 +23,6 @@ import '../intermediate/bip39_hd_wallet.dart'; import '../wallet_mixin_interfaces/coin_control_interface.dart'; import '../wallet_mixin_interfaces/electrumx_interface.dart'; import '../wallet_mixin_interfaces/extended_keys_interface.dart'; -import '../wallet_mixin_interfaces/lelantus_interface.dart'; import '../wallet_mixin_interfaces/spark_interface.dart'; const sparkStartBlock = 819300; // (approx 18 Jan 2024) @@ -32,11 +31,9 @@ class FiroWallet extends Bip39HDWallet with ElectrumXInterface, ExtendedKeysInterface, - LelantusInterface, SparkInterface, CoinControlInterface { // IMPORTANT: The order of the above mixins matters. - // SparkInterface MUST come after LelantusInterface. FiroWallet(CryptoCurrencyNetwork network) : super(Firo(network) as T); @@ -695,20 +692,6 @@ class FiroWallet extends Bip39HDWallet await mainDB.deleteWalletBlockchainData(walletId); } - // lelantus - int? latestSetId; - final List> lelantusFutures = []; - final enableLelantusScanning = - info.otherData[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false; - if (enableLelantusScanning) { - latestSetId = await electrumXClient.getLelantusLatestCoinId(); - lelantusFutures.add( - electrumXCachedClient.getUsedCoinSerials(cryptoCurrency: info.coin), - ); - lelantusFutures.add(getSetDataMap(latestSetId)); - } - // spark final latestSparkCoinId = await electrumXClient.getSparkLatestCoinId(); final List> sparkAnonSetFutures = []; @@ -809,44 +792,9 @@ class FiroWallet extends Bip39HDWallet await Future.wait([updateTransactions(), updateUTXOs()]); - final List> futures = []; - if (enableLelantusScanning) { - futures.add(lelantusFutures[0]); - futures.add(lelantusFutures[1]); - } - futures.add(sparkUsedCoinTagsFuture); - futures.addAll(sparkAnonSetFutures); - - final futureResults = await Future.wait(futures); + await Future.wait([sparkUsedCoinTagsFuture, ...sparkAnonSetFutures]); - // lelantus - Set? usedSerialsSet; - Map? setDataMap; - if (enableLelantusScanning) { - usedSerialsSet = (futureResults[0] as List).toSet(); - setDataMap = futureResults[1] as Map; - } - - if (Util.isDesktop) { - await Future.wait([ - if (enableLelantusScanning) - recoverLelantusWallet( - latestSetId: latestSetId!, - usedSerialNumbers: usedSerialsSet!, - setDataMap: setDataMap!, - ), - recoverSparkWallet(latestSparkCoinId: latestSparkCoinId), - ]); - } else { - if (enableLelantusScanning) { - await recoverLelantusWallet( - latestSetId: latestSetId!, - usedSerialNumbers: usedSerialsSet!, - setDataMap: setDataMap!, - ); - } - await recoverSparkWallet(latestSparkCoinId: latestSparkCoinId); - } + await recoverSparkWallet(latestSparkCoinId: latestSparkCoinId); }); unawaited(refresh()); @@ -884,23 +832,4 @@ class FiroWallet extends Bip39HDWallet int estimateTxFee({required int vSize, required BigInt feeRatePerKB}) { return vSize * (feeRatePerKB.toInt() / 1000).ceil(); } - - // =========================================================================== - - bool get lelantusCoinIsarRescanRequired => - info.otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] as bool? ?? - true; - - Future firoRescanRecovery() async { - try { - await recover(isRescan: true); - await info.updateOtherData( - newEntries: {WalletInfoKeys.lelantusCoinIsarRescanRequired: false}, - isar: mainDB.isar, - ); - return true; - } catch (_) { - return false; - } - } } diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index 19923d45a..6ea950fe7 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -52,7 +52,6 @@ import 'impl/wownero_wallet.dart'; import 'impl/xelis_wallet.dart'; import 'intermediate/cryptonote_wallet.dart'; import 'wallet_mixin_interfaces/electrumx_interface.dart'; -import 'wallet_mixin_interfaces/lelantus_interface.dart'; import 'wallet_mixin_interfaces/mnemonic_interface.dart'; import 'wallet_mixin_interfaces/multi_address_interface.dart'; import 'wallet_mixin_interfaces/paynym_interface.dart'; @@ -686,13 +685,6 @@ abstract class Wallet { // await getAllTxsToWatch(); - // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided. - if (this is LelantusInterface && !viewOnly) { - if (info.otherData[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false) { - await (this as LelantusInterface).refreshLelantusData(); - } - } _fireRefreshPercentChange(0.90); await updateBalance(); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart deleted file mode 100644 index 1a7937113..000000000 --- a/lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart +++ /dev/null @@ -1,1215 +0,0 @@ -import 'dart:async'; -import 'dart:math'; -import 'dart:typed_data'; - -import 'package:bitcoindart/bitcoindart.dart' as bitcoindart; -import 'package:decimal/decimal.dart'; -import 'package:isar/isar.dart'; -import 'package:lelantus/lelantus.dart' as lelantus; -import 'package:tuple/tuple.dart'; - -import '../../../models/balance.dart'; -import '../../../models/isar/models/isar_models.dart'; -import '../../../models/lelantus_fee_data.dart'; -import '../../../utilities/amount/amount.dart'; -import '../../../utilities/enums/derive_path_type_enum.dart'; -import '../../../utilities/extensions/impl/uint8_list.dart'; -import '../../../utilities/format.dart'; -import '../../../utilities/logger.dart'; -import '../../api/lelantus_ffi_wrapper.dart'; -import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; -import '../../models/tx_data.dart'; -import '../intermediate/bip39_hd_wallet.dart'; -import 'electrumx_interface.dart'; - -mixin LelantusInterface - on Bip39HDWallet, ElectrumXInterface { - Future estimateFeeForLelantus(Amount amount) async { - final lelantusEntries = await _getLelantusEntry(); - final int spendAmount = amount.raw.toInt(); - if (spendAmount == 0 || lelantusEntries.isEmpty) { - return Amount( - rawValue: BigInt.from(LelantusFeeData(0, 0, []).fee), - fractionDigits: cryptoCurrency.fractionDigits, - ); - } - - final result = await LelantusFfiWrapper.estimateJoinSplitFee( - spendAmount: amount, - subtractFeeFromAmount: true, - lelantusEntries: lelantusEntries, - isTestNet: cryptoCurrency.network.isTestNet, - ); - - return Amount( - rawValue: BigInt.from(result.fee), - fractionDigits: cryptoCurrency.fractionDigits, - ); - } - - Future> _getLelantusEntry() async { - final List lelantusCoins = - await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .group( - (q) => q - .valueEqualTo("0") - .or() - .anonymitySetIdEqualTo( - LelantusFfiWrapper.ANONYMITY_SET_EMPTY_ID, - ), - ) - .findAll(); - - final root = await getRootHDNode(); - - final waitLelantusEntries = - lelantusCoins.map((coin) async { - final derivePath = cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: LelantusFfiWrapper.MINT_INDEX, - index: coin.mintIndex, - ); - - try { - final keyPair = root.derivePath(derivePath); - final String privateKey = keyPair.privateKey.data.toHex; - return lelantus.DartLelantusEntry( - coin.isUsed ? 1 : 0, - 0, - coin.anonymitySetId, - int.parse(coin.value), - coin.mintIndex, - privateKey, - ); - } catch (e, s) { - Logging.instance.e("error bad key"); - Logging.instance.t("error bad key", error: e, stackTrace: s); - return lelantus.DartLelantusEntry(1, 0, 0, 0, 0, ''); - } - }).toList(); - - final lelantusEntries = await Future.wait(waitLelantusEntries); - - if (lelantusEntries.isNotEmpty) { - // should be redundant as _getUnspentCoins() should - // already remove all where value=0 - lelantusEntries.removeWhere((element) => element.amount == 0); - } - - return lelantusEntries; - } - - Future prepareSendLelantus({required TxData txData}) async { - if (txData.recipients!.length != 1) { - throw Exception("Lelantus send requires a single recipient"); - } - - if (txData.recipients!.first.amount.raw > - BigInt.from(LelantusFfiWrapper.MINT_LIMIT)) { - throw Exception( - "Lelantus sends of more than 5001 are currently disabled", - ); - } - - try { - // check for send all - bool isSendAll = false; - final balance = info.cachedBalanceSecondary.spendable; - if (txData.recipients!.first.amount == balance) { - // print("is send all"); - isSendAll = true; - } - - final lastUsedIndex = await mainDB.getHighestUsedMintIndex( - walletId: walletId, - ); - final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; - - final root = await getRootHDNode(); - - final derivePath = cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: 0, - index: 0, - ); - final partialDerivationPath = derivePath.substring( - 0, - derivePath.length - 3, - ); - - final result = await LelantusFfiWrapper.createJoinSplitTransaction( - txData: txData, - subtractFeeFromAmount: isSendAll, - nextFreeMintIndex: nextFreeMintIndex, - locktime: await chainHeight, - lelantusEntries: await _getLelantusEntry(), - anonymitySets: await fetchAnonymitySets(), - cryptoCurrency: cryptoCurrency, - partialDerivationPath: partialDerivationPath, - hexRootPrivateKey: root.privateKey.data.toHex, - chaincode: root.chaincode, - ); - - Logging.instance.d("prepared fee: ${result.fee}"); - Logging.instance.d("prepared vSize: ${result.vSize}"); - - // fee should never be less than vSize sanity check - if (result.fee!.raw.toInt() < result.vSize!) { - throw Exception( - "Error in fee calculation: Transaction fee cannot be less than vSize", - ); - } - return result; - } catch (e, s) { - Logging.instance.e( - "Exception rethrown in firo prepareSend()", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - Future confirmSendLelantus({required TxData txData}) async { - final latestSetId = await electrumXClient.getLelantusLatestCoinId(); - final txid = await electrumXClient.broadcastTransaction(rawTx: txData.raw!); - - assert(txid == txData.txid!); - - final lastUsedIndex = await mainDB.getHighestUsedMintIndex( - walletId: walletId, - ); - final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; - - if (txData.spendCoinIndexes != null) { - // This is a joinsplit - - final spentCoinIndexes = txData.spendCoinIndexes!; - final List updatedCoins = []; - - // Update all of the coins that have been spent. - - for (final index in spentCoinIndexes) { - final possibleCoin = - await mainDB.isar.lelantusCoins - .where() - .mintIndexWalletIdEqualTo(index, walletId) - .findFirst(); - - if (possibleCoin != null) { - updatedCoins.add(possibleCoin.copyWith(isUsed: true)); - } - } - - // if a jmint was made add it to the unspent coin index - final jmint = LelantusCoin( - walletId: walletId, - mintIndex: nextFreeMintIndex, - value: (txData.jMintValue ?? 0).toString(), - txid: txid, - anonymitySetId: latestSetId, - isUsed: false, - isJMint: true, - otherData: null, - ); - - try { - await mainDB.isar.writeTxn(() async { - for (final c in updatedCoins) { - await mainDB.isar.lelantusCoins.deleteByMintIndexWalletId( - c.mintIndex, - c.walletId, - ); - } - await mainDB.isar.lelantusCoins.putAll(updatedCoins); - - await mainDB.isar.lelantusCoins.put(jmint); - }); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - rethrow; - } - - final amount = txData.amount!; - - // add the send transaction - final transaction = Transaction( - walletId: walletId, - txid: txid, - timestamp: (DateTime.now().millisecondsSinceEpoch ~/ 1000), - type: TransactionType.outgoing, - subType: TransactionSubType.join, - amount: amount.raw.toInt(), - amountString: amount.toJsonString(), - fee: txData.fee!.raw.toInt(), - height: txData.height, - isCancelled: false, - isLelantus: true, - slateId: null, - nonce: null, - otherData: null, - // otherData: transactionInfo["otherData"] as String?, - inputs: [], - outputs: [], - numberOfMessages: null, - ); - - final transactionAddress = - await mainDB - .getAddresses(walletId) - .filter() - .valueEqualTo(txData.recipients!.first.address) - .findFirst() ?? - Address( - walletId: walletId, - value: txData.recipients!.first.address, - derivationIndex: -1, - derivationPath: null, - type: AddressType.nonWallet, - subType: AddressSubType.nonWallet, - publicKey: [], - ); - - final List> txnsData = []; - - txnsData.add(Tuple2(transaction, transactionAddress)); - - await mainDB.addNewTransactionData(txnsData, walletId); - } else { - // This is a mint - Logging.instance.t("this is a mint"); - - final List updatedCoins = []; - - for (final mintMap in txData.mintsMapLelantus!) { - final index = mintMap['index'] as int; - final mint = LelantusCoin( - walletId: walletId, - mintIndex: index, - value: (mintMap['value'] as int).toString(), - txid: txid, - anonymitySetId: latestSetId, - isUsed: false, - isJMint: false, - otherData: null, - ); - - updatedCoins.add(mint); - } - // Logging.instance.log(coins); - try { - await mainDB.isar.writeTxn(() async { - await mainDB.isar.lelantusCoins.putAll(updatedCoins); - }); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - rethrow; - } - } - - return txData.copyWith(txid: txid); - } - - Future>> fastFetch(List allTxHashes) async { - final List> allTransactions = []; - - const futureLimit = 30; - final List>> transactionFutures = []; - int currentFutureCount = 0; - for (final txHash in allTxHashes) { - final Future> transactionFuture = - electrumXCachedClient.getTransaction( - txHash: txHash, - verbose: true, - cryptoCurrency: cryptoCurrency, - ); - transactionFutures.add(transactionFuture); - currentFutureCount++; - if (currentFutureCount > futureLimit) { - currentFutureCount = 0; - await Future.wait(transactionFutures); - for (final fTx in transactionFutures) { - final tx = await fTx; - // delete unused large parts - tx.remove("hex"); - tx.remove("lelantusData"); - - allTransactions.add(tx); - } - } - } - if (currentFutureCount != 0) { - currentFutureCount = 0; - await Future.wait(transactionFutures); - for (final fTx in transactionFutures) { - final tx = await fTx; - // delete unused large parts - tx.remove("hex"); - tx.remove("lelantusData"); - - allTransactions.add(tx); - } - } - return allTransactions; - } - - Future> getJMintTransactions( - List transactions, - ) async { - try { - final Map txs = {}; - final List> allTransactions = await fastFetch( - transactions, - ); - - for (int i = 0; i < allTransactions.length; i++) { - try { - final tx = allTransactions[i]; - - var sendIndex = 1; - if (tx["vout"][0]["value"] != null && - Decimal.parse(tx["vout"][0]["value"].toString()) > Decimal.zero) { - sendIndex = 0; - } - tx["amount"] = tx["vout"][sendIndex]["value"]; - tx["address"] = tx["vout"][sendIndex]["scriptPubKey"]["addresses"][0]; - tx["fees"] = tx["vin"][0]["nFees"]; - - final Amount amount = Amount.fromDecimal( - Decimal.parse(tx["amount"].toString()), - fractionDigits: cryptoCurrency.fractionDigits, - ); - - final txn = Transaction( - walletId: walletId, - txid: tx["txid"] as String, - timestamp: - tx["time"] as int? ?? - (DateTime.now().millisecondsSinceEpoch ~/ 1000), - type: TransactionType.outgoing, - subType: TransactionSubType.join, - amount: amount.raw.toInt(), - amountString: amount.toJsonString(), - fee: - Amount.fromDecimal( - Decimal.parse(tx["fees"].toString()), - fractionDigits: cryptoCurrency.fractionDigits, - ).raw.toInt(), - height: tx["height"] as int?, - isCancelled: false, - isLelantus: true, - slateId: null, - otherData: null, - nonce: null, - inputs: [], - outputs: [], - numberOfMessages: null, - ); - - final address = - await mainDB - .getAddresses(walletId) - .filter() - .valueEqualTo(tx["address"] as String) - .findFirst() ?? - Address( - walletId: walletId, - value: tx["address"] as String, - derivationIndex: -2, - derivationPath: null, - type: AddressType.nonWallet, - subType: AddressSubType.unknown, - publicKey: [], - ); - - txs[address] = txn; - } catch (e, s) { - Logging.instance.i( - "Exception caught in getJMintTransactions(): ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - return txs; - } catch (e, s) { - Logging.instance.i( - "Exception rethrown in getJMintTransactions(): ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - Future>> fetchAnonymitySets() async { - try { - final latestSetId = await electrumXClient.getLelantusLatestCoinId(); - - final List> sets = []; - final List>> anonFutures = []; - for (int i = 1; i <= latestSetId; i++) { - final set = electrumXCachedClient.getAnonymitySet( - groupId: "$i", - cryptoCurrency: info.coin, - ); - anonFutures.add(set); - } - await Future.wait(anonFutures); - for (int i = 1; i <= latestSetId; i++) { - final Map set = (await anonFutures[i - 1]); - set["setId"] = i; - sets.add(set); - } - return sets; - } catch (e, s) { - Logging.instance.e( - "Exception rethrown from refreshAnonymitySets: ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - Future> getSetDataMap(int latestSetId) async { - final Map setDataMap = {}; - final anonymitySets = await fetchAnonymitySets(); - for (int setId = 1; setId <= latestSetId; setId++) { - final setData = anonymitySets.firstWhere( - (element) => element["setId"] == setId, - orElse: () => {}, - ); - - if (setData.isNotEmpty) { - setDataMap[setId] = setData; - } - } - return setDataMap; - } - - // TODO: verify this function does what we think it does - Future refreshLelantusData() async { - final lelantusCoins = - await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .valueEqualTo(0.toString()) - .findAll(); - - final List updatedCoins = []; - - final usedSerialNumbersSet = - (await electrumXCachedClient.getUsedCoinSerials( - cryptoCurrency: info.coin, - )).toSet(); - - final root = await getRootHDNode(); - - for (final coin in lelantusCoins) { - final _derivePath = cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: LelantusFfiWrapper.MINT_INDEX, - index: coin.mintIndex, - ); - - final mintKeyPair = root.derivePath(_derivePath); - - final String serialNumber = lelantus.GetSerialNumber( - int.parse(coin.value), - mintKeyPair.privateKey.data.toHex, - coin.mintIndex, - isTestnet: cryptoCurrency.network.isTestNet, - ); - final bool isUsed = usedSerialNumbersSet.contains(serialNumber); - - if (isUsed) { - updatedCoins.add(coin.copyWith(isUsed: isUsed)); - } - - final tx = await mainDB.getTransaction(walletId, coin.txid); - if (tx == null) { - Logging.instance.e( - "Transaction with txid=REDACTED not found in local db!", - ); - Logging.instance.d( - "Transaction with txid=${coin.txid} not found in local db!", - ); - } - } - - if (updatedCoins.isNotEmpty) { - try { - await mainDB.isar.writeTxn(() async { - for (final c in updatedCoins) { - await mainDB.isar.lelantusCoins.deleteByMintIndexWalletId( - c.mintIndex, - c.walletId, - ); - } - await mainDB.isar.lelantusCoins.putAll(updatedCoins); - }); - } catch (e, s) { - Logging.instance.f(" ", error: e, stackTrace: s); - rethrow; - } - } - } - - /// Should only be called within the standard wallet [recover] function due to - /// mutex locking. Otherwise behaviour MAY be undefined. - Future recoverLelantusWallet({ - required int latestSetId, - required Map setDataMap, - required Set usedSerialNumbers, - }) async { - final root = await getRootHDNode(); - - final derivePath = cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: 0, - index: 0, - ); - - // get "m/$purpose'/$coinType'/$account'/" from "m/$purpose'/$coinType'/$account'/0/0" - final partialDerivationPath = derivePath.substring( - 0, - derivePath.length - 3, - ); - - final result = await LelantusFfiWrapper.restore( - hexRootPrivateKey: root.privateKey.data.toHex, - chaincode: root.chaincode, - cryptoCurrency: cryptoCurrency, - latestSetId: latestSetId, - setDataMap: setDataMap, - usedSerialNumbers: usedSerialNumbers, - walletId: walletId, - partialDerivationPath: partialDerivationPath, - ); - - final currentHeight = await chainHeight; - - final txns = - await mainDB - .getTransactions(walletId) - .filter() - .isLelantusIsNull() - .or() - .isLelantusEqualTo(false) - .findAll(); - - // TODO: [prio=high] shouldn't these be v2? If it doesn't matter than we can get rid of this logic - // Edit the receive transactions with the mint fees. - final List editedTransactions = []; - - for (final coin in result.lelantusCoins) { - final String txid = coin.txid; - Transaction? tx; - try { - tx = txns.firstWhere((e) => e.txid == txid); - } catch (_) { - tx = null; - } - - if (tx == null || tx.subType == TransactionSubType.join) { - // This is a jmint. - continue; - } - - final List inputTxns = []; - for (final input in tx.inputs) { - Transaction? inputTx; - try { - inputTx = txns.firstWhere((e) => e.txid == input.txid); - } catch (_) { - inputTx = null; - } - if (inputTx != null) { - inputTxns.add(inputTx); - } - } - if (inputTxns.isEmpty) { - //some error. - Logging.instance.f( - "cryptic \"//some error\" occurred in staticProcessRestore on lelantus coin: $coin", - ); - continue; - } - - final int mintFee = tx.fee; - final int sharedFee = mintFee ~/ inputTxns.length; - for (final inputTx in inputTxns) { - final edited = Transaction( - walletId: inputTx.walletId, - txid: inputTx.txid, - timestamp: inputTx.timestamp, - type: inputTx.type, - subType: TransactionSubType.mint, - amount: inputTx.amount, - amountString: - Amount( - rawValue: BigInt.from(inputTx.amount), - fractionDigits: cryptoCurrency.fractionDigits, - ).toJsonString(), - fee: sharedFee, - height: inputTx.height, - isCancelled: false, - isLelantus: true, - slateId: null, - otherData: txid, - nonce: null, - inputs: inputTx.inputs, - outputs: inputTx.outputs, - numberOfMessages: null, - )..address.value = inputTx.address.value; - editedTransactions.add(edited); - } - } - // Logging.instance.log(editedTransactions, addToDebugMessagesDB: false); - - final Map transactionMap = {}; - for (final e in txns) { - transactionMap[e.txid] = e; - } - // Logging.instance.log(transactionMap, addToDebugMessagesDB: false); - - // update with edited transactions - for (final tx in editedTransactions) { - transactionMap[tx.txid] = tx; - } - - transactionMap.removeWhere( - (key, value) => - result.lelantusCoins.any((element) => element.txid == key) || - ((value.height == -1 || value.height == null) && - !value.isConfirmed(currentHeight, cryptoCurrency.minConfirms)), - ); - - try { - await mainDB.isar.writeTxn(() async { - await mainDB.isar.lelantusCoins.putAll(result.lelantusCoins); - }); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - // don't just rethrow since isar likes to strip stack traces for some reason - throw Exception("e=$e & s=$s"); - } - - final Map> data = {}; - - for (final entry in transactionMap.entries) { - data[entry.key] = Tuple2(entry.value.address.value, entry.value); - } - - // Create the joinsplit transactions. - final spendTxs = await getJMintTransactions(result.spendTxIds); - Logging.instance.d("lelantus spendTxs: $spendTxs"); - - for (final element in spendTxs.entries) { - final address = - element.value.address.value ?? - data[element.value.txid]?.item1 ?? - element.key; - // Address( - // walletId: walletId, - // value: transactionInfo["address"] as String, - // derivationIndex: -1, - // type: AddressType.nonWallet, - // subType: AddressSubType.nonWallet, - // publicKey: [], - // ); - - data[element.value.txid] = Tuple2(address, element.value); - } - - final List> txnsData = []; - - for (final value in data.values) { - final transactionAddress = value.item1!; - final outs = value.item2.outputs - .where((_) => true) - .toList(growable: false); - final ins = value.item2.inputs.where((_) => true).toList(growable: false); - - txnsData.add( - Tuple2( - value.item2.copyWith(inputs: ins, outputs: outs).item1, - transactionAddress, - ), - ); - } - - await mainDB.addNewTransactionData(txnsData, walletId); - } - - /// Builds and signs a transaction - Future buildMintTransaction({required TxData txData}) async { - final signingData = await fetchBuildTxData(txData.utxos!.toList()); - - final convertedNetwork = bitcoindart.NetworkType( - messagePrefix: cryptoCurrency.networkParams.messagePrefix, - bech32: cryptoCurrency.networkParams.bech32Hrp, - bip32: bitcoindart.Bip32Type( - public: cryptoCurrency.networkParams.pubHDPrefix, - private: cryptoCurrency.networkParams.privHDPrefix, - ), - pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix, - scriptHash: cryptoCurrency.networkParams.p2shPrefix, - wif: cryptoCurrency.networkParams.wifPrefix, - ); - - final txb = bitcoindart.TransactionBuilder(network: convertedNetwork); - txb.setVersion(2); - - final int height = await chainHeight; - - txb.setLockTime(height); - int amount = 0; - // Add transaction inputs - for (var i = 0; i < signingData.length; i++) { - final pubKey = signingData[i].keyPair!.publicKey.data; - final bitcoindart.PaymentData? data; - - switch (signingData[i].derivePathType) { - case DerivePathType.bip44: - data = - bitcoindart - .P2PKH( - data: bitcoindart.PaymentData(pubkey: pubKey), - network: convertedNetwork, - ) - .data; - break; - - case DerivePathType.bip49: - final p2wpkh = - bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData(pubkey: pubKey), - network: convertedNetwork, - ) - .data; - data = - bitcoindart - .P2SH( - data: bitcoindart.PaymentData(redeem: p2wpkh), - network: convertedNetwork, - ) - .data; - break; - - case DerivePathType.bip84: - data = - bitcoindart - .P2WPKH( - data: bitcoindart.PaymentData(pubkey: pubKey), - network: convertedNetwork, - ) - .data; - break; - - case DerivePathType.bip86: - data = null; - break; - - default: - throw Exception("DerivePathType unsupported"); - } - - txb.addInput( - signingData[i].utxo.txid, - signingData[i].utxo.vout, - null, - data!.output!, - ); - amount += signingData[i].utxo.value; - } - - for (final mintsElement in txData.mintsMapLelantus!) { - Logging.instance.d("using $mintsElement"); - final Uint8List mintu8 = Format.stringToUint8List( - mintsElement['script'] as String, - ); - txb.addOutput(mintu8, mintsElement['value'] as int); - } - - for (var i = 0; i < signingData.length; i++) { - txb.sign( - vin: i, - keyPair: bitcoindart.ECPair.fromPrivateKey( - signingData[i].keyPair!.privateKey.data, - network: convertedNetwork, - compressed: signingData[i].keyPair!.privateKey.compressed, - ), - witnessValue: signingData[i].utxo.value, - ); - } - final incomplete = txb.buildIncomplete(); - final txId = incomplete.getId(); - final txHex = incomplete.toHex(); - final int fee = amount - incomplete.outs[0].value!; - - final builtHex = txb.build(); - - return txData.copyWith( - recipients: [ - ( - amount: Amount( - rawValue: BigInt.from(incomplete.outs[0].value!), - fractionDigits: cryptoCurrency.fractionDigits, - ), - address: "no address for lelantus mints", - isChange: false, - ), - ], - vSize: builtHex.virtualSize(), - txid: txId, - raw: txHex, - height: height, - txType: TransactionType.outgoing, - txSubType: TransactionSubType.mint, - fee: Amount( - rawValue: BigInt.from(fee), - fractionDigits: cryptoCurrency.fractionDigits, - ), - ); - - // return { - // "transaction": builtHex, - // "txid": txId, - // "txHex": txHex, - // "value": amount - fee, - // "fees": Amount( - // rawValue: BigInt.from(fee), - // fractionDigits: coin.fractionDigits, - // ).decimal.toDouble(), - // "height": height, - // "txType": "Sent", - // "confirmed_status": false, - // "amount": Amount( - // rawValue: BigInt.from(amount), - // fractionDigits: coin.fractionDigits, - // ).decimal.toDouble(), - // "timestamp": DateTime.now().millisecondsSinceEpoch ~/ 1000, - // "subType": "mint", - // "mintsMap": mintsMap, - // }; - } - - /// Returns the mint transaction hex to mint all of the available funds. - Future _mintSelection() async { - final currentChainHeight = await chainHeight; - final List availableOutputs = - await mainDB - .getUTXOs(walletId) - .filter() - .isBlockedEqualTo(false) - .findAll(); - final List spendableOutputs = []; - - // Build list of spendable outputs and totaling their satoshi amount - for (var i = 0; i < availableOutputs.length; i++) { - if (availableOutputs[i].isConfirmed( - currentChainHeight, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - ) == - true && - !(availableOutputs[i].isCoinbase && - availableOutputs[i].getConfirmations(currentChainHeight) <= - 101)) { - spendableOutputs.add(availableOutputs[i]); - } - } - - final lelantusCoins = - await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .not() - .valueEqualTo(0.toString()) - .findAll(); - - final data = - await mainDB - .getTransactions(walletId) - .filter() - .isLelantusIsNull() - .or() - .isLelantusEqualTo(false) - .findAll(); - - for (final value in data) { - if (value.inputs.isNotEmpty) { - for (final element in value.inputs) { - if (lelantusCoins.any((e) => e.txid == value.txid) && - spendableOutputs.firstWhere( - (output) => output?.txid == element.txid, - orElse: () => null, - ) != - null) { - spendableOutputs.removeWhere( - (output) => output!.txid == element.txid, - ); - } - } - } - } - - // If there is no Utxos to mint then stop the function. - if (spendableOutputs.isEmpty) { - throw Exception("_mintSelection(): No spendable outputs found"); - } - - int satoshisBeingUsed = 0; - final Set utxoObjectsToUse = {}; - - for (var i = 0; i < spendableOutputs.length; i++) { - final spendable = spendableOutputs[i]; - if (spendable != null) { - utxoObjectsToUse.add(spendable); - satoshisBeingUsed += spendable.value; - } - } - - final mintsWithoutFee = await _createMintsFromAmount(satoshisBeingUsed); - - TxData txData = await buildMintTransaction( - txData: TxData( - utxos: utxoObjectsToUse, - mintsMapLelantus: mintsWithoutFee, - ), - ); - - final Decimal dvSize = Decimal.fromInt(txData.vSize!); - - final feesObject = await fees; - - final Decimal fastFee = - Amount( - rawValue: feesObject.fast, - fractionDigits: cryptoCurrency.fractionDigits, - ).decimal; - int firoFee = - (dvSize * fastFee * Decimal.fromInt(100000)).toDouble().ceil(); - // int firoFee = (vSize * feesObject.fast * (1 / 1000.0) * 100000000).ceil(); - - if (firoFee < txData.vSize!) { - firoFee = txData.vSize! + 1; - } - firoFee = firoFee + 10; - final int satoshiAmountToSend = satoshisBeingUsed - firoFee; - - final mintsWithFee = await _createMintsFromAmount(satoshiAmountToSend); - - txData = await buildMintTransaction( - txData: txData.copyWith(mintsMapLelantus: mintsWithFee), - ); - - return txData; - } - - Future>> _createMintsFromAmount(int total) async { - if (total > LelantusFfiWrapper.MINT_LIMIT) { - throw Exception( - "Lelantus mints of more than 5001 are currently disabled", - ); - } - - int tmpTotal = total; - int counter = 0; - final lastUsedIndex = await mainDB.getHighestUsedMintIndex( - walletId: walletId, - ); - final nextFreeMintIndex = (lastUsedIndex ?? 0) + 1; - - final isTestnet = cryptoCurrency.network.isTestNet; - - final root = await getRootHDNode(); - - final mints = >[]; - while (tmpTotal > 0) { - final index = nextFreeMintIndex + counter; - - final mintKeyPair = root.derivePath( - cryptoCurrency.constructDerivePath( - derivePathType: DerivePathType.bip44, - chain: LelantusFfiWrapper.MINT_INDEX, - index: index, - ), - ); - - final privateKeyHex = mintKeyPair.privateKey.data.toHex; - final seedId = Format.uint8listToString(mintKeyPair.identifier); - - final String mintTag = lelantus.CreateTag( - privateKeyHex, - index, - seedId, - isTestnet: isTestnet, - ); - final List> anonymitySets; - try { - anonymitySets = await fetchAnonymitySets(); - } catch (e, s) { - Logging.instance.f( - "Firo needs better internet to create mints: ", - error: e, - stackTrace: s, - ); - rethrow; - } - - bool isUsedMintTag = false; - - // stupid dynamic maps - for (final set in anonymitySets) { - final setCoins = set["coins"] as List; - for (final coin in setCoins) { - if (coin[1] == mintTag) { - isUsedMintTag = true; - break; - } - } - if (isUsedMintTag) { - break; - } - } - - if (isUsedMintTag) { - Logging.instance.d("Found used index when minting"); - } - - if (!isUsedMintTag) { - final mintValue = min( - tmpTotal, - (isTestnet - ? LelantusFfiWrapper.MINT_LIMIT_TESTNET - : LelantusFfiWrapper.MINT_LIMIT), - ); - final mint = await LelantusFfiWrapper.getMintScript( - amount: Amount( - rawValue: BigInt.from(mintValue), - fractionDigits: cryptoCurrency.fractionDigits, - ), - privateKeyHex: privateKeyHex, - index: index, - seedId: seedId, - isTestNet: isTestnet, - ); - - mints.add({"value": mintValue, "script": mint, "index": index}); - tmpTotal = - tmpTotal - - (isTestnet - ? LelantusFfiWrapper.MINT_LIMIT_TESTNET - : LelantusFfiWrapper.MINT_LIMIT); - } - - counter++; - } - return mints; - } - - Future anonymizeAllLelantus() async { - try { - final mintResult = await _mintSelection(); - - await confirmSendLelantus(txData: mintResult); - - unawaited(refresh()); - } catch (e, s) { - Logging.instance.w( - "Exception caught in anonymizeAllLelantus(): ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - @override - Future updateBalance() async { - // call to super to update transparent balance - final normalBalanceFuture = super.updateBalance(); - - final lelantusCoins = - await mainDB.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .filter() - .isUsedEqualTo(false) - .not() - .valueEqualTo(0.toString()) - .findAll(); - - final currentChainHeight = await chainHeight; - int intLelantusBalance = 0; - int unconfirmedLelantusBalance = 0; - - for (final lelantusCoin in lelantusCoins) { - final Transaction? txn = - mainDB.isar.transactions - .where() - .txidWalletIdEqualTo(lelantusCoin.txid, walletId) - .findFirstSync(); - - if (txn == null) { - Logging.instance.e("Transaction not found in DB for lelantus coin"); - Logging.instance.d( - "Transaction not found in DB for lelantus coin: $lelantusCoin", - ); - } else { - if (txn.isLelantus != true) { - Logging.instance.f( - "Bad database state found in ${info.name} $walletId for _refreshBalance lelantus", - ); - } - - if (txn.isConfirmed(currentChainHeight, cryptoCurrency.minConfirms)) { - // mint tx, add value to balance - intLelantusBalance += int.parse(lelantusCoin.value); - } else { - unconfirmedLelantusBalance += int.parse(lelantusCoin.value); - } - } - } - - final balancePrivate = Balance( - total: Amount( - rawValue: BigInt.from(intLelantusBalance + unconfirmedLelantusBalance), - fractionDigits: cryptoCurrency.fractionDigits, - ), - spendable: Amount( - rawValue: BigInt.from(intLelantusBalance), - fractionDigits: cryptoCurrency.fractionDigits, - ), - blockedTotal: Amount( - rawValue: BigInt.zero, - fractionDigits: cryptoCurrency.fractionDigits, - ), - pendingSpendable: Amount( - rawValue: BigInt.from(unconfirmedLelantusBalance), - fractionDigits: cryptoCurrency.fractionDigits, - ), - ); - await info.updateBalanceSecondary( - newBalance: balancePrivate, - isar: mainDB.isar, - ); - - // wait for updated uxtos to get updated public balance - await normalBalanceFuture; - } -} diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index c22429d10..21bd7a74a 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -2243,8 +2243,7 @@ mixin SparkInterface @override Future updateBalance() async { - // call to super to update transparent balance (and lelantus balance if - // what ever class this mixin is used on uses LelantusInterface as well) + // call to super to update transparent balance final normalBalanceFuture = super.updateBalance(); // todo: spark balance aka update info.tertiaryBalance here? diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart index aa3175cac..3252be98e 100644 --- a/lib/widgets/desktop/desktop_fee_dialog.dart +++ b/lib/widgets/desktop/desktop_fee_dialog.dart @@ -73,10 +73,6 @@ class _DesktopFeeDialogState extends ConsumerState { fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, @@ -127,10 +123,6 @@ class _DesktopFeeDialogState extends ConsumerState { fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, @@ -181,10 +173,6 @@ class _DesktopFeeDialogState extends ConsumerState { fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.lelantus: - fee = await (wallet as FiroWallet).estimateFeeForLelantus( - amount, - ); case FiroType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, @@ -361,28 +349,6 @@ class _DesktopFeeItemState extends ConsumerState { ), child: Builder( builder: (_) { - if (!widget.isButton) { - final coin = ref.watch( - pWallets.select( - (value) => value.getWallet(widget.walletId).info.coin, - ), - ); - if ((coin is Firo) && - ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.lelantus) { - return Text( - "~${ref.watch(pAmountFormatter(coin)).format(Amount(rawValue: BigInt.parse("3794"), fractionDigits: coin.fractionDigits), indicatePrecisionLoss: false)}", - style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textFieldActiveText, - ), - textAlign: TextAlign.left, - ); - } - } - if (widget.feeRateType == FeeRateType.custom) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 8b28c002f..d2bf8597f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -17,7 +17,6 @@ import flutter_libepiccash import flutter_local_notifications import flutter_secure_storage_macos import isar_flutter_libs -import lelantus import local_auth_darwin import package_info_plus import path_provider_foundation @@ -41,7 +40,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin")) - LelantusPlugin.register(with: registry.registrar(forPlugin: "LelantusPlugin")) FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index a51d63f71..3dba40491 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -30,8 +30,6 @@ PODS: - FlutterMacOS - isar_flutter_libs (1.0.0): - FlutterMacOS - - lelantus (0.0.1): - - FlutterMacOS - local_auth_darwin (0.0.1): - Flutter - FlutterMacOS @@ -86,7 +84,6 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - frostdart (from `Flutter/ephemeral/.symlinks/plugins/frostdart/macos`) - isar_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/isar_flutter_libs/macos`) - - lelantus (from `Flutter/ephemeral/.symlinks/plugins/lelantus/macos`) - local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) @@ -135,8 +132,6 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/frostdart/macos isar_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/isar_flutter_libs/macos - lelantus: - :path: Flutter/ephemeral/.symlinks/plugins/lelantus/macos local_auth_darwin: :path: Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin package_info_plus: @@ -176,7 +171,6 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 frostdart: e6bf3119527ccfbcec1b8767da6ede5bb4c4f716 isar_flutter_libs: 43385c99864c168fadba7c9adeddc5d38838ca6a - lelantus: 308e42c5a648598936a07a234471dd8cf8e687a0 local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 diff --git a/pubspec.lock b/pubspec.lock index 6cb6be1ac..7c3844799 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1361,13 +1361,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - lelantus: - dependency: "direct main" - description: - path: "crypto_plugins/flutter_liblelantus" - relative: true - source: path - version: "0.0.3" lints: dependency: transitive description: diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh index 5438234ea..d791b933b 100755 --- a/scripts/android/build_all.sh +++ b/scripts/android/build_all.sh @@ -7,8 +7,6 @@ mkdir -p build PLUGINS_DIR=../../crypto_plugins -(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/android/build_all_campfire.sh b/scripts/android/build_all_campfire.sh index 5438234ea..d791b933b 100755 --- a/scripts/android/build_all_campfire.sh +++ b/scripts/android/build_all_campfire.sh @@ -7,8 +7,6 @@ mkdir -p build PLUGINS_DIR=../../crypto_plugins -(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/android/build_all_duo.sh b/scripts/android/build_all_duo.sh index 40be4bee4..39579d238 100755 --- a/scripts/android/build_all_duo.sh +++ b/scripts/android/build_all_duo.sh @@ -9,8 +9,6 @@ mkdir -p build PLUGINS_DIR=../../crypto_plugins -(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj b/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj index c89885057..5c1e9e238 100644 --- a/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj +++ b/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj @@ -11,8 +11,6 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7E1603B5288D73EA002F7A6F /* libepic_cash_wallet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E8A4F06288D5A9300F18717 /* libepic_cash_wallet.a */; }; - 7E569F992798D47200056D51 /* mobileliblelantus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E569F982798D47200056D51 /* mobileliblelantus.framework */; }; - 7E569F9A2798D47F00056D51 /* mobileliblelantus.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7E569F982798D47200056D51 /* mobileliblelantus.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7E729AE82893C1B1009BBD65 /* flutter_libepiccash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E1603B3288D734C002F7A6F /* flutter_libepiccash.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -20,20 +18,6 @@ B49D91439948369648AB0603 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51604430FD0FD1FA5C4767A0 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 7E569F9A2798D47F00056D51 /* mobileliblelantus.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; @@ -45,7 +29,6 @@ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7E1603B3288D734C002F7A6F /* flutter_libepiccash.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = flutter_libepiccash.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E569F982798D47200056D51 /* mobileliblelantus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mobileliblelantus.framework; path = ../crypto_plugins/flutter_liblelantus/scripts/ios/mobileliblelantus/mobileliblelantus.framework; sourceTree = ""; }; 7E8A4F02288D57DE00F18717 /* flutter_libepiccash.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = flutter_libepiccash.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7E8A4F06288D5A9300F18717 /* libepic_cash_wallet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libepic_cash_wallet.a; path = ../crypto_plugins/flutter_libepiccash/ios/libs/libepic_cash_wallet.a; sourceTree = ""; }; 7E8A4F09288D5E8F00F18717 /* flutter_libepiccash.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = flutter_libepiccash.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -74,7 +57,6 @@ files = ( 7E1603B5288D73EA002F7A6F /* libepic_cash_wallet.a in Frameworks */, 7E729AE82893C1B1009BBD65 /* flutter_libepiccash.framework in Frameworks */, - 7E569F992798D47200056D51 /* mobileliblelantus.framework in Frameworks */, B49D91439948369648AB0603 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -104,7 +86,6 @@ 7E8A4F09288D5E8F00F18717 /* flutter_libepiccash.framework */, 7E8A4F06288D5A9300F18717 /* libepic_cash_wallet.a */, 7E8A4F02288D57DE00F18717 /* flutter_libepiccash.framework */, - 7E569F982798D47200056D51 /* mobileliblelantus.framework */, 51604430FD0FD1FA5C4767A0 /* Pods_Runner.framework */, ); name = Frameworks; @@ -178,7 +159,6 @@ 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, FD1CA371131604E6658D4146 /* [CP] Embed Pods Frameworks */, 4823D12ED8C268BC85F26ABD /* [CP] Copy Pods Resources */, @@ -343,7 +323,6 @@ "${BUILT_PRODUCTS_DIR}/frostdart/frostdart.framework", "${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework", "${BUILT_PRODUCTS_DIR}/isar_flutter_libs/isar_flutter_libs.framework", - "${BUILT_PRODUCTS_DIR}/lelantus/lelantus.framework", "${BUILT_PRODUCTS_DIR}/local_auth_darwin/local_auth_darwin.framework", "${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework", "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", @@ -380,7 +359,6 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/frostdart.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/isar_flutter_libs.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/lelantus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_darwin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", @@ -497,7 +475,6 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/../crypto_plugins/flutter_liblelantus/scripts/ios/mobileliblelantus", "$(PROJECT_DIR)", ); HEADER_SEARCH_PATHS = ( @@ -516,7 +493,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash/flutter_native_splash.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage/flutter_secure_storage.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/integration_test/integration_test.framework/Headers\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus/lelantus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/local_auth/local_auth.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus/package_info_plus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_ios/path_provider_ios.framework/Headers\"", @@ -679,7 +655,6 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/../crypto_plugins/flutter_liblelantus/scripts/ios/mobileliblelantus", "$(PROJECT_DIR)", ); HEADER_SEARCH_PATHS = ( @@ -698,7 +673,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash/flutter_native_splash.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage/flutter_secure_storage.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/integration_test/integration_test.framework/Headers\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus/lelantus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/local_auth/local_auth.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus/package_info_plus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_ios/path_provider_ios.framework/Headers\"", @@ -753,7 +727,6 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/../crypto_plugins/flutter_liblelantus/scripts/ios/mobileliblelantus/**", "$(PROJECT_DIR)", ); HEADER_SEARCH_PATHS = ( @@ -772,7 +745,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash/flutter_native_splash.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage/flutter_secure_storage.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/integration_test/integration_test.framework/Headers\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus/lelantus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/local_auth/local_auth.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus/package_info_plus.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_ios/path_provider_ios.framework/Headers\"", diff --git a/scripts/app_config/templates/linux/CMakeLists.txt b/scripts/app_config/templates/linux/CMakeLists.txt index 25750ef4f..94d6e7f5e 100644 --- a/scripts/app_config/templates/linux/CMakeLists.txt +++ b/scripts/app_config/templates/linux/CMakeLists.txt @@ -137,9 +137,6 @@ install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash/scripts/linux/build/rust/target/x86_64-unknown-linux-gnu/release/libepic_cash_wallet.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/scripts/app_config/templates/macos/Runner.xcodeproj/project.pbxproj b/scripts/app_config/templates/macos/Runner.xcodeproj/project.pbxproj index 6db80d9b0..c0fe37d8a 100644 --- a/scripts/app_config/templates/macos/Runner.xcodeproj/project.pbxproj +++ b/scripts/app_config/templates/macos/Runner.xcodeproj/project.pbxproj @@ -27,8 +27,6 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - B98151812A674022009D013C /* mobileliblelantus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B98151802A674022009D013C /* mobileliblelantus.framework */; }; - B98151822A67402A009D013C /* mobileliblelantus.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = B98151802A674022009D013C /* mobileliblelantus.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B98151842A674143009D013C /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B98151832A674143009D013C /* libsqlite3.0.tbd */; }; BFD0376C00E1FFD46376BB9D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */; }; F1FA2C4E2BA4B49F00BDA1BB /* frostdart.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F1FA2C4D2BA4B49F00BDA1BB /* frostdart.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; @@ -62,7 +60,6 @@ dstSubfolderSpec = 10; files = ( F1FA2C512BA4B51E00BDA1BB /* frostdart.dylib in Bundle Framework */, - B98151822A67402A009D013C /* mobileliblelantus.framework in Bundle Framework */, ); name = "Bundle Framework"; runOnlyForDeploymentPostprocessing = 0; @@ -94,7 +91,6 @@ 9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; ACB8E553D75AA4AC9A7656CE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - B98151802A674022009D013C /* mobileliblelantus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mobileliblelantus.framework; path = ../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus/mobileliblelantus.framework; sourceTree = ""; }; B98151832A674143009D013C /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; }; BF5E76865ACB46314AC27D8F /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; E6036BF01BF05EA773C76D22 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -116,7 +112,6 @@ buildActionMask = 2147483647; files = ( B98151842A674143009D013C /* libsqlite3.0.tbd in Frameworks */, - B98151812A674022009D013C /* mobileliblelantus.framework in Frameworks */, F1FA2C4E2BA4B49F00BDA1BB /* frostdart.dylib in Frameworks */, F653CA022D33E8B60E11A9F3 /* Pods_Runner.framework in Frameworks */, ); @@ -206,7 +201,6 @@ children = ( F1FA2C4D2BA4B49F00BDA1BB /* frostdart.dylib */, B98151832A674143009D013C /* libsqlite3.0.tbd */, - B98151802A674022009D013C /* mobileliblelantus.framework */, E6036BF01BF05EA773C76D22 /* Pods_Runner.framework */, 9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */, ); @@ -602,7 +596,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", @@ -610,7 +603,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"", - "\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -760,7 +752,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", @@ -768,7 +759,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"", - "\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -809,7 +799,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", @@ -817,7 +806,6 @@ "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"", - "\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 9b007143e..6a8c1f552 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -24,9 +24,6 @@ dependencies: mutex: ^3.0.0 web_socket_channel: ^2.4.0 - lelantus: - path: ./crypto_plugins/flutter_liblelantus - frostdart: path: ./crypto_plugins/frostdart diff --git a/scripts/app_config/templates/windows/CMakeLists.txt b/scripts/app_config/templates/windows/CMakeLists.txt index b9add856d..650a25d76 100644 --- a/scripts/app_config/templates/windows/CMakeLists.txt +++ b/scripts/app_config/templates/windows/CMakeLists.txt @@ -83,9 +83,6 @@ install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash/scripts/windows/build/libepic_cash_wallet.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/scripts/ios/build_all.sh b/scripts/ios/build_all.sh index c47228cdc..b6f93e35f 100755 --- a/scripts/ios/build_all.sh +++ b/scripts/ios/build_all.sh @@ -10,8 +10,6 @@ rustup target add x86_64-apple-ios rustup target add aarch64-apple-ios rustup target add x86_64-apple-ios -(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/ios/build_all_campfire.sh b/scripts/ios/build_all_campfire.sh index c47228cdc..b6f93e35f 100755 --- a/scripts/ios/build_all_campfire.sh +++ b/scripts/ios/build_all_campfire.sh @@ -10,8 +10,6 @@ rustup target add x86_64-apple-ios rustup target add aarch64-apple-ios rustup target add x86_64-apple-ios -(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/ios/build_all_duo.sh b/scripts/ios/build_all_duo.sh index 3e3a73119..ea00ed599 100755 --- a/scripts/ios/build_all_duo.sh +++ b/scripts/ios/build_all_duo.sh @@ -12,8 +12,6 @@ rustup target add x86_64-apple-ios rustup target add aarch64-apple-ios rustup target add x86_64-apple-ios -(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh ) - # libepiccash requires old rust source ../rust_version.sh set_rust_version_for_libepiccash diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 011d972b3..a2e6c3d85 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -8,7 +8,6 @@ set -x -e # flutter-elinux build linux --dart-define="IS_ARM=true" mkdir -p build ./build_secure_storage_deps.sh -(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) # libepiccash requires old rust source ../rust_version.sh diff --git a/scripts/linux/build_all_campfire.sh b/scripts/linux/build_all_campfire.sh index 011d972b3..a2e6c3d85 100755 --- a/scripts/linux/build_all_campfire.sh +++ b/scripts/linux/build_all_campfire.sh @@ -8,7 +8,6 @@ set -x -e # flutter-elinux build linux --dart-define="IS_ARM=true" mkdir -p build ./build_secure_storage_deps.sh -(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) # libepiccash requires old rust source ../rust_version.sh diff --git a/scripts/linux/build_all_duo.sh b/scripts/linux/build_all_duo.sh index aa804e73e..b9c18f6b2 100755 --- a/scripts/linux/build_all_duo.sh +++ b/scripts/linux/build_all_duo.sh @@ -10,8 +10,7 @@ set -x -e # flutter-elinux pub get # flutter-elinux build linux --dart-define="IS_ARM=true" mkdir -p build -./build_secure_storage_deps.sh & -(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) +./build_secure_storage_deps.sh # libepiccash requires old rust source ../rust_version.sh diff --git a/scripts/macos/build_all.sh b/scripts/macos/build_all.sh index 37dda0e64..5cfed585f 100755 --- a/scripts/macos/build_all.sh +++ b/scripts/macos/build_all.sh @@ -10,7 +10,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh ) wait diff --git a/scripts/macos/build_all_campfire.sh b/scripts/macos/build_all_campfire.sh index 59a93ef26..e13ad106d 100755 --- a/scripts/macos/build_all_campfire.sh +++ b/scripts/macos/build_all_campfire.sh @@ -10,7 +10,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh ) wait diff --git a/scripts/macos/build_all_duo.sh b/scripts/macos/build_all_duo.sh index 960f5a44a..a520cafc2 100755 --- a/scripts/macos/build_all_duo.sh +++ b/scripts/macos/build_all_duo.sh @@ -12,7 +12,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh ) wait diff --git a/scripts/windows/build_all.sh b/scripts/windows/build_all.sh index cf3ad76d9..338394410 100755 --- a/scripts/windows/build_all.sh +++ b/scripts/windows/build_all.sh @@ -11,7 +11,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh ) ./build_secp256k1_wsl.sh diff --git a/scripts/windows/build_all_campfire.sh b/scripts/windows/build_all_campfire.sh index cf3ad76d9..338394410 100755 --- a/scripts/windows/build_all_campfire.sh +++ b/scripts/windows/build_all_campfire.sh @@ -11,7 +11,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh ) ./build_secp256k1_wsl.sh diff --git a/scripts/windows/build_all_duo.sh b/scripts/windows/build_all_duo.sh index e54986e7d..e70eb145d 100755 --- a/scripts/windows/build_all_duo.sh +++ b/scripts/windows/build_all_duo.sh @@ -13,7 +13,6 @@ set_rust_version_for_libepiccash # set rust (back) to a more recent stable release after building epiccash set_rust_to_everything_else -(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh ) (cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh ) ./build_secp256k1_wsl.sh diff --git a/scripts/windows/deps.sh b/scripts/windows/deps.sh index c9975b457..f68011a69 100644 --- a/scripts/windows/deps.sh +++ b/scripts/windows/deps.sh @@ -1,8 +1,6 @@ #!/bin/bash cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./deps.sh -cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./mxedeps.sh -# cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./monerodeps.sh && ./mxedeps.sh sudo apt install libgtk2.0-dev wait diff --git a/test/models/lelantus_fee_data_test.dart b/test/models/lelantus_fee_data_test.dart deleted file mode 100644 index a6e2ebb9b..000000000 --- a/test/models/lelantus_fee_data_test.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:stackwallet/models/lelantus_fee_data.dart'; - -void main() { - test("LelantusFeeData constructor", () { - final lfData = LelantusFeeData(10000, 3794, [1, 2, 1, 0, 1]); - expect(lfData.toString(), - "{changeToMint: 10000, fee: 3794, spendCoinIndexes: [1, 2, 1, 0, 1]}"); - }); -} From f3d923e91928d0a5ef2b45a0a167b8a0266ca848 Mon Sep 17 00:00:00 2001 From: Julian Date: Thu, 29 May 2025 13:15:08 -0600 Subject: [PATCH 102/206] ios fix --- ios/Podfile.lock | 16 +++++++++++++--- macos/Podfile.lock | 13 +++++++++++-- .../ios/Runner.xcodeproj/project.pbxproj | 14 ++++++++++---- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 13a199bd8..3f6bee8e7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,6 +11,8 @@ PODS: - ReachabilitySwift - cs_monero_flutter_libs_ios (0.0.1): - Flutter + - cs_salvium_flutter_libs_ios (0.0.1): + - Flutter - device_info_plus (0.0.1): - Flutter - devicelocale (0.0.1): @@ -85,6 +87,8 @@ PODS: - "sqlite3 (3.46.0+1)": - "sqlite3/common (= 3.46.0+1)" - "sqlite3/common (3.46.0+1)" + - "sqlite3/dbstatvtab (3.46.0+1)": + - sqlite3/common - "sqlite3/fts5 (3.46.0+1)": - sqlite3/common - "sqlite3/perf-threadsafe (3.46.0+1)": @@ -93,7 +97,8 @@ PODS: - sqlite3/common - sqlite3_flutter_libs (0.0.1): - Flutter - - sqlite3 (~> 3.46.0) + - "sqlite3 (~> 3.46.0+1)" + - sqlite3/dbstatvtab - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -115,6 +120,7 @@ DEPENDENCIES: - coinlib_flutter (from `.symlinks/plugins/coinlib_flutter/darwin`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - cs_monero_flutter_libs_ios (from `.symlinks/plugins/cs_monero_flutter_libs_ios/ios`) + - cs_salvium_flutter_libs_ios (from `.symlinks/plugins/cs_salvium_flutter_libs_ios/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) @@ -159,6 +165,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/connectivity_plus/ios" cs_monero_flutter_libs_ios: :path: ".symlinks/plugins/cs_monero_flutter_libs_ios/ios" + cs_salvium_flutter_libs_ios: + :path: ".symlinks/plugins/cs_salvium_flutter_libs_ios/ios" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" devicelocale: @@ -211,6 +219,7 @@ SPEC CHECKSUMS: coinlib_flutter: 9275e8255ef67d3da33beb6e117d09ced4f46eb5 connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a cs_monero_flutter_libs_ios: fd353631682247f72a36493ff060d4328d6f720d + cs_salvium_flutter_libs_ios: f9d6ce540cb34d8cb8641822cf02fa0695a8d405 device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926 DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac @@ -234,13 +243,14 @@ SPEC CHECKSUMS: SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866 share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5 sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630 - sqlite3_flutter_libs: 0d611efdf6d1c9297d5ab03dab21b75aeebdae31 + sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b stack_wallet_backup: 5b8563aba5d8ffbf2ce1944331ff7294a0ec7c03 SwiftProtobuf: 6ef3f0e422ef90d6605ca20b21a94f6c1324d6b3 SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 tor_ffi_plugin: d80e291b649379c8176e1be739e49be007d4ef93 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1 + wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 + xelis_flutter: a6a1ee1f1e47f5aeb42dc4a5889358b79d8d90fc PODFILE CHECKSUM: 57c8aed26fba39d3ec9424816221f294a07c58eb diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 3dba40491..64b655098 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -9,6 +9,8 @@ PODS: - ReachabilitySwift - cs_monero_flutter_libs_macos (0.0.1): - FlutterMacOS + - cs_salvium_flutter_libs_macos (0.0.1): + - FlutterMacOS - desktop_drop (0.0.1): - FlutterMacOS - device_info_plus (0.0.1): @@ -44,6 +46,8 @@ PODS: - "sqlite3 (3.46.0+1)": - "sqlite3/common (= 3.46.0+1)" - "sqlite3/common (3.46.0+1)" + - "sqlite3/dbstatvtab (3.46.0+1)": + - sqlite3/common - "sqlite3/fts5 (3.46.0+1)": - sqlite3/common - "sqlite3/perf-threadsafe (3.46.0+1)": @@ -52,7 +56,8 @@ PODS: - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.46.0) + - "sqlite3 (~> 3.46.0+1)" + - sqlite3/dbstatvtab - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -73,6 +78,7 @@ DEPENDENCIES: - coinlib_flutter (from `Flutter/ephemeral/.symlinks/plugins/coinlib_flutter/darwin`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - cs_monero_flutter_libs_macos (from `Flutter/ephemeral/.symlinks/plugins/cs_monero_flutter_libs_macos/macos`) + - cs_salvium_flutter_libs_macos (from `Flutter/ephemeral/.symlinks/plugins/cs_salvium_flutter_libs_macos/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) @@ -110,6 +116,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos cs_monero_flutter_libs_macos: :path: Flutter/ephemeral/.symlinks/plugins/cs_monero_flutter_libs_macos/macos + cs_salvium_flutter_libs_macos: + :path: Flutter/ephemeral/.symlinks/plugins/cs_salvium_flutter_libs_macos/macos desktop_drop: :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos device_info_plus: @@ -160,6 +168,7 @@ SPEC CHECKSUMS: coinlib_flutter: 9275e8255ef67d3da33beb6e117d09ced4f46eb5 connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 cs_monero_flutter_libs_macos: b901f94d39d1338f706312b026aba928d23582d4 + cs_salvium_flutter_libs_macos: 3c7b30fb8c82ee0fb0195280ddcc10c65ab5e082 desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 @@ -177,7 +186,7 @@ SPEC CHECKSUMS: ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979 share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7 sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630 - sqlite3_flutter_libs: 1be4459672f8168ded2d8667599b8e3ca5e72b83 + sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b stack_wallet_backup: 6ebc60b1bdcf11cf1f1cbad9aa78332e1e15778c tor_ffi_plugin: 2566c1ed174688cca560fa0c64b7a799c66f07cb url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 diff --git a/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj b/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj index 5c1e9e238..300249f37 100644 --- a/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj +++ b/scripts/app_config/templates/ios/Runner.xcodeproj/project.pbxproj @@ -310,9 +310,11 @@ "${BUILT_PRODUCTS_DIR}/barcode_scan2/barcode_scan2.framework", "${BUILT_PRODUCTS_DIR}/coinlib_flutter/secp256k1.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", - "${PODS_ROOT}/../.symlinks/plugins/cs_monero_flutter_libs/ios/Frameworks/MoneroWallet.framework", - "${PODS_ROOT}/../.symlinks/plugins/cs_monero_flutter_libs/ios/Frameworks/WowneroWallet.framework", - "${BUILT_PRODUCTS_DIR}/cs_monero_flutter_libs/cs_monero_flutter_libs.framework", + "${PODS_ROOT}/../.symlinks/plugins/cs_monero_flutter_libs_ios/ios/Frameworks/MoneroWallet.framework", + "${PODS_ROOT}/../.symlinks/plugins/cs_monero_flutter_libs_ios/ios/Frameworks/WowneroWallet.framework", + "${BUILT_PRODUCTS_DIR}/cs_monero_flutter_libs_ios/cs_monero_flutter_libs_ios.framework", + "${PODS_ROOT}/../.symlinks/plugins/cs_salvium_flutter_libs_ios/ios/Frameworks/SalviumWallet.framework", + "${BUILT_PRODUCTS_DIR}/cs_salvium_flutter_libs_ios/cs_salvium_flutter_libs_ios.framework", "${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework", "${BUILT_PRODUCTS_DIR}/devicelocale/devicelocale.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", @@ -333,6 +335,7 @@ "${BUILT_PRODUCTS_DIR}/tor_ffi_plugin/tor_ffi_plugin.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", "${BUILT_PRODUCTS_DIR}/wakelock_plus/wakelock_plus.framework", + "${BUILT_PRODUCTS_DIR}/xelis_flutter/xelis_flutter.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -348,7 +351,9 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MoneroWallet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WowneroWallet.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cs_monero_flutter_libs.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cs_monero_flutter_libs_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SalviumWallet.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cs_salvium_flutter_libs_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/devicelocale.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", @@ -369,6 +374,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/tor_ffi_plugin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock_plus.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/xelis_flutter.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; From 58703ac6b5549e56fa5de4d8e591e8be47e27af3 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 29 May 2025 15:13:14 -0600 Subject: [PATCH 103/206] Add space on desktop --- .../frost_ms/new/select_new_frost_import_type_view.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart index e00f679cb..131e60004 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart @@ -170,6 +170,7 @@ class _SelectNewFrostImportTypeViewState ).pushNamed(FrostStepScaffold.routeName); }, ), + if (Util.isDesktop) const SizedBox(height: 32), ], ), ), From 769a872be10aa3c265f2a0a33309b864e63efd7b Mon Sep 17 00:00:00 2001 From: Julian Date: Thu, 29 May 2025 16:16:38 -0600 Subject: [PATCH 104/206] ios cam permission dialog tweak --- lib/utilities/barcode_scanner_interface.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/utilities/barcode_scanner_interface.dart b/lib/utilities/barcode_scanner_interface.dart index 7579eedcf..87b079d03 100644 --- a/lib/utilities/barcode_scanner_interface.dart +++ b/lib/utilities/barcode_scanner_interface.dart @@ -44,7 +44,11 @@ Future checkCamPermDeniedMobileAndOpenAppSettings( }) async { if (Platform.isAndroid || Platform.isIOS) { final status = await Permission.camera.status; - if (status == PermissionStatus.permanentlyDenied && context.mounted) { + final androidShow = + Platform.isAndroid && status == PermissionStatus.permanentlyDenied; + final iosShow = Platform.isIOS && status == PermissionStatus.denied; + + if ((iosShow || androidShow) && context.mounted) { final trySettings = await showDialog( context: context, builder: From 0ff1ad0a9aab384b1420eaffd07e4baac744f720 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 May 2025 11:05:39 -0600 Subject: [PATCH 105/206] show prev gen frost info in backup view --- .../unlock_wallet_keys_desktop.dart | 127 ++++----- .../wallet_keys_desktop_popup.dart | 257 ++++++++++-------- lib/route_generator.dart | 16 +- 3 files changed, 214 insertions(+), 186 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart index 3faf4ec80..4f1db4504 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart @@ -37,10 +37,7 @@ import '../../../../widgets/stack_text_field.dart'; import 'wallet_keys_desktop_popup.dart'; class UnlockWalletKeysDesktop extends ConsumerStatefulWidget { - const UnlockWalletKeysDesktop({ - super.key, - required this.walletId, - }); + const UnlockWalletKeysDesktop({super.key, required this.walletId}); final String walletId; @@ -64,16 +61,12 @@ class _UnlockWalletKeysDesktopState unawaited( showDialog( context: context, - builder: (context) => const Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - LoadingIndicator( - width: 200, - height: 200, + builder: + (context) => const Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [LoadingIndicator(width: 200, height: 200)], ), - ], - ), ), ); @@ -89,17 +82,38 @@ class _UnlockWalletKeysDesktopState } final wallet = ref.read(pWallets).getWallet(widget.walletId); - ({String keys, String config})? frostData; + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData; List? words; // TODO: [prio=low] handle wallets that don't have a mnemonic // All wallets currently are mnemonic based if (wallet is! MnemonicInterface) { if (wallet is BitcoinFrostWallet) { - frostData = ( - keys: (await wallet.getSerializedKeys())!, - config: (await wallet.getMultisigConfig())!, - ); + final futures = [ + wallet.getSerializedKeys(), + wallet.getMultisigConfig(), + wallet.getSerializedKeysPrevGen(), + wallet.getMultisigConfigPrevGen(), + ]; + + final results = await Future.wait(futures); + if (results.length == 4) { + frostWalletData = ( + myName: wallet.frostInfo.myName, + config: results[1]!, + keys: results[0]!, + prevGen: + results[2] == null || results[3] == null + ? null + : (config: results[3]!, keys: results[2]!), + ); + } } else { throw Exception("FIXME ~= see todo in code"); } @@ -129,7 +143,7 @@ class _UnlockWalletKeysDesktopState arguments: ( mnemonic: words ?? [], walletId: widget.walletId, - frostData: frostData, + frostData: frostWalletData, keyData: keyData, ), ); @@ -177,44 +191,25 @@ class _UnlockWalletKeysDesktopState mainAxisAlignment: MainAxisAlignment.end, children: [ DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, ), ], ), - const SizedBox( - height: 12, - ), - SvgPicture.asset( - Assets.svg.keys, - width: 100, - height: 58, - ), - const SizedBox( - height: 55, - ), - Text( - "Wallet keys", - style: STextStyles.desktopH2(context), - ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 12), + SvgPicture.asset(Assets.svg.keys, width: 100, height: 58), + const SizedBox(height: 55), + Text("Wallet keys", style: STextStyles.desktopH2(context)), + const SizedBox(height: 16), Text( "Enter your password", style: STextStyles.desktopTextMedium(context).copyWith( color: Theme.of(context).extension()!.textDark3, ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -223,9 +218,9 @@ class _UnlockWalletKeysDesktopState key: const Key("enterPasswordUnlockWalletKeysDesktopFieldKey"), focusNode: passwordFocusNode, controller: passwordController, - style: STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ), + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), obscureText: hidePassword, enableSuggestions: false, autocorrect: false, @@ -266,18 +261,17 @@ class _UnlockWalletKeysDesktopState hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 24, height: 19, ), ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), ], ), ), @@ -291,27 +285,18 @@ class _UnlockWalletKeysDesktopState ), ), ), - const SizedBox( - height: 55, - ), + const SizedBox(height: 55), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: Row( children: [ Expanded( child: SecondaryButton( label: "Cancel", - onPressed: Navigator.of( - context, - rootNavigator: true, - ).pop, + onPressed: Navigator.of(context, rootNavigator: true).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Continue", @@ -322,9 +307,7 @@ class _UnlockWalletKeysDesktopState ], ), ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart index bb8ba8089..2c31098a2 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart @@ -49,7 +49,13 @@ class WalletKeysDesktopPopup extends ConsumerWidget { final List words; final String walletId; - final ({String keys, String config})? frostData; + final ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostData; final ClipboardInterface clipboardInterface; final KeyDataInterface? keyData; @@ -66,9 +72,7 @@ class WalletKeysDesktopPopup extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( - padding: const EdgeInsets.only( - left: 32, - ), + padding: const EdgeInsets.only(left: 32), child: Text( "Wallet keys", style: STextStyles.desktopH3(context), @@ -81,28 +85,93 @@ class WalletKeysDesktopPopup extends ConsumerWidget { ), ], ), - const SizedBox( - height: 6, - ), + const SizedBox(height: 6), frostData != null ? Column( - children: [ + children: [ + Text("Keys", style: STextStyles.desktopTextMedium(context)), + const SizedBox(height: 8), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: RoundedWhiteContainer( + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 9, + ), + child: Row( + children: [ + Flexible( + child: SelectableText( + frostData!.keys, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + textAlign: TextAlign.center, + ), + ), + const SizedBox(width: 10), + IconCopyButton(data: frostData!.keys), + // TODO [prio=low: Add QR code button and dialog. + ], + ), + ), + ), + ), + const SizedBox(height: 24), + Text("Config", style: STextStyles.desktopTextMedium(context)), + const SizedBox(height: 8), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: RoundedWhiteContainer( + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 9, + ), + child: Row( + children: [ + Flexible( + child: SelectableText( + frostData!.config, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + textAlign: TextAlign.center, + ), + ), + const SizedBox(width: 10), + IconCopyButton(data: frostData!.config), + // TODO [prio=low: Add QR code button and dialog. + ], + ), + ), + ), + ), + if (frostData?.prevGen != null) const SizedBox(height: 24), + if (frostData?.prevGen != null) Text( - "Keys", + "Previous generation Keys", style: STextStyles.desktopTextMedium(context), ), - const SizedBox( - height: 8, - ), + if (frostData?.prevGen != null) const SizedBox(height: 8), + if (frostData?.prevGen != null) Center( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: RoundedWhiteContainer( - borderColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 9, @@ -118,37 +187,30 @@ class WalletKeysDesktopPopup extends ConsumerWidget { textAlign: TextAlign.center, ), ), - const SizedBox( - width: 10, - ), - IconCopyButton( - data: frostData!.keys, - ), + const SizedBox(width: 10), + IconCopyButton(data: frostData!.keys), // TODO [prio=low: Add QR code button and dialog. ], ), ), ), ), - const SizedBox( - height: 24, - ), + if (frostData?.prevGen != null) const SizedBox(height: 24), + if (frostData?.prevGen != null) Text( - "Config", + "Previous generation Config", style: STextStyles.desktopTextMedium(context), ), - const SizedBox( - height: 8, - ), + if (frostData?.prevGen != null) const SizedBox(height: 8), + if (frostData?.prevGen != null) Center( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: RoundedWhiteContainer( - borderColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 9, @@ -157,70 +219,58 @@ class WalletKeysDesktopPopup extends ConsumerWidget { children: [ Flexible( child: SelectableText( - frostData!.config, + frostData!.prevGen!.config, style: STextStyles.desktopTextExtraExtraSmall( context, ), textAlign: TextAlign.center, ), ), - const SizedBox( - width: 10, - ), - IconCopyButton( - data: frostData!.config, - ), + const SizedBox(width: 10), + IconCopyButton(data: frostData!.prevGen!.config), // TODO [prio=low: Add QR code button and dialog. ], ), ), ), ), - const SizedBox( - height: 24, - ), - ], - ) + const SizedBox(height: 24), + ], + ) : keyData != null - ? keyData is ViewOnlyWalletData - ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: ViewOnlyWalletDataWidget( - data: keyData as ViewOnlyWalletData, - ), - ) - : CustomTabView( - titles: [ - if (words.isNotEmpty) "Mnemonic", - if (keyData is XPrivData) "XPriv(s)", - if (keyData is CWKeyData) "Keys", - ], - children: [ - if (words.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 16), - child: _Mnemonic( - words: words, - ), - ), - if (keyData is XPrivData) - WalletXPrivs( - xprivData: keyData as XPrivData, - walletId: walletId, - ), - if (keyData is CWKeyData) - CNWalletKeys( - cwKeyData: keyData as CWKeyData, - walletId: walletId, - ), - ], - ) - : _Mnemonic( - words: words, + ? keyData is ViewOnlyWalletData + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ViewOnlyWalletDataWidget( + data: keyData as ViewOnlyWalletData, ), - const SizedBox( - height: 32, - ), + ) + : CustomTabView( + titles: [ + if (words.isNotEmpty) "Mnemonic", + if (keyData is XPrivData) "XPriv(s)", + if (keyData is CWKeyData) "Keys", + ], + children: [ + if (words.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 16), + child: _Mnemonic(words: words), + ), + if (keyData is XPrivData) + WalletXPrivs( + xprivData: keyData as XPrivData, + walletId: walletId, + ), + if (keyData is CWKeyData) + CNWalletKeys( + cwKeyData: keyData as CWKeyData, + walletId: walletId, + ), + ], + ) + : _Mnemonic(words: words), + const SizedBox(height: 32), ], ), ); @@ -241,18 +291,11 @@ class _Mnemonic extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - Text( - "Recovery phrase", - style: STextStyles.desktopTextMedium(context), - ), - const SizedBox( - height: 8, - ), + Text("Recovery phrase", style: STextStyles.desktopTextMedium(context)), + const SizedBox(height: 8), Center( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: Text( "Please write down your recovery phrase in the correct order and " "save it to keep your funds secure. You will also be asked to" @@ -262,13 +305,9 @@ class _Mnemonic extends StatelessWidget { ), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: MnemonicTable( words: words, isDesktop: true, @@ -276,13 +315,9 @@ class _Mnemonic extends StatelessWidget { Theme.of(context).extension()!.buttonBackSecondary, ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(horizontal: 32), child: Row( children: [ Expanded( @@ -305,9 +340,7 @@ class _Mnemonic extends StatelessWidget { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Show QR code", diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 55f6964b3..7c0f4ea13 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -2336,7 +2336,13 @@ class RouteGenerator { is ({ List mnemonic, String walletId, - ({String keys, String config})? frostData, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostData, })) { return FadePageRoute( WalletKeysDesktopPopup( @@ -2350,7 +2356,13 @@ class RouteGenerator { is ({ List mnemonic, String walletId, - ({String keys, String config})? frostData, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostData, KeyDataInterface? keyData, })) { return FadePageRoute( From f4abb1f48e4768c5b017b285f320f318f43caab7 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 May 2025 11:15:08 -0600 Subject: [PATCH 106/206] frost spend fix --- crypto_plugins/frostdart | 2 +- .../wallet/impl/bitcoin_frost_wallet.dart | 532 ++++++++---------- 2 files changed, 239 insertions(+), 295 deletions(-) diff --git a/crypto_plugins/frostdart b/crypto_plugins/frostdart index 6f1310ecc..5e8a51592 160000 --- a/crypto_plugins/frostdart +++ b/crypto_plugins/frostdart @@ -1 +1 @@ -Subproject commit 6f1310eccd336fb3c8dc00b61e39a3f0f3a2b59a +Subproject commit 5e8a51592690650e7ac63fafa81017dfc51ae6d5 diff --git a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart index 2b5173b6b..3b0c36ac0 100644 --- a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart @@ -37,12 +37,13 @@ const kFrostSecureStartingIndex = 1; class BitcoinFrostWallet extends Wallet with MultiAddressInterface { BitcoinFrostWallet(CryptoCurrencyNetwork network) - : super(BitcoinFrost(network) as T); + : super(BitcoinFrost(network) as T); - FrostWalletInfo get frostInfo => mainDB.isar.frostWalletInfo - .where() - .walletIdEqualTo(walletId) - .findFirstSync()!; + FrostWalletInfo get frostInfo => + mainDB.isar.frostWalletInfo + .where() + .walletIdEqualTo(walletId) + .findFirstSync()!; late ElectrumXClient electrumXClient; late CachedElectrumXClient electrumXCachedClient; @@ -59,11 +60,7 @@ class BitcoinFrostWallet extends Wallet Logging.instance.i("Generating new FROST wallet."); try { - final salt = frost - .multisigSalt( - multisigConfig: multisigConfig, - ) - .toHex; + final salt = frost.multisigSalt(multisigConfig: multisigConfig).toHex; final FrostWalletInfo frostWalletInfo = FrostWalletInfo( walletId: info.walletId, @@ -127,22 +124,24 @@ class BitcoinFrostWallet extends Wallet .map((e) => e.amount) .reduce((value, e) => value += e); - final utxos = await mainDB - .getUTXOs(walletId) - .filter() - .isBlockedEqualTo(false) - .findAll(); + final utxos = + await mainDB + .getUTXOs(walletId) + .filter() + .isBlockedEqualTo(false) + .findAll(); if (utxos.isEmpty) { throw Exception("No UTXOs found"); } else { final currentHeight = await chainHeight; utxos.removeWhere( - (e) => !e.isConfirmed( - currentHeight, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - ), + (e) => + !e.isConfirmed( + currentHeight, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + ), ); if (utxos.isEmpty) { throw Exception("No confirmed UTXOs found"); @@ -174,32 +173,32 @@ class BitcoinFrostWallet extends Wallet } } - final int network = cryptoCurrency.network == CryptoCurrencyNetwork.main - ? Network.Mainnet - : Network.Testnet; + final int network = + cryptoCurrency.network == CryptoCurrencyNetwork.main + ? Network.Mainnet + : Network.Testnet; final List< - ({ - UTXO utxo, - Uint8List scriptPubKey, - ({int account, int index, bool change}) addressDerivationData - })> inputs = []; + ({ + UTXO utxo, + Uint8List scriptPubKey, + ({int account, int index, bool change, bool secure}) + addressDerivationData, + }) + > + inputs = []; for (final utxo in utxosToUse) { - final dData = await getDerivationData( - utxo.address, - ); + final dData = await getDerivationData(utxo.address); final publicKey = cryptoCurrency.addressToPubkey( address: utxo.address!, ); - inputs.add( - ( - utxo: utxo, - scriptPubKey: publicKey, - addressDerivationData: dData, - ), - ); + inputs.add(( + utxo: utxo, + scriptPubKey: publicKey, + addressDerivationData: dData, + )); } await checkChangeAddressForTransactions(); final changeAddress = await getCurrentChangeAddress(); @@ -221,19 +220,15 @@ class BitcoinFrostWallet extends Wallet utxosRemaining.isNotEmpty) { // add extra utxo final utxo = utxosRemaining.take(1).first; - final dData = await getDerivationData( - utxo.address, - ); + final dData = await getDerivationData(utxo.address); final publicKey = cryptoCurrency.addressToPubkey( address: utxo.address!, ); - inputs.add( - ( - utxo: utxo, - scriptPubKey: publicKey, - addressDerivationData: dData, - ), - ); + inputs.add(( + utxo: utxo, + scriptPubKey: publicKey, + addressDerivationData: dData, + )); } else { rethrow; } @@ -246,9 +241,8 @@ class BitcoinFrostWallet extends Wallet } } - Future<({int account, int index, bool change})> getDerivationData( - String? address, - ) async { + Future<({int account, int index, bool change, bool secure})> + getDerivationData(String? address) async { if (address == null) { throw Exception("Missing address required for FROST signing"); } @@ -269,15 +263,14 @@ class BitcoinFrostWallet extends Wallet ); } if (components[1] != 0 && components[1] != 1) { - throw Exception( - "${components[1]} must be 1 or 0 for change", - ); + throw Exception("${components[1]} must be 1 or 0 for change"); } return ( account: components[0], change: components[1] == 1, index: components[2], + secure: addr.zSafeFrost ?? false, ); } catch (_) { rethrow; @@ -285,15 +278,13 @@ class BitcoinFrostWallet extends Wallet } Future< - ({ - Pointer machinePtr, - String preprocess, - })> frostAttemptSignConfig({ - required String config, - }) async { - final int network = cryptoCurrency.network == CryptoCurrencyNetwork.main - ? Network.Mainnet - : Network.Testnet; + ({Pointer machinePtr, String preprocess}) + > + frostAttemptSignConfig({required String config}) async { + final int network = + cryptoCurrency.network == CryptoCurrencyNetwork.main + ? Network.Mainnet + : Network.Testnet; final serializedKeys = await getSerializedKeys(); return Frost.attemptSignConfig( @@ -312,17 +303,13 @@ class BitcoinFrostWallet extends Wallet await _saveMultisigConfig(multisigConfig); await _updateThreshold( - frost.getThresholdFromKeys( - serializedKeys: serializedKeys, - ), + frost.getThresholdFromKeys(serializedKeys: serializedKeys), ); final myNameIndex = frost.getParticipantIndexFromKeys( serializedKeys: serializedKeys, ); - final participants = Frost.getParticipants( - multisigConfig: multisigConfig, - ); + final participants = Frost.getParticipants(multisigConfig: multisigConfig); final myName = participants[myNameIndex]; await _updateParticipants(participants); @@ -367,7 +354,11 @@ class BitcoinFrostWallet extends Wallet // return vSize * (feeRatePerKB / 1000).ceil(); // } - Amount _roughFeeEstimate(int inputCount, int outputCount, BigInt feeRatePerKB) { + Amount _roughFeeEstimate( + int inputCount, + int outputCount, + BigInt feeRatePerKB, + ) { return Amount( rawValue: BigInt.from( ((42 + (272 * inputCount) + (128 * outputCount)) / 4).ceil() * @@ -386,48 +377,26 @@ class BitcoinFrostWallet extends Wallet int get isarTransactionVersion => 2; @override - FilterOperation? get changeAddressFilterOperation => FilterGroup.and( - [ - FilterCondition.equalTo( - property: r"type", - value: info.mainAddressType, - ), - const FilterCondition.equalTo( - property: r"subType", - value: AddressSubType.change, - ), - const FilterCondition.equalTo( - property: r"zSafeFrost", - value: true, - ), - const FilterCondition.greaterThan( - property: r"derivationIndex", - value: 0, - ), - ], - ); + FilterOperation? get changeAddressFilterOperation => FilterGroup.and([ + FilterCondition.equalTo(property: r"type", value: info.mainAddressType), + const FilterCondition.equalTo( + property: r"subType", + value: AddressSubType.change, + ), + const FilterCondition.equalTo(property: r"zSafeFrost", value: true), + const FilterCondition.greaterThan(property: r"derivationIndex", value: 0), + ]); @override - FilterOperation? get receivingAddressFilterOperation => FilterGroup.and( - [ - FilterCondition.equalTo( - property: r"type", - value: info.mainAddressType, - ), - const FilterCondition.equalTo( - property: r"subType", - value: AddressSubType.receiving, - ), - const FilterCondition.equalTo( - property: r"zSafeFrost", - value: true, - ), - const FilterCondition.greaterThan( - property: r"derivationIndex", - value: 0, - ), - ], - ); + FilterOperation? get receivingAddressFilterOperation => FilterGroup.and([ + FilterCondition.equalTo(property: r"type", value: info.mainAddressType), + const FilterCondition.equalTo( + property: r"subType", + value: AddressSubType.receiving, + ), + const FilterCondition.equalTo(property: r"zSafeFrost", value: true), + const FilterCondition.greaterThan(property: r"derivationIndex", value: 0), + ]); @override Future updateTransactions() async { @@ -436,14 +405,16 @@ class BitcoinFrostWallet extends Wallet await _fetchAddressesForElectrumXScan(); // Separate receiving and change addresses. - final Set receivingAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - final Set changeAddresses = allAddressesOld - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); + final Set receivingAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + final Set changeAddresses = + allAddressesOld + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); // Remove duplicates. final allAddressesSet = {...receivingAddresses, ...changeAddresses}; @@ -451,18 +422,20 @@ class BitcoinFrostWallet extends Wallet final currentHeight = await chainHeight; // Fetch history from ElectrumX. - final List> allTxHashes = - await _fetchHistory(allAddressesSet); + final List> allTxHashes = await _fetchHistory( + allAddressesSet, + ); final List> allTransactions = []; for (final txHash in allTxHashes) { - final storedTx = await mainDB.isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .filter() - .txidEqualTo(txHash["tx_hash"] as String) - .findFirst(); + final storedTx = + await mainDB.isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(txHash["tx_hash"] as String) + .findFirst(); if (storedTx == null || !storedTx.isConfirmed( @@ -590,8 +563,9 @@ class BitcoinFrostWallet extends Wallet TransactionSubType subType = TransactionSubType.none; if (outputs.length > 1 && inputs.isNotEmpty) { for (int i = 0; i < outputs.length; i++) { - final List? scriptChunks = - outputs[i].scriptPubKeyAsm?.split(" "); + final List? scriptChunks = outputs[i].scriptPubKeyAsm?.split( + " ", + ); if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") { final blindedPaymentCode = scriptChunks![1]; final bytes = blindedPaymentCode.toUint8ListFromHex; @@ -635,7 +609,8 @@ class BitcoinFrostWallet extends Wallet txid: txData["txid"] as String, height: txData["height"] as int?, version: txData["version"] as int, - timestamp: txData["blocktime"] as int? ?? + timestamp: + txData["blocktime"] as int? ?? DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, inputs: List.unmodifiable(inputs), outputs: List.unmodifiable(outputs), @@ -698,9 +673,7 @@ class BitcoinFrostWallet extends Wallet final hex = txData.raw!; final txHash = await electrumXClient.broadcastTransaction(rawTx: hex); - Logging.instance.d( - "Sent txHash: $txHash", - ); + Logging.instance.d("Sent txHash: $txHash"); // mark utxos as used final usedUTXOs = txData.utxos!.map((e) => e.copyWith(used: true)); @@ -787,18 +760,21 @@ class BitcoinFrostWallet extends Wallet numberOfBlocksFast: f, numberOfBlocksAverage: m, numberOfBlocksSlow: s, - fast: Amount.fromDecimal( - fast, - fractionDigits: cryptoCurrency.fractionDigits, - ).raw, - medium: Amount.fromDecimal( - medium, - fractionDigits: cryptoCurrency.fractionDigits, - ).raw, - slow: Amount.fromDecimal( - slow, - fractionDigits: cryptoCurrency.fractionDigits, - ).raw, + fast: + Amount.fromDecimal( + fast, + fractionDigits: cryptoCurrency.fractionDigits, + ).raw, + medium: + Amount.fromDecimal( + medium, + fractionDigits: cryptoCurrency.fractionDigits, + ).raw, + slow: + Amount.fromDecimal( + slow, + fractionDigits: cryptoCurrency.fractionDigits, + ).raw, ); Logging.instance.i("fetched fees: $feeObject"); @@ -839,21 +815,14 @@ class BitcoinFrostWallet extends Wallet final coin = info.coin; GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.syncing, - walletId, - coin, - ), + WalletSyncStatusChangedEvent(WalletSyncStatus.syncing, walletId, coin), ); try { await refreshMutex.protect(() async { if (!isRescan) { - final salt = frost - .multisigSalt( - multisigConfig: multisigConfig!, - ) - .toHex; + final salt = + frost.multisigSalt(multisigConfig: multisigConfig!).toHex; final knownSalts = _getKnownSalts(); if (knownSalts.contains(salt)) { throw Exception("Known frost multisig salt found!"); @@ -875,20 +844,12 @@ class BitcoinFrostWallet extends Wallet const receiveChain = 0; const changeChain = 1; final List addresses})>> - receiveFutures = [ - _checkGapsLinearly( - serializedKeys, - receiveChain, - secure: true, - ), + receiveFutures = [ + _checkGapsLinearly(serializedKeys, receiveChain, secure: true), ]; final List addresses})>> - changeFutures = [ - _checkGapsLinearly( - serializedKeys, - changeChain, - secure: true, - ), + changeFutures = [ + _checkGapsLinearly(serializedKeys, changeChain, secure: true), ]; // io limitations may require running these linearly instead @@ -949,17 +910,16 @@ class BitcoinFrostWallet extends Wallet }); GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.synced, - walletId, - coin, - ), + WalletSyncStatusChangedEvent(WalletSyncStatus.synced, walletId, coin), ); unawaited(refresh()); } catch (e, s) { - Logging.instance - .f("recoverFromSerializedKeys failed: ", error: e, stackTrace: s); + Logging.instance.f( + "recoverFromSerializedKeys failed: ", + error: e, + stackTrace: s, + ); GlobalEventBus.instance.fire( WalletSyncStatusChangedEvent( WalletSyncStatus.unableToSync, @@ -978,21 +938,11 @@ class BitcoinFrostWallet extends Wallet const changeChain = 1; final List addresses})>> receiveFutures = - [ - _checkGapsLinearly( - serializedKeys, - receiveChain, - secure: false, - ), - ]; + [_checkGapsLinearly(serializedKeys, receiveChain, secure: false)]; final List addresses})>> changeFutures = [ // for legacy support secure is set to false to see // funds received on insecure addresses - _checkGapsLinearly( - serializedKeys, - changeChain, - secure: false, - ), + _checkGapsLinearly(serializedKeys, changeChain, secure: false), ]; // io limitations may require running these linearly instead @@ -1111,10 +1061,7 @@ class BitcoinFrostWallet extends Wallet rethrow; } - await info.updateCachedChainHeight( - newHeight: height, - isar: mainDB.isar, - ); + await info.updateCachedChainHeight(newHeight: height, isar: mainDB.isar); } @override @@ -1153,9 +1100,7 @@ class BitcoinFrostWallet extends Wallet for (int i = 0; i < fetchedUtxoList.length; i++) { for (int j = 0; j < fetchedUtxoList[i].length; j++) { - final utxo = await _parseUTXO( - jsonUTXO: fetchedUtxoList[i][j], - ); + final utxo = await _parseUTXO(jsonUTXO: fetchedUtxoList[i][j]); outputArray.add(utxo); } @@ -1163,8 +1108,11 @@ class BitcoinFrostWallet extends Wallet return await mainDB.updateUTXOs(walletId, outputArray); } catch (e, s) { - Logging.instance - .e("Output fetch unsuccessful: ", error: e, stackTrace: s); + Logging.instance.e( + "Output fetch unsuccessful: ", + error: e, + stackTrace: s, + ); return false; } } @@ -1172,13 +1120,9 @@ class BitcoinFrostWallet extends Wallet // =================== Secure storage ======================================== Future getSerializedKeys() async => - await secureStorageInterface.read( - key: "{$walletId}_serializedFROSTKeys", - ); + await secureStorageInterface.read(key: "{$walletId}_serializedFROSTKeys"); - Future _saveSerializedKeys( - String keys, - ) async { + Future _saveSerializedKeys(String keys) async { final current = await getSerializedKeys(); if (current == null) { @@ -1205,18 +1149,14 @@ class BitcoinFrostWallet extends Wallet ); Future getMultisigConfig() async => - await secureStorageInterface.read( - key: "{$walletId}_multisigConfig", - ); + await secureStorageInterface.read(key: "{$walletId}_multisigConfig"); Future getMultisigConfigPrevGen() async => await secureStorageInterface.read( key: "{$walletId}_multisigConfigPrevGen", ); - Future _saveMultisigConfig( - String multisigConfig, - ) async { + Future _saveMultisigConfig(String multisigConfig) async { final current = await getMultisigConfig(); if (current == null) { @@ -1248,21 +1188,16 @@ class BitcoinFrostWallet extends Wallet } } - Future _saveMultisigId( - Uint8List id, - ) async => + Future _saveMultisigId(Uint8List id) async => await secureStorageInterface.write( key: "{$walletId}_multisigIdFROST", value: id.toHex, ); - Future _recoveryString() async => await secureStorageInterface.read( - key: "{$walletId}_recoveryStringFROST", - ); + Future _recoveryString() async => + await secureStorageInterface.read(key: "{$walletId}_recoveryStringFROST"); - Future _saveRecoveryString( - String recoveryString, - ) async => + Future _saveRecoveryString(String recoveryString) async => await secureStorageInterface.write( key: "{$walletId}_recoveryStringFROST", value: recoveryString, @@ -1270,11 +1205,12 @@ class BitcoinFrostWallet extends Wallet // =================== DB ==================================================== - List _getKnownSalts() => mainDB.isar.frostWalletInfo - .where() - .walletIdEqualTo(walletId) - .knownSaltsProperty() - .findFirstSync()!; + List _getKnownSalts() => + mainDB.isar.frostWalletInfo + .where() + .walletIdEqualTo(walletId) + .knownSaltsProperty() + .findFirstSync()!; Future _updateKnownSalts(List knownSalts) async { final info = frostInfo; @@ -1287,11 +1223,12 @@ class BitcoinFrostWallet extends Wallet }); } - List _getParticipants() => mainDB.isar.frostWalletInfo - .where() - .walletIdEqualTo(walletId) - .participantsProperty() - .findFirstSync()!; + List _getParticipants() => + mainDB.isar.frostWalletInfo + .where() + .walletIdEqualTo(walletId) + .participantsProperty() + .findFirstSync()!; Future _updateParticipants(List participants) async { final info = frostInfo; @@ -1304,11 +1241,12 @@ class BitcoinFrostWallet extends Wallet }); } - int _getThreshold() => mainDB.isar.frostWalletInfo - .where() - .walletIdEqualTo(walletId) - .thresholdProperty() - .findFirstSync()!; + int _getThreshold() => + mainDB.isar.frostWalletInfo + .where() + .walletIdEqualTo(walletId) + .thresholdProperty() + .findFirstSync()!; Future _updateThreshold(int threshold) async { final info = frostInfo; @@ -1321,20 +1259,19 @@ class BitcoinFrostWallet extends Wallet }); } - String _getMyName() => mainDB.isar.frostWalletInfo - .where() - .walletIdEqualTo(walletId) - .myNameProperty() - .findFirstSync()!; + String _getMyName() => + mainDB.isar.frostWalletInfo + .where() + .walletIdEqualTo(walletId) + .myNameProperty() + .findFirstSync()!; Future _updateMyName(String myName) async { final info = frostInfo; await mainDB.isar.writeTxn(() async { await mainDB.isar.frostWalletInfo.delete(info.id); - await mainDB.isar.frostWalletInfo.put( - info.copyWith(myName: myName), - ); + await mainDB.isar.frostWalletInfo.put(info.copyWith(myName: myName)); }); } @@ -1356,20 +1293,21 @@ class BitcoinFrostWallet extends Wallet // TODO [prio=low]: Use ElectrumXInterface method. Future _updateElectrumX() async { - final failovers = nodeService - .failoverNodesFor(currency: cryptoCurrency) - .map( - (e) => ElectrumXNode( - address: e.host, - port: e.port, - name: e.name, - id: e.id, - useSSL: e.useSSL, - torEnabled: e.torEnabled, - clearnetEnabled: e.clearnetEnabled, - ), - ) - .toList(); + final failovers = + nodeService + .failoverNodesFor(currency: cryptoCurrency) + .map( + (e) => ElectrumXNode( + address: e.host, + port: e.port, + name: e.name, + id: e.id, + useSSL: e.useSSL, + torEnabled: e.torEnabled, + clearnetEnabled: e.clearnetEnabled, + ), + ) + .toList(); final newNode = await _getCurrentElectrumXNode(); try { @@ -1409,9 +1347,7 @@ class BitcoinFrostWallet extends Wallet return false; } - Future _parseUTXO({ - required Map jsonUTXO, - }) async { + Future _parseUTXO({required Map jsonUTXO}) async { final txn = await electrumXCachedClient.getTransaction( txHash: jsonUTXO["tx_hash"] as String, verbose: true, @@ -1430,7 +1366,7 @@ class BitcoinFrostWallet extends Wallet // scriptPubKey = output["scriptPubKey"]?["hex"] as String?; utxoOwnerAddress = output["scriptPubKey"]?["addresses"]?[0] as String? ?? - output["scriptPubKey"]?["address"] as String?; + output["scriptPubKey"]?["address"] as String?; } } @@ -1476,9 +1412,10 @@ class BitcoinFrostWallet extends Wallet await checkChangeAddressForTransactions(); } } catch (e, s) { - Logging.instance - .i("Exception rethrown from _checkChangeAddressForTransactions" - "($cryptoCurrency): $e\n$s"); + Logging.instance.i( + "Exception rethrown from _checkChangeAddressForTransactions" + "($cryptoCurrency): $e\n$s", + ); rethrow; } } @@ -1534,9 +1471,10 @@ class BitcoinFrostWallet extends Wallet @override Future generateNewChangeAddress() async { final current = await getCurrentChangeAddress(); - int index = current == null - ? kFrostSecureStartingIndex - : current.derivationIndex + 1; + int index = + current == null + ? kFrostSecureStartingIndex + : current.derivationIndex + 1; const chain = 1; // change address final serializedKeys = (await getSerializedKeys())!; @@ -1567,9 +1505,10 @@ class BitcoinFrostWallet extends Wallet @override Future generateNewReceivingAddress() async { final current = await getCurrentReceivingAddress(); - int index = current == null - ? kFrostSecureStartingIndex - : current.derivationIndex + 1; + int index = + current == null + ? kFrostSecureStartingIndex + : current.derivationIndex + 1; const chain = 0; // receiving address final serializedKeys = (await getSerializedKeys())!; @@ -1649,8 +1588,9 @@ class BitcoinFrostWallet extends Wallet } } - nextReceivingAddresses - .removeWhere((e) => e.derivationIndex > activeReceiveIndex); + nextReceivingAddresses.removeWhere( + (e) => e.derivationIndex > activeReceiveIndex, + ); if (nextReceivingAddresses.isNotEmpty) { await mainDB.updateOrPutAddresses(nextReceivingAddresses); await info.updateReceivingAddress( @@ -1658,8 +1598,9 @@ class BitcoinFrostWallet extends Wallet isar: mainDB.isar, ); } - nextChangeAddresses - .removeWhere((e) => e.derivationIndex > activeChangeIndex); + nextChangeAddresses.removeWhere( + (e) => e.derivationIndex > activeChangeIndex, + ); if (nextChangeAddresses.isNotEmpty) { await mainDB.updateOrPutAddresses(nextChangeAddresses); } @@ -1707,14 +1648,16 @@ class BitcoinFrostWallet extends Wallet account: account, change: change == 1, index: index, + secure: secure, ); final keys = frost.deserializeKeys(keys: serializedKeys); final addressString = frost.addressForKeys( - network: cryptoCurrency.network == CryptoCurrencyNetwork.main - ? Network.Mainnet - : Network.Testnet, + network: + cryptoCurrency.network == CryptoCurrencyNetwork.main + ? Network.Mainnet + : Network.Testnet, keys: keys, addressDerivationData: addressDerivationData, secure: secure, @@ -1726,9 +1669,10 @@ class BitcoinFrostWallet extends Wallet publicKey: cryptoCurrency.addressToPubkey(address: addressString), derivationIndex: index, derivationPath: DerivationPath()..value = "$account/$change/$index", - subType: change == 0 - ? AddressSubType.receiving - : change == 1 + subType: + change == 0 + ? AddressSubType.receiving + : change == 1 ? AddressSubType.change : AddressSubType.unknown, type: AddressType.frostMS, @@ -1770,9 +1714,7 @@ class BitcoinFrostWallet extends Wallet } // get address tx count - final count = await _fetchTxCount( - address: address, - ); + final count = await _fetchTxCount(address: address); // check and add appropriate addresses if (count > 0) { @@ -1792,25 +1734,24 @@ class BitcoinFrostWallet extends Wallet Future _fetchTxCount({required Address address}) async { final transactions = await electrumXClient.getHistory( - scripthash: cryptoCurrency.addressToScriptHash( - address: address.value, - ), + scripthash: cryptoCurrency.addressToScriptHash(address: address.value), ); return transactions.length; } Future> _fetchAddressesForElectrumXScan() async { - final allAddresses = await mainDB - .getAddresses(walletId) - .filter() - .not() - .group( - (q) => q - .typeEqualTo(AddressType.nonWallet) - .or() - .subTypeEqualTo(AddressSubType.nonWallet), - ) - .findAll(); + final allAddresses = + await mainDB + .getAddresses(walletId) + .filter() + .not() + .group( + (q) => q + .typeEqualTo(AddressType.nonWallet) + .or() + .subTypeEqualTo(AddressSubType.nonWallet), + ) + .findAll(); return allAddresses; } @@ -1839,8 +1780,11 @@ class BitcoinFrostWallet extends Wallet return allTxHashes; } catch (e, s) { - Logging.instance - .e("$runtimeType._fetchHistory: ", error: e, stackTrace: s); + Logging.instance.e( + "$runtimeType._fetchHistory: ", + error: e, + stackTrace: s, + ); rethrow; } } From b28d18164f3ffbf4831654ef5f94a08a7697cda5 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 May 2025 15:09:27 -0600 Subject: [PATCH 107/206] fix optional date --- lib/models/exchange/change_now/cn_exchange_transaction.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/models/exchange/change_now/cn_exchange_transaction.dart b/lib/models/exchange/change_now/cn_exchange_transaction.dart index 5063df995..bd904f8f5 100644 --- a/lib/models/exchange/change_now/cn_exchange_transaction.dart +++ b/lib/models/exchange/change_now/cn_exchange_transaction.dart @@ -48,7 +48,7 @@ class CNExchangeTransaction { final String refundExtraId; /// Deadline until which the estimated rate or transaction is valid. - final DateTime validUntil; + final DateTime? validUntil; /// Date when transaction was created. final DateTime date; @@ -104,7 +104,7 @@ class CNExchangeTransaction { toCurrency: json["toCurrency"] as String, refundAddress: json["refundAddress"] as String, refundExtraId: json["refundExtraId"] as String, - validUntil: DateTime.parse(json["validUntil"] as String), + validUntil: DateTime.tryParse(json["validUntil"] as String? ?? ""), date: DateTime.parse(json["date"] as String), id: json["id"] as String, directedAmount: Decimal.tryParse(json["directedAmount"].toString()), @@ -133,7 +133,7 @@ class CNExchangeTransaction { "toCurrency": toCurrency, "refundAddress": refundAddress, "refundExtraId": refundExtraId, - "validUntil": validUntil.toIso8601String(), + "validUntil": validUntil?.toIso8601String(), "date": date.toIso8601String(), "id": id, "directedAmount": directedAmount, From 877ef21e6e307a1615a303061b1476e704d6e0d8 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 May 2025 15:26:34 -0600 Subject: [PATCH 108/206] fix duress favorites --- .../providers/favourite_wallets_provider.dart | 70 +++++++++++-------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/lib/wallets/isar/providers/favourite_wallets_provider.dart b/lib/wallets/isar/providers/favourite_wallets_provider.dart index 1f7eb798e..8a0b2c0ef 100644 --- a/lib/wallets/isar/providers/favourite_wallets_provider.dart +++ b/lib/wallets/isar/providers/favourite_wallets_provider.dart @@ -3,8 +3,10 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; -import '../../../providers/db/main_db_provider.dart'; + import '../../../app_config.dart'; +import '../../../providers/db/main_db_provider.dart'; +import '../../../providers/global/duress_provider.dart'; import '../../crypto_currency/crypto_currency.dart'; import '../models/wallet_info.dart'; @@ -27,9 +29,9 @@ class _Watcher extends ChangeNotifier { .sortByFavouriteOrderIndex() .watch(fireImmediately: true) .listen((event) { - _value = event; - notifyListeners(); - }); + _value = event; + notifyListeners(); + }); } @override @@ -39,32 +41,42 @@ class _Watcher extends ChangeNotifier { } } -final _wiProvider = ChangeNotifierProvider.family<_Watcher, bool>( - (ref, isFavourite) { - final isar = ref.watch(mainDBProvider).isar; +final _wiProvider = ChangeNotifierProvider.family<_Watcher, bool>(( + ref, + isFavourite, +) { + final isar = ref.watch(mainDBProvider).isar; + + final watcher = _Watcher( + isar.walletInfo + .filter() + .anyOf( + AppConfig.coins.map((e) => e.identifier), + (q, element) => q.coinNameMatches(element), + ) + .isFavouriteEqualTo(isFavourite) + .sortByFavouriteOrderIndex() + .findAllSync(), + isFavourite, + isar, + ); + + ref.onDispose(() => watcher.dispose()); + + return watcher; +}); - final watcher = _Watcher( - isar.walletInfo - .filter() - .anyOf( - AppConfig.coins.map((e) => e.identifier), - (q, element) => q.coinNameMatches(element), - ) - .isFavouriteEqualTo(isFavourite) - .sortByFavouriteOrderIndex() - .findAllSync(), - isFavourite, - isar, - ); +final pFavouriteWalletInfos = Provider.family, bool>(( + ref, + isFavourite, +) { + final isDuress = ref.watch(pDuress); - ref.onDispose(() => watcher.dispose()); + final infos = ref.watch(_wiProvider(isFavourite)).value; - return watcher; - }, -); + if (isDuress) { + infos.retainWhere((e) => e.isDuressVisible); + } -final pFavouriteWalletInfos = Provider.family, bool>( - (ref, isFavourite) { - return ref.watch(_wiProvider(isFavourite)).value; - }, -); + return infos; +}); From 59621d6098fc04bef0a1a37969e4f864a4ecd5a9 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 May 2025 18:14:33 -0600 Subject: [PATCH 109/206] demo --- .../wallet/intermediate/lib_monero_wallet.dart | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index b81a10d97..9e2661311 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -478,9 +478,16 @@ abstract class LibMoneroWallet }); } + // dumb temporary hack + bool _canPing = false; + @override Future pingCheck() async { - return (await libMoneroWallet?.isConnectedToDaemon()) ?? false; + if (_canPing) { + return (await libMoneroWallet?.isConnectedToDaemon()) ?? false; + } else { + return false; + } } @override @@ -490,8 +497,10 @@ abstract class LibMoneroWallet final host = node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; ({InternetAddress host, int port})? proxy; + _canPing = true; if (prefs.useTor) { if (node.clearnetEnabled && !node.torEnabled) { + _canPing = false; libMoneroWallet?.stopAutoSaving(); libMoneroWallet?.stopListeners(); libMoneroWallet?.stopSyncing(); @@ -501,6 +510,7 @@ abstract class LibMoneroWallet proxy = TorService.sharedInstance.getProxyInfo(); } else { if (!node.clearnetEnabled && node.torEnabled) { + _canPing = false; libMoneroWallet?.stopAutoSaving(); libMoneroWallet?.stopListeners(); libMoneroWallet?.stopSyncing(); @@ -1087,8 +1097,10 @@ abstract class LibMoneroWallet final node = getCurrentNode(); + _canPing = true; if (prefs.useTor) { if (node.clearnetEnabled && !node.torEnabled) { + _canPing = false; libMoneroWallet?.stopAutoSaving(); libMoneroWallet?.stopListeners(); libMoneroWallet?.stopSyncing(); @@ -1097,6 +1109,7 @@ abstract class LibMoneroWallet } } else { if (!node.clearnetEnabled && node.torEnabled) { + _canPing = false; libMoneroWallet?.stopAutoSaving(); libMoneroWallet?.stopListeners(); libMoneroWallet?.stopSyncing(); From 5bdc7d03feecd5faa20674afe9efac0ab1765d3d Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 31 May 2025 17:50:20 -0600 Subject: [PATCH 110/206] update cs_salvium dep with ios plist fix --- pubspec.lock | 20 +++++++++---------- scripts/app_config/templates/pubspec.template | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 7c3844799..c5dda1160 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -540,18 +540,18 @@ packages: dependency: "direct main" description: name: cs_salvium - sha256: e25976e874dcf6bf4e4330b541b1028cffe8bacfffbcc51ab106f76c6686a56d + sha256: "5711a9b547e9e5ba1d91e1c6b37ba94803b0b7c6ef56baf245b270e2a637b839" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" cs_salvium_flutter_libs: dependency: "direct main" description: name: cs_salvium_flutter_libs - sha256: "4ab42fb499de4749e30de5cd4155aaaa44239229ec30a5c4ce661c6a2964ea96" + sha256: cb2759e3d0829251cb13daa9e012f7821d9717ec1f1dedc9329c4012f99f386c url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" cs_salvium_flutter_libs_android: dependency: transitive description: @@ -588,18 +588,18 @@ packages: dependency: transitive description: name: cs_salvium_flutter_libs_ios - sha256: "6e57590b054f420c79549d7059edfeca55e38cea19e34cf94fcf9fbd3de53d8b" + sha256: "4c11cc7499ca7d3a8c0f2b29fcb4eaf4cd1475c5752f34856a3d4c0b721a6319" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" cs_salvium_flutter_libs_linux: dependency: transitive description: name: cs_salvium_flutter_libs_linux - sha256: ed24070da5c4bad5fd2f76c003a45a7378389d382b919cfa1ee88fad25d07fe3 + sha256: "0cb2f545ea4aa45c819a0656540d022a9c73a43681e50f1d2a5e72eaf1bc500e" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" cs_salvium_flutter_libs_macos: dependency: transitive description: @@ -620,10 +620,10 @@ packages: dependency: transitive description: name: cs_salvium_flutter_libs_windows - sha256: "3cef0c1320ecc55afecbe5d0a97b9447d033d5994a2ebf93df64d0558e582daf" + sha256: "824966223a32bfe4d99c634d3b8d81917806d06ad878007552597e2070c25a02" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" csslib: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 6a8c1f552..e70887c87 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -218,8 +218,8 @@ dependencies: drift: ^2.22.1 drift_flutter: ^0.2.3 path: ^1.9.1 - cs_salvium: ^1.1.0 - cs_salvium_flutter_libs: ^1.0.1 + cs_salvium: ^1.2.0 + cs_salvium_flutter_libs: ^1.0.2 dev_dependencies: flutter_test: From 4ebf972e4008f27f27d4dd19d921023cae6094b2 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 07:16:13 -0600 Subject: [PATCH 111/206] 8 places + polyseed --- lib/wallets/crypto_currency/coins/salvium.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/wallets/crypto_currency/coins/salvium.dart b/lib/wallets/crypto_currency/coins/salvium.dart index fe4d8f64d..1bbe599a3 100644 --- a/lib/wallets/crypto_currency/coins/salvium.dart +++ b/lib/wallets/crypto_currency/coins/salvium.dart @@ -88,7 +88,7 @@ class Salvium extends CryptonoteCurrency { int get defaultSeedPhraseLength => 25; @override - int get fractionDigits => 12; + int get fractionDigits => 8; @override bool get hasBuySupport => false; @@ -100,13 +100,14 @@ class Salvium extends CryptonoteCurrency { List get possibleMnemonicLengths => [defaultSeedPhraseLength]; @override - BigInt get satsPerCoin => BigInt.from(1000000000000); + BigInt get satsPerCoin => BigInt.from(100000000); @override int get targetBlockTimeSeconds => 120; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); From 0f32556f095f48fff24ec64dcbee90d151b4ba75 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 10:03:30 -0600 Subject: [PATCH 112/206] primary node flag --- lib/models/node_model.dart | 6 ++++++ lib/models/type_adaptors/node_model.g.dart | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/models/node_model.dart b/lib/models/node_model.dart index 530c2a0c2..1224d7e5b 100644 --- a/lib/models/node_model.dart +++ b/lib/models/node_model.dart @@ -45,6 +45,8 @@ class NodeModel { final bool clearnetEnabled; // @HiveField(13) final bool forceNoTor; + // @HiveField(14) + final bool isPrimary; NodeModel({ required this.host, @@ -58,6 +60,7 @@ class NodeModel { required this.isDown, required this.torEnabled, required this.clearnetEnabled, + required this.isPrimary, this.forceNoTor = false, this.loginName, this.trusted, @@ -77,6 +80,7 @@ class NodeModel { bool? torEnabled, bool? forceNoTor, bool? clearnetEnabled, + bool? isPrimary, }) { return NodeModel( host: host ?? this.host, @@ -93,6 +97,7 @@ class NodeModel { torEnabled: torEnabled ?? this.torEnabled, clearnetEnabled: clearnetEnabled ?? this.clearnetEnabled, forceNoTor: forceNoTor ?? this.forceNoTor, + isPrimary: isPrimary ?? this.isPrimary, ); } @@ -117,6 +122,7 @@ class NodeModel { map['torEnabled'] = torEnabled; map['clearEnabled'] = clearnetEnabled; map['forceNoTor'] = forceNoTor; + map['isPrimary'] = isPrimary; return map; } diff --git a/lib/models/type_adaptors/node_model.g.dart b/lib/models/type_adaptors/node_model.g.dart index 381091edd..218731a69 100644 --- a/lib/models/type_adaptors/node_model.g.dart +++ b/lib/models/type_adaptors/node_model.g.dart @@ -31,13 +31,14 @@ class NodeModelAdapter extends TypeAdapter { torEnabled: fields[11] as bool? ?? true, clearnetEnabled: fields[12] as bool? ?? true, forceNoTor: fields[13] as bool? ?? false, + isPrimary: fields[14] as bool? ?? false, ); } @override void write(BinaryWriter writer, NodeModel obj) { writer - ..writeByte(14) + ..writeByte(15) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -65,7 +66,9 @@ class NodeModelAdapter extends TypeAdapter { ..writeByte(12) ..write(obj.clearnetEnabled) ..writeByte(13) - ..write(obj.forceNoTor); + ..write(obj.forceNoTor) + ..writeByte(14) + ..write(obj.isPrimary); } @override From 0f54f975f11b2e3de7f4dbbc1c2269d83210178f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 10:13:54 -0600 Subject: [PATCH 113/206] WIP remove store primary nodes separately. Still requires SWB changes as well as a db migration with version update --- lib/services/node_service.dart | 100 +++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 41 deletions(-) diff --git a/lib/services/node_service.dart b/lib/services/node_service.dart index 35f595050..1657cfa78 100644 --- a/lib/services/node_service.dart +++ b/lib/services/node_service.dart @@ -27,9 +27,7 @@ class NodeService extends ChangeNotifier { final SecureStorageInterface secureStorageInterface; /// Exposed [secureStorageInterface] in order to inject mock for tests - NodeService({ - required this.secureStorageInterface, - }); + NodeService({required this.secureStorageInterface}); Future updateDefaults() async { // hack @@ -64,6 +62,7 @@ class NodeService extends ChangeNotifier { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: false, ); await DB.instance.put( @@ -75,17 +74,15 @@ class NodeService extends ChangeNotifier { } } - for (final defaultNode in AppConfig.coins.map( - (e) => e.defaultNode, - )) { - final savedNode = DB.instance - .get(boxName: DB.boxNameNodeModels, key: defaultNode.id); + for (final defaultNode in AppConfig.coins.map((e) => e.defaultNode)) { + final savedNode = DB.instance.get( + boxName: DB.boxNameNodeModels, + key: defaultNode.id, + ); if (savedNode == null) { // save the default node to hive only if no other nodes for the specific coin exist if (getNodesFor( - AppConfig.getCryptoCurrencyByPrettyName( - defaultNode.coinName, - ), + AppConfig.getCryptoCurrencyByPrettyName(defaultNode.coinName), ).isEmpty) { await DB.instance.put( boxName: DB.boxNameNodeModels, @@ -111,8 +108,9 @@ class NodeService extends ChangeNotifier { // check if a default node is the primary node for the crypto currency // and update it if needed - final coin = - AppConfig.getCryptoCurrencyByPrettyName(defaultNode.coinName); + final coin = AppConfig.getCryptoCurrencyByPrettyName( + defaultNode.coinName, + ); final primaryNode = getPrimaryNodeFor(currency: coin); if (primaryNode != null && primaryNode.id == defaultNode.id) { await setPrimaryNodeFor( @@ -135,25 +133,48 @@ class NodeService extends ChangeNotifier { required NodeModel node, bool shouldNotifyListeners = false, }) async { - await DB.instance.put( - boxName: DB.boxNamePrimaryNodes, - key: coin.identifier, - value: node, + // current + final currentPrimaries = primaryNodes.where( + (e) => e.coinName == coin.identifier && e.id != node.id, ); + final List toStore = []; + for (final node in currentPrimaries) { + final updated = node.copyWith( + loginName: node.loginName, + trusted: node.trusted, + isPrimary: false, + ); + toStore.add(updated); + } + toStore.add( + node.copyWith( + loginName: node.loginName, + trusted: node.trusted, + isPrimary: true, + ), + ); + + for (final node in toStore) { + await DB.instance.put( + boxName: DB.boxNameNodeModels, + key: node.id, + value: node, + ); + } + if (shouldNotifyListeners) { notifyListeners(); } } NodeModel? getPrimaryNodeFor({required CryptoCurrency currency}) { - return DB.instance.get( - boxName: DB.boxNamePrimaryNodes, - key: currency.identifier, - ); + return primaryNodes + .where((e) => e.coinName == currency.identifier) + .firstOrNull; } List get primaryNodes { - return DB.instance.values(boxName: DB.boxNamePrimaryNodes); + return nodes.where((e) => e.isPrimary).toList(); } List get nodes { @@ -161,14 +182,15 @@ class NodeService extends ChangeNotifier { } List getNodesFor(CryptoCurrency coin) { - final list = DB.instance - .values(boxName: DB.boxNameNodeModels) - .where( - (e) => - e.coinName == coin.identifier && - !e.id.startsWith(DefaultNodes.defaultNodeIdPrefix), - ) - .toList(); + final list = + DB.instance + .values(boxName: DB.boxNameNodeModels) + .where( + (e) => + e.coinName == coin.identifier && + !e.id.startsWith(DefaultNodes.defaultNodeIdPrefix), + ) + .toList(); // add default to end of list list.addAll( @@ -191,9 +213,9 @@ class NodeService extends ChangeNotifier { } List failoverNodesFor({required CryptoCurrency currency}) { - return getNodesFor(currency) - .where((e) => e.isFailover && !e.isDown) - .toList(); + return getNodesFor( + currency, + ).where((e) => e.isFailover && !e.isDown).toList(); } // should probably just combine this and edit into a save() func at some point @@ -237,10 +259,8 @@ class NodeService extends ChangeNotifier { bool enabled, bool shouldNotifyListeners, ) async { - final model = DB.instance.get( - boxName: DB.boxNameNodeModels, - key: id, - )!; + final model = + DB.instance.get(boxName: DB.boxNameNodeModels, key: id)!; await DB.instance.put( boxName: DB.boxNameNodeModels, key: model.id, @@ -284,10 +304,7 @@ class NodeService extends ChangeNotifier { final response = await client.post( uri, headers: {'Content-Type': 'application/json'}, - body: jsonEncode({ - "jsonrpc": "2.0", - "id": "0", - }), + body: jsonEncode({"jsonrpc": "2.0", "id": "0"}), ); final json = jsonDecode(response.body) as Map; @@ -312,6 +329,7 @@ class NodeService extends ChangeNotifier { torEnabled: nodeMap["torEnabled"] == "true", isDown: nodeMap["isDown"] == "true", clearnetEnabled: nodeMap["plainEnabled"] == "true", + isPrimary: nodeMap["plainEnabled"] == "true", ); final currentNode = getNodeById(id: nodeMap["id"] as String); if (currentNode != null) { From 905c64b131276e72e1f40f23ce2b0cc038d40a78 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 12:22:12 -0600 Subject: [PATCH 114/206] migrate primary nodes --- lib/db/db_version_migration.dart | 40 ++++++++++++++++ lib/db/hive/db.dart | 80 ++++++++++++++++---------------- lib/utilities/constants.dart | 2 +- test/hive/db_test.dart | 44 +++++++++++------- 4 files changed, 106 insertions(+), 60 deletions(-) diff --git a/lib/db/db_version_migration.dart b/lib/db/db_version_migration.dart index 8ef1f2bb5..2e5ebf219 100644 --- a/lib/db/db_version_migration.dart +++ b/lib/db/db_version_migration.dart @@ -19,6 +19,7 @@ import '../models/isar/models/blockchain_data/address.dart'; import '../models/isar/models/contact_entry.dart' as isar_contact; import '../models/isar/models/isar_models.dart' as isar_models; import '../models/models.dart'; +import '../models/node_model.dart'; import '../services/mixins/wallet_db.dart'; import '../services/wallets_service.dart'; import '../utilities/amount/amount.dart'; @@ -361,6 +362,20 @@ class DbVersionMigrator with WalletDB { // try to continue migrating return await migrate(14, secureStore: secureStore); + case 14: + // migrate + await _v14(); + + // update version + await DB.instance.put( + boxName: DB.boxNameDBInfo, + key: "hive_data_version", + value: 15, + ); + + // try to continue migrating + return await migrate(15, secureStore: secureStore); + default: // finally return return; @@ -632,4 +647,29 @@ class DbVersionMigrator with WalletDB { await isar.close(deleteFromDisk: true); } } + + Future _v14() async { + final nodesBox = await DB.instance.hive.openBox( + DB.boxNameNodeModels, + ); + final primariesBox = await DB.instance.hive.openBox( + DB.boxNamePrimaryNodesDeprecated, + ); + + final primaries = primariesBox.values; + + for (final node in primaries) { + await nodesBox.put( + node.id, + node.copyWith( + loginName: node.loginName, + trusted: node.trusted, + isPrimary: true, + ), + ); + } + + await primariesBox.close(); + await primariesBox.deleteFromDisk(); + } } diff --git a/lib/db/hive/db.dart b/lib/db/hive/db.dart index 0e9449094..be431aba7 100644 --- a/lib/db/hive/db.dart +++ b/lib/db/hive/db.dart @@ -33,11 +33,11 @@ class DB { static const String boxNameTrades = "exchangeTransactionsBox"; static const String boxNameAllWalletsData = "wallets"; static const String boxNameFavoriteWallets = "favoriteWallets"; + static const String boxNamePrimaryNodesDeprecated = "primaryNodes"; // in use // TODO: migrate static const String boxNameNodeModels = "nodeModels"; - static const String boxNamePrimaryNodes = "primaryNodes"; static const String boxNameNotifications = "notificationModels"; static const String boxNameWatchedTransactions = "watchedTxNotificationModels"; @@ -127,29 +127,27 @@ class DB { _boxNodeModels = await hive.openBox(boxNameNodeModels); } - if (hive.isBoxOpen(boxNamePrimaryNodes)) { - _boxPrimaryNodes = hive.box(boxNamePrimaryNodes); - } else { - _boxPrimaryNodes = await hive.openBox(boxNamePrimaryNodes); - } - if (hive.isBoxOpen(boxNameAllWalletsData)) { _boxAllWalletsData = hive.box(boxNameAllWalletsData); } else { _boxAllWalletsData = await hive.openBox(boxNameAllWalletsData); } - _boxNotifications = - await hive.openBox(boxNameNotifications); - _boxWatchedTransactions = - await hive.openBox(boxNameWatchedTransactions); - _boxWatchedTrades = - await hive.openBox(boxNameWatchedTrades); + _boxNotifications = await hive.openBox( + boxNameNotifications, + ); + _boxWatchedTransactions = await hive.openBox( + boxNameWatchedTransactions, + ); + _boxWatchedTrades = await hive.openBox( + boxNameWatchedTrades, + ); _boxTradesV2 = await hive.openBox(boxNameTradesV2); _boxTradeNotes = await hive.openBox(boxNameTradeNotes); _boxTradeLookup = await hive.openBox(boxNameTradeLookup); _walletInfoSource = await hive.openBox( - lib_monero_compat.WalletInfo.boxName); + lib_monero_compat.WalletInfo.boxName, + ); _boxFavoriteWallets = await hive.openBox(boxNameFavoriteWallets); await Future.wait([ @@ -183,11 +181,13 @@ class DB { for (final entry in mapped.entries) { if (hive.isBoxOpen(entry.value.walletId)) { - _walletBoxes[entry.value.walletId] = - hive.box(entry.value.walletId); + _walletBoxes[entry.value.walletId] = hive.box( + entry.value.walletId, + ); } else { - _walletBoxes[entry.value.walletId] = - await hive.openBox(entry.value.walletId); + _walletBoxes[entry.value.walletId] = await hive.openBox( + entry.value.walletId, + ); } } } @@ -196,8 +196,9 @@ class DB { if (_txCacheBoxes[currency.identifier]?.isOpen != true) { _txCacheBoxes.remove(currency.identifier); } - return _txCacheBoxes[currency.identifier] ??= - await hive.openBox(_boxNameTxCache(currency: currency)); + return _txCacheBoxes[currency.identifier] ??= await hive.openBox( + _boxNameTxCache(currency: currency), + ); } Future closeTxCacheBox({required CryptoCurrency currency}) async { @@ -210,8 +211,9 @@ class DB { if (_setCacheBoxes[currency.identifier]?.isOpen != true) { _setCacheBoxes.remove(currency.identifier); } - return _setCacheBoxes[currency.identifier] ??= - await hive.openBox(_boxNameSetCache(currency: currency)); + return _setCacheBoxes[currency.identifier] ??= await hive.openBox( + _boxNameSetCache(currency: currency), + ); } Future closeAnonymitySetCacheBox({ @@ -226,10 +228,8 @@ class DB { if (_usedSerialsCacheBoxes[currency.identifier]?.isOpen != true) { _usedSerialsCacheBoxes.remove(currency.identifier); } - return _usedSerialsCacheBoxes[currency.identifier] ??= - await hive.openBox( - _boxNameUsedSerialsCache(currency: currency), - ); + return _usedSerialsCacheBoxes[currency.identifier] ??= await hive + .openBox(_boxNameUsedSerialsCache(currency: currency)); } Future closeUsedSerialsCacheBox({ @@ -274,10 +274,7 @@ class DB { List values({required String boxName}) => hive.box(boxName).values.toList(growable: false); - T? get({ - required String boxName, - required dynamic key, - }) => + T? get({required String boxName, required dynamic key}) => hive.box(boxName).get(key); bool containsKey({required String boxName, required dynamic key}) => @@ -289,9 +286,9 @@ class DB { required String boxName, required dynamic key, required T value, - }) async => - await mutex - .protect(() async => await hive.box(boxName).put(key, value)); + }) async => await mutex.protect( + () async => await hive.box(boxName).put(key, value), + ); Future add({required String boxName, required T value}) async => await mutex.protect(() async => await hive.box(boxName).add(value)); @@ -299,9 +296,9 @@ class DB { Future addAll({ required String boxName, required Iterable values, - }) async => - await mutex - .protect(() async => await hive.box(boxName).addAll(values)); + }) async => await mutex.protect( + () async => await hive.box(boxName).addAll(values), + ); Future delete({ required dynamic key, @@ -325,11 +322,11 @@ class DB { await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameAddressBook); await DB.instance.deleteBoxFromDisk(boxName: "debugInfoBox"); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameNodeModels); - await DB.instance.deleteBoxFromDisk(boxName: DB.boxNamePrimaryNodes); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameAllWalletsData); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameNotifications); - await DB.instance - .deleteBoxFromDisk(boxName: DB.boxNameWatchedTransactions); + await DB.instance.deleteBoxFromDisk( + boxName: DB.boxNameWatchedTransactions, + ); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameWatchedTrades); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameTrades); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameTradesV2); @@ -337,8 +334,9 @@ class DB { await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameTradeLookup); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameFavoriteWallets); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNamePrefs); - await DB.instance - .deleteBoxFromDisk(boxName: DB.boxNameWalletsToDeleteOnStart); + await DB.instance.deleteBoxFromDisk( + boxName: DB.boxNameWalletsToDeleteOnStart, + ); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNamePriceCache); await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameDBInfo); await DB.instance.deleteBoxFromDisk(boxName: "theme"); diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 1c3b908a1..69205f1f0 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -40,7 +40,7 @@ abstract class Constants { // Enable Logger.print statements static const bool disableLogger = false; - static const int currentDataVersion = 14; + static const int currentDataVersion = 15; static const int rescanV1 = 1; diff --git a/test/hive/db_test.dart b/test/hive/db_test.dart index 2f5130837..fb4e71434 100644 --- a/test/hive/db_test.dart +++ b/test/hive/db_test.dart @@ -6,31 +6,39 @@ void main() { group("DB box names", () { test("address book", () => expect(DB.boxNameAddressBook, "addressBook")); test("nodes", () => expect(DB.boxNameNodeModels, "nodeModels")); - test("primary nodes", () => expect(DB.boxNamePrimaryNodes, "primaryNodes")); test("wallets info", () => expect(DB.boxNameAllWalletsData, "wallets")); - test("notifications", - () => expect(DB.boxNameNotifications, "notificationModels")); test( - "watched transactions", - () => expect( - DB.boxNameWatchedTransactions, "watchedTxNotificationModels")); + "notifications", + () => expect(DB.boxNameNotifications, "notificationModels"), + ); test( - "watched trades", - () => - expect(DB.boxNameWatchedTrades, "watchedTradesNotificationModels")); + "watched transactions", + () => + expect(DB.boxNameWatchedTransactions, "watchedTxNotificationModels"), + ); + test( + "watched trades", + () => expect(DB.boxNameWatchedTrades, "watchedTradesNotificationModels"), + ); test("trades", () => expect(DB.boxNameTrades, "exchangeTransactionsBox")); test("trade notes", () => expect(DB.boxNameTradeNotes, "tradeNotesBox")); - test("tx <> trade lookup table", - () => expect(DB.boxNameTradeLookup, "tradeToTxidLookUpBox")); - test("favorite wallets", - () => expect(DB.boxNameFavoriteWallets, "favoriteWallets")); + test( + "tx <> trade lookup table", + () => expect(DB.boxNameTradeLookup, "tradeToTxidLookUpBox"), + ); + test( + "favorite wallets", + () => expect(DB.boxNameFavoriteWallets, "favoriteWallets"), + ); test("preferences", () => expect(DB.boxNamePrefs, "prefs")); test( - "deleted wallets to clear out on start", - () => - expect(DB.boxNameWalletsToDeleteOnStart, "walletsToDeleteOnStart")); - test("price cache", - () => expect(DB.boxNamePriceCache, "priceAPIPrice24hCache")); + "deleted wallets to clear out on start", + () => expect(DB.boxNameWalletsToDeleteOnStart, "walletsToDeleteOnStart"), + ); + test( + "price cache", + () => expect(DB.boxNamePriceCache, "priceAPIPrice24hCache"), + ); }); group("tests requiring test hive environment", () { From 6ffdf3dedc58eca11e85414e6cc6b90f4bec1fca Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 2 Jun 2025 13:30:52 -0500 Subject: [PATCH 115/206] refactor: extract canPing-related checks to helper fn --- .../intermediate/lib_monero_wallet.dart | 67 ++++++++----------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index 9e2661311..82f3bce3c 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -19,6 +19,7 @@ import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; +import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; @@ -494,30 +495,16 @@ abstract class LibMoneroWallet Future updateNode() async { final node = getCurrentNode(); + if (_torNodeMismatchGuard(node)) { + throw Exception("TOR – clearnet mismatch"); + } + final host = node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; ({InternetAddress host, int port})? proxy; - _canPing = true; - if (prefs.useTor) { - if (node.clearnetEnabled && !node.torEnabled) { - _canPing = false; - libMoneroWallet?.stopAutoSaving(); - libMoneroWallet?.stopListeners(); - libMoneroWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - proxy = TorService.sharedInstance.getProxyInfo(); - } else { - if (!node.clearnetEnabled && node.torEnabled) { - _canPing = false; - libMoneroWallet?.stopAutoSaving(); - libMoneroWallet?.stopListeners(); - libMoneroWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - } + proxy = prefs.useTor && !node.forceNoTor + ? TorService.sharedInstance.getProxyInfo() + : null; _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); try { @@ -1001,6 +988,23 @@ abstract class LibMoneroWallet } } + bool _torNodeMismatchGuard(NodeModel node) { + _canPing = true; // Reset. + + final bool mismatch = (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || + (!prefs.useTor && !node.clearnetEnabled && node.torEnabled); + + if (mismatch) { + _canPing = false; + libMoneroWallet?.stopAutoSaving(); + libMoneroWallet?.stopListeners(); + libMoneroWallet?.stopSyncing(); + _setSyncStatus(lib_monero_compat.FailedSyncStatus()); + } + + return mismatch; // Caller decides whether to throw. + } + // ============ Overrides ==================================================== @override @@ -1097,25 +1101,8 @@ abstract class LibMoneroWallet final node = getCurrentNode(); - _canPing = true; - if (prefs.useTor) { - if (node.clearnetEnabled && !node.torEnabled) { - _canPing = false; - libMoneroWallet?.stopAutoSaving(); - libMoneroWallet?.stopListeners(); - libMoneroWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - } else { - if (!node.clearnetEnabled && node.torEnabled) { - _canPing = false; - libMoneroWallet?.stopAutoSaving(); - libMoneroWallet?.stopListeners(); - libMoneroWallet?.stopSyncing(); - _setSyncStatus(lib_monero_compat.FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } + if (_torNodeMismatchGuard(node)) { + throw Exception("TOR – clearnet mismatch"); } // this acquire should be almost instant due to above check. From 505ba4c439f9a814f1f48d751dda697d11c85e22 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 2 Jun 2025 13:41:02 -0500 Subject: [PATCH 116/206] feat: avoid crash w local node + "TOR only" node and tor off --- .../intermediate/lib_salvium_wallet.dart | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index fcb1cae60..7f7eea6f0 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -17,6 +17,7 @@ import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; +import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; @@ -457,36 +458,31 @@ abstract class LibSalviumWallet }); } + bool _canPing = false; + @override Future pingCheck() async { - return (await libSalviumWallet?.isConnectedToDaemon()) ?? false; + if (_canPing) { + return (await libSalviumWallet?.isConnectedToDaemon()) ?? false; + } else { + return false; + } } @override Future updateNode() async { final node = getCurrentNode(); + if (_torNodeMismatchGuard(node)) { + throw Exception("TOR – clearnet mismatch"); + } + final host = node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; ({InternetAddress host, int port})? proxy; - if (prefs.useTor) { - if (node.clearnetEnabled && !node.torEnabled) { - libSalviumWallet?.stopAutoSaving(); - libSalviumWallet?.stopListeners(); - libSalviumWallet?.stopSyncing(); - _setSyncStatus(FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - proxy = TorService.sharedInstance.getProxyInfo(); - } else { - if (!node.clearnetEnabled && node.torEnabled) { - libSalviumWallet?.stopAutoSaving(); - libSalviumWallet?.stopListeners(); - libSalviumWallet?.stopSyncing(); - _setSyncStatus(FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - } + proxy = prefs.useTor && !node.forceNoTor + ? TorService.sharedInstance.getProxyInfo() + : null; _setSyncStatus(ConnectingSyncStatus()); try { @@ -957,6 +953,23 @@ abstract class LibSalviumWallet } } + bool _torNodeMismatchGuard(NodeModel node) { + _canPing = true; // Reset. + + final bool mismatch = (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || + (!prefs.useTor && !node.clearnetEnabled && node.torEnabled); + + if (mismatch) { + _canPing = false; + libSalviumWallet?.stopAutoSaving(); + libSalviumWallet?.stopListeners(); + libSalviumWallet?.stopSyncing(); + _setSyncStatus(FailedSyncStatus()); + } + + return mismatch; // Caller decides whether to throw. + } + // ============ Overrides ==================================================== @override @@ -1053,22 +1066,8 @@ abstract class LibSalviumWallet final node = getCurrentNode(); - if (prefs.useTor) { - if (node.clearnetEnabled && !node.torEnabled) { - libSalviumWallet?.stopAutoSaving(); - libSalviumWallet?.stopListeners(); - libSalviumWallet?.stopSyncing(); - _setSyncStatus(FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } - } else { - if (!node.clearnetEnabled && node.torEnabled) { - libSalviumWallet?.stopAutoSaving(); - libSalviumWallet?.stopListeners(); - libSalviumWallet?.stopSyncing(); - _setSyncStatus(FailedSyncStatus()); - throw Exception("TOR - clearnet mismatch"); - } + if (_torNodeMismatchGuard(node)) { + throw Exception("TOR – clearnet mismatch"); } // this acquire should be almost instant due to above check. From 0c42fbedced1c67fa8a06078f2ca5640de8f8a94 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 12:45:12 -0600 Subject: [PATCH 117/206] update swb to handle updated primary node handling --- .../helpers/restore_create_backup.dart | 68 +++---------------- 1 file changed, 11 insertions(+), 57 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index d0200b034..c61d73d1d 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -47,7 +47,6 @@ import '../../../../../utilities/format.dart'; import '../../../../../utilities/logger.dart'; import '../../../../../utilities/prefs.dart'; import '../../../../../utilities/util.dart'; -import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/crypto_currency/intermediate/frost_currency.dart'; import '../../../../../wallets/isar/models/frost_wallet_info.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; @@ -242,17 +241,6 @@ abstract class SWB { await DB.instance.mutex.protect(() async { Logging.instance.i("...createStackWalletJSON DB.instance.mutex acquired"); Logging.instance.i("SWB backing up nodes"); - try { - final primaryNodes = - nodeService.primaryNodes.map((e) async { - final map = e.toMap(); - map["password"] = await e.getPassword(_secureStore); - return map; - }).toList(); - backupJson['primaryNodes'] = await Future.wait(primaryNodes); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - } try { final nodesFuture = nodeService.nodes.map((e) async { @@ -896,8 +884,6 @@ abstract class SWB { revertToState.validJSON["prefs"] as Map; final List? addressBookEntries = revertToState.validJSON["addressBookEntries"] as List?; - final List? primaryNodes = - revertToState.validJSON["primaryNodes"] as List?; final List? nodes = revertToState.validJSON["nodes"] as List?; final List? trades = revertToState.validJSON["tradeHistory"] as List?; @@ -1001,6 +987,7 @@ abstract class SWB { isFailover: nodeData['isFailover'] as bool, isDown: nodeData['isDown'] as bool, trusted: nodeData['trusted'] as bool?, + isPrimary: nodeData["isPrimary"] as bool? ?? false, ), nodeData['password'] as String?, true, @@ -1011,28 +998,6 @@ abstract class SWB { } } - // primary nodes - if (primaryNodes != null) { - for (final node in primaryNodes) { - try { - final CryptoCurrency coin; - try { - coin = AppConfig.getCryptoCurrencyByPrettyName( - node['coinName'] as String, - ); - } catch (_) { - continue; - } - - await nodeService.setPrimaryNodeFor( - coin: coin, - node: nodeService.getNodeById(id: node['id'] as String)!, - ); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - } - } - } await nodeService.updateDefaults(); // trades @@ -1204,13 +1169,20 @@ abstract class SWB { secureStorageInterface: secureStorageInterface, ); if (nodes != null) { + final primaryIds = + primaryNodes + ?.map((e) => e["id"] as String?) + .whereType() + .toSet(); + for (final node in nodes) { + final id = node['id'] as String; await nodeService.add( NodeModel( host: node['host'] as String, port: node['port'] as int, name: node['name'] as String, - id: node['id'] as String, + id: id, useSSL: node['useSSL'] == "false" ? false : true, enabled: node['enabled'] == "false" ? false : true, coinName: node['coinName'] as String, @@ -1219,33 +1191,15 @@ abstract class SWB { isDown: node['isDown'] as bool, torEnabled: node['torEnabled'] as bool? ?? true, clearnetEnabled: node['plainEnabled'] as bool? ?? true, + isPrimary: + node["isPrimary"] as bool? ?? primaryIds?.contains(id) ?? false, ), node["password"] as String?, true, ); } } - if (primaryNodes != null) { - for (final node in primaryNodes) { - final CryptoCurrency coin; - try { - coin = AppConfig.getCryptoCurrencyByPrettyName( - node['coinName'] as String, - ); - } catch (_) { - continue; - } - try { - await nodeService.setPrimaryNodeFor( - coin: coin, - node: nodeService.getNodeById(id: node['id'] as String)!, - ); - } catch (e, s) { - Logging.instance.e("", error: e, stackTrace: s); - } - } - } await nodeService.updateDefaults(); } From a6ba1cd568bc2b094912b8c6b89990f5f86adc68 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 2 Jun 2025 14:04:22 -0500 Subject: [PATCH 118/206] refactor: combine NodeService add and edit -> save --- .../add_edit_node_view.dart | 19 +++++--- .../manage_nodes_views/node_details_view.dart | 2 +- .../helpers/restore_create_backup.dart | 4 +- lib/services/node_service.dart | 43 ++++++++----------- .../pages/send_view/send_view_test.mocks.dart | 2 +- .../lockscreen_view_screen_test.mocks.dart | 2 +- .../create_pin_view_screen_test.mocks.dart | 2 +- ...restore_wallet_view_screen_test.mocks.dart | 2 +- ...dd_custom_node_view_screen_test.mocks.dart | 2 +- .../node_details_view_screen_test.mocks.dart | 2 +- ...twork_settings_view_screen_test.mocks.dart | 2 +- test/services/node_service_test.dart | 12 ++++-- .../managed_favorite_test.mocks.dart | 2 +- test/widget_tests/node_card_test.dart | 6 +++ test/widget_tests/node_card_test.mocks.dart | 2 +- .../widget_tests/node_options_sheet_test.dart | 8 +++- .../node_options_sheet_test.mocks.dart | 2 +- ...et_info_row_balance_future_test.mocks.dart | 2 +- .../wallet_info_row_test.mocks.dart | 2 +- 19 files changed, 67 insertions(+), 51 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 98b80995d..27b50796d 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -262,11 +262,12 @@ class _AddEditNodeViewState extends ConsumerState { torEnabled: torEnabled, clearnetEnabled: plainEnabled, forceNoTor: forceNoTor, + isPrimary: false, ); await ref .read(nodeServiceChangeNotifierProvider) - .add(node, formData.password, true); + .save(node, formData.password, true); await _notifyWalletsOfUpdatedNode(); if (mounted) { Navigator.of( @@ -290,11 +291,12 @@ class _AddEditNodeViewState extends ConsumerState { torEnabled: torEnabled, clearnetEnabled: plainEnabled, forceNoTor: forceNoTor, + isPrimary: formData.isPrimary ?? false, ); await ref .read(nodeServiceChangeNotifierProvider) - .add(node, formData.password, true); + .save(node, formData.password, true); await _notifyWalletsOfUpdatedNode(); if (mounted) { Navigator.of( @@ -420,6 +422,7 @@ class _AddEditNodeViewState extends ConsumerState { torEnabled: true, clearnetEnabled: !nodeQrData.host.endsWith(".onion"), loginName: (nodeQrData as LibMoneroNodeQrData?)?.user, + isPrimary: false, ), (nodeQrData as LibMoneroNodeQrData?)?.password ?? "", ); @@ -766,12 +769,12 @@ class _AddEditNodeViewState extends ConsumerState { class NodeFormData { String? name, host, login, password; int? port; - bool? useSSL, isFailover, trusted, forceNoTor; + bool? useSSL, isFailover, trusted, forceNoTor, isPrimary; TorPlainNetworkOption? netOption; @override String toString() { - return "{ name: $name, host: $host, port: $port, useSSL: $useSSL, trusted: $trusted, netOption: $netOption }"; + return "{ name: $name, host: $host, port: $port, useSSL: $useSSL, trusted: $trusted, netOption: $netOption, isPrimary: $isPrimary }"; } } @@ -819,6 +822,7 @@ class _NodeFormState extends ConsumerState { int? port; late bool enableSSLCheckbox; late TorPlainNetworkOption netOption; + bool _isPrimary = false; late final bool enableAuthFields; @@ -875,6 +879,8 @@ class _NodeFormState extends ConsumerState { ref.read(nodeFormDataProvider).trusted = _trusted; ref.read(nodeFormDataProvider).netOption = netOption; ref.read(nodeFormDataProvider).forceNoTor = _forceNoTor; + ref.read(nodeFormDataProvider).host; + ref.read(nodeFormDataProvider).isPrimary = _isPrimary; } @override @@ -910,6 +916,7 @@ class _NodeFormState extends ConsumerState { _isFailover = node.isFailover; _trusted = node.trusted ?? false; _forceNoTor = node.forceNoTor ?? false; + _isPrimary = node.isPrimary ?? false; if (node.torEnabled && !node.clearnetEnabled) { netOption = TorPlainNetworkOption.tor; @@ -1359,7 +1366,7 @@ class _NodeFormState extends ConsumerState { if (widget.readOnly) { ref .read(nodeServiceChangeNotifierProvider) - .edit( + .save( widget.node!.copyWith( isFailover: _isFailover, loginName: widget.node!.loginName, @@ -1390,7 +1397,7 @@ class _NodeFormState extends ConsumerState { if (widget.readOnly) { ref .read(nodeServiceChangeNotifierProvider) - .edit( + .save( widget.node!.copyWith( isFailover: _isFailover, loginName: widget.node!.loginName, diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 414ba8097..481c3906d 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -396,7 +396,7 @@ class _NodeDetailsViewState extends ConsumerState { await ref .read(nodeServiceChangeNotifierProvider) - .edit( + .save( editedNode, ref.read(nodeFormDataProvider).password, true, diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index c61d73d1d..bcec91212 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -975,7 +975,7 @@ abstract class SWB { if (nodeData != null) { // node existed before restore attempt // revert to pre restore node - await nodeService.edit( + await nodeService.save( node.copyWith( host: nodeData['host'] as String, port: nodeData['port'] as int, @@ -1177,7 +1177,7 @@ abstract class SWB { for (final node in nodes) { final id = node['id'] as String; - await nodeService.add( + await nodeService.save( NodeModel( host: node['host'] as String, port: node['port'] as int, diff --git a/lib/services/node_service.dart b/lib/services/node_service.dart index 1657cfa78..6d061e146 100644 --- a/lib/services/node_service.dart +++ b/lib/services/node_service.dart @@ -218,20 +218,33 @@ class NodeService extends ChangeNotifier { ).where((e) => e.isFailover && !e.isDown).toList(); } - // should probably just combine this and edit into a save() func at some point - /// Over write node in hive if a node with existing id already exists. - /// Otherwise add node to hive - Future add( + /// Adds a new node to the database. + /// + /// If a node with the same ID already exists, it will be overwritten. + Future save( NodeModel node, String? password, bool shouldNotifyListeners, ) async { + // Handle primary node updates (logic from edit()) + final coin = AppConfig.getCryptoCurrencyByPrettyName(node.coinName); + final primaryNode = getPrimaryNodeFor(currency: coin); + if (primaryNode?.id == node.id) { + await setPrimaryNodeFor( + coin: coin, + node: node, + shouldNotifyListeners: true, + ); + } + + // Save to database (logic from add()). await DB.instance.put( boxName: DB.boxNameNodeModels, key: node.id, value: node, ); + // Save password to secure storage. if (password != null) { await secureStorageInterface.write( key: "${node.id}_nodePW", @@ -275,26 +288,6 @@ class NodeService extends ChangeNotifier { } } - /// convenience wrapper for add - Future edit( - NodeModel editedNode, - String? password, - bool shouldNotifyListeners, - ) async { - // check if the node being edited is the primary one; if it is, setPrimaryNodeFor coin - final coin = AppConfig.getCryptoCurrencyByPrettyName(editedNode.coinName); - final primaryNode = getPrimaryNodeFor(currency: coin); - if (primaryNode?.id == editedNode.id) { - await setPrimaryNodeFor( - coin: coin, - node: editedNode, - shouldNotifyListeners: true, - ); - } - - return add(editedNode, password, shouldNotifyListeners); - } - //============================================================================ Future updateCommunityNodes() async { @@ -344,7 +337,7 @@ class NodeService extends ChangeNotifier { trusted: node.trusted, ); } - await add(node, null, false); + await save(node, null, false); } } } catch (e, s) { diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index c4398cf4d..436a918fd 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -341,7 +341,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) as List<_i13.NodeModel>); @override - _i10.Future add( + _i10.Future save( _i13.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/lockscreen_view_screen_test.mocks.dart b/test/screen_tests/lockscreen_view_screen_test.mocks.dart index a3523a093..c68851019 100644 --- a/test/screen_tests/lockscreen_view_screen_test.mocks.dart +++ b/test/screen_tests/lockscreen_view_screen_test.mocks.dart @@ -202,7 +202,7 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { ) as List<_i7.NodeModel>); @override - _i4.Future add( + _i4.Future save( _i7.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart index 4f9addbc7..08e96b5a3 100644 --- a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart @@ -202,7 +202,7 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { ) as List<_i7.NodeModel>); @override - _i4.Future add( + _i4.Future save( _i7.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart index 0603d61be..3c66bf1f3 100644 --- a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart @@ -243,7 +243,7 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { ) as List<_i9.NodeModel>); @override - _i5.Future add( + _i5.Future save( _i9.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart index 75a10f43e..d6d788327 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart @@ -142,7 +142,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) as List<_i4.NodeModel>); @override - _i5.Future add( + _i5.Future save( _i4.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart index fb159cea3..6a4ad08ce 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart @@ -142,7 +142,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) as List<_i4.NodeModel>); @override - _i5.Future add( + _i5.Future save( _i4.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart index c60df280d..b8fee8040 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart @@ -142,7 +142,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) as List<_i4.NodeModel>); @override - _i5.Future add( + _i5.Future save( _i4.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/services/node_service_test.dart b/test/services/node_service_test.dart index 2fac42b96..8865c748c 100644 --- a/test/services/node_service_test.dart +++ b/test/services/node_service_test.dart @@ -17,7 +17,7 @@ void main() { Hive.registerAdapter(NodeModelAdapter()); } await Hive.openBox(DB.boxNameNodeModels); - await Hive.openBox(DB.boxNamePrimaryNodes); + // await Hive.openBox(DB.boxNamePrimaryNodes); }); group("Empty nodes DB tests", () { @@ -50,6 +50,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ); await service.setPrimaryNodeFor( coin: Bitcoin(CryptoCurrencyNetwork.main), @@ -133,6 +134,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ); final nodeB = NodeModel( host: "host2", @@ -146,6 +148,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ); final nodeC = NodeModel( host: "host3", @@ -159,6 +162,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ); setUp(() async { @@ -226,7 +230,7 @@ void main() { test("add a node without a password", () async { final fakeStore = FakeSecureStorage(); final service = NodeService(secureStorageInterface: fakeStore); - await service.add(nodeA, null, true); + await service.save(nodeA, null, true); expect( service.nodes.length, AppConfig.coins.map((e) => e.defaultNode).length + 1, @@ -237,7 +241,7 @@ void main() { test("add a node with a password", () async { final fakeStore = FakeSecureStorage(); final service = NodeService(secureStorageInterface: fakeStore); - await service.add(nodeA, "some password", true); + await service.save(nodeA, "some password", true); expect( service.nodes.length, AppConfig.coins.map((e) => e.defaultNode).length + 1, @@ -276,7 +280,7 @@ void main() { trusted: null, ); - await service.edit(editedNode, "123456", true); + await service.save(editedNode, "123456", true); expect(service.nodes.length, currentLength); diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index 6eb09a26e..4b1944af8 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -1256,7 +1256,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) as List<_i23.NodeModel>); @override - _i10.Future add( + _i10.Future save( _i23.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/widget_tests/node_card_test.dart b/test/widget_tests/node_card_test.dart index cc706824c..71a08f851 100644 --- a/test/widget_tests/node_card_test.dart +++ b/test/widget_tests/node_card_test.dart @@ -39,6 +39,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -55,6 +56,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -118,6 +120,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -134,6 +137,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -198,6 +202,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -214,6 +219,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); diff --git a/test/widget_tests/node_card_test.mocks.dart b/test/widget_tests/node_card_test.mocks.dart index 441edcdbf..808f10fab 100644 --- a/test/widget_tests/node_card_test.mocks.dart +++ b/test/widget_tests/node_card_test.mocks.dart @@ -142,7 +142,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) as List<_i4.NodeModel>); @override - _i5.Future add( + _i5.Future save( _i4.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/widget_tests/node_options_sheet_test.dart b/test/widget_tests/node_options_sheet_test.dart index 998f6322a..cedc9158b 100644 --- a/test/widget_tests/node_options_sheet_test.dart +++ b/test/widget_tests/node_options_sheet_test.dart @@ -38,6 +38,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, )); when(mockNodeService.getPrimaryNodeFor( @@ -53,7 +54,8 @@ void main() { isFailover: false, torEnabled: true, clearnetEnabled: true, - isDown: false)); + isDown: false, + isPrimary: true)); await tester.pumpWidget( ProviderScope( @@ -116,6 +118,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -134,6 +137,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -197,6 +201,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); @@ -215,6 +220,7 @@ void main() { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: true, ), ); diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index 172abecf2..d01578f3f 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -1060,7 +1060,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) as List<_i19.NodeModel>); @override - _i10.Future add( + _i10.Future save( _i19.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart index 7ded2cf87..fc2c10fbb 100644 --- a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart @@ -309,7 +309,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) as List<_i11.NodeModel>); @override - _i8.Future add( + _i8.Future save( _i11.NodeModel? node, String? password, bool? shouldNotifyListeners, diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart index 3f2a24ac7..5f16a8a2e 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart @@ -449,7 +449,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) as List<_i15.NodeModel>); @override - _i9.Future add( + _i9.Future save( _i15.NodeModel? node, String? password, bool? shouldNotifyListeners, From e8a13f9aa4054e9bbe88e6971d8b5cf5ff733e21 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 13:05:12 -0600 Subject: [PATCH 119/206] update nodeservice delete func --- lib/services/node_service.dart | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/services/node_service.dart b/lib/services/node_service.dart index 6d061e146..3fb226809 100644 --- a/lib/services/node_service.dart +++ b/lib/services/node_service.dart @@ -259,9 +259,34 @@ class NodeService extends ChangeNotifier { } Future delete(String id, bool shouldNotifyListeners) async { - await DB.instance.delete(boxName: DB.boxNameNodeModels, key: id); + final nodeToDelete = getNodeById(id: id); + + if (nodeToDelete == null) { + // doesn't exist + Logging.instance.w( + "Attempted delete of a node model that does not exist", + ); + return; + } + + final coin = AppConfig.getCryptoCurrencyByPrettyName(nodeToDelete.coinName); + final remaining = getNodesFor(coin); + + if (remaining.length - 1 < 1) { + // doesn't exist + Logging.instance.w("Attempted delete the last remaining node for $coin"); + return; + } + + remaining.retainWhere((e) => e.id != nodeToDelete.id); + await DB.instance.delete(boxName: DB.boxNameNodeModels, key: id); await secureStorageInterface.delete(key: "${id}_nodePW"); + + if (nodeToDelete.isPrimary) { + await setPrimaryNodeFor(coin: coin, node: remaining.first); + } + if (shouldNotifyListeners) { notifyListeners(); } From d5945b457b772667e3aa246531facab27329a3ca Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 13:25:40 -0600 Subject: [PATCH 120/206] clean up remaining node service refactor code issues --- ...w_wallet_recovery_phrase_warning_view.dart | 4 +- .../restore_view_only_wallet_view.dart | 4 +- .../restore_wallet_view.dart | 4 +- .../helpers/restore_create_backup.dart | 4 +- lib/services/ethereum/ethereum_api.dart | 2 +- lib/services/node_service.dart | 37 +------ .../show_node_tor_settings_mismatch.dart | 99 +++++++++---------- lib/wallets/crypto_currency/coins/banano.dart | 10 +- .../crypto_currency/coins/bitcoin.dart | 30 +++--- .../crypto_currency/coins/bitcoin_frost.dart | 14 +-- .../crypto_currency/coins/bitcoincash.dart | 16 +-- .../crypto_currency/coins/cardano.dart | 6 +- lib/wallets/crypto_currency/coins/dash.dart | 18 ++-- .../crypto_currency/coins/dogecoin.dart | 19 ++-- lib/wallets/crypto_currency/coins/ecash.dart | 15 ++- .../crypto_currency/coins/epiccash.dart | 6 +- .../crypto_currency/coins/ethereum.dart | 3 +- .../crypto_currency/coins/fact0rn.dart | 3 +- lib/wallets/crypto_currency/coins/firo.dart | 19 ++-- .../crypto_currency/coins/litecoin.dart | 33 +++---- lib/wallets/crypto_currency/coins/monero.dart | 6 +- .../crypto_currency/coins/namecoin.dart | 28 +++--- lib/wallets/crypto_currency/coins/nano.dart | 10 +- .../crypto_currency/coins/particl.dart | 15 ++- .../crypto_currency/coins/peercoin.dart | 27 ++--- .../crypto_currency/coins/salvium.dart | 3 +- lib/wallets/crypto_currency/coins/solana.dart | 3 +- .../crypto_currency/coins/stellar.dart | 15 ++- lib/wallets/crypto_currency/coins/tezos.dart | 18 ++-- .../crypto_currency/coins/wownero.dart | 6 +- lib/wallets/crypto_currency/coins/xelis.dart | 8 +- .../crypto_currency/crypto_currency.dart | 2 +- lib/wallets/wallet/impl/solana_wallet.dart | 4 +- lib/wallets/wallet/impl/tezos_wallet.dart | 4 +- lib/wallets/wallet/wallet.dart | 2 +- .../nano_interface.dart | 4 +- test/services/node_service_test.dart | 18 ++-- 37 files changed, 248 insertions(+), 271 deletions(-) diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index 970614542..a3e6f0093 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -165,10 +165,10 @@ class _NewWalletRecoveryPhraseWarningViewState .getPrimaryNodeFor(currency: coin); if (node == null) { - node = coin.defaultNode; + node = coin.defaultNode(isPrimary: true); await ref .read(nodeServiceChangeNotifierProvider) - .setPrimaryNodeFor(coin: coin, node: node); + .save(node, null, false); } final txTracker = TransactionNotificationTracker(walletId: info.walletId); diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart index 606841139..a473d83ec 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_view_only_wallet_view.dart @@ -198,10 +198,10 @@ class _RestoreViewOnlyWalletViewState .getPrimaryNodeFor(currency: widget.coin); if (node == null) { - node = widget.coin.defaultNode; + node = widget.coin.defaultNode(isPrimary: true); await ref .read(nodeServiceChangeNotifierProvider) - .setPrimaryNodeFor(coin: widget.coin, node: node); + .save(node, null, false); } try { diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index b4aeb3693..535fbe07a 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -298,10 +298,10 @@ class _RestoreWalletViewState extends ConsumerState { .getPrimaryNodeFor(currency: widget.coin); if (node == null) { - node = widget.coin.defaultNode; + node = widget.coin.defaultNode(isPrimary: true); await ref .read(nodeServiceChangeNotifierProvider) - .setPrimaryNodeFor(coin: widget.coin, node: node); + .save(node, null, false); } final txTracker = TransactionNotificationTracker( diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart index bcec91212..1d8d9c90f 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart @@ -794,8 +794,8 @@ abstract class SWB { var node = nodeService.getPrimaryNodeFor(currency: coin); if (node == null) { - node = coin.defaultNode; - await nodeService.setPrimaryNodeFor(coin: coin, node: node); + node = coin.defaultNode(isPrimary: true); + await nodeService.save(node, null, false); } // final txTracker = TransactionNotificationTracker(walletId: walletId); diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 091165b30..fd644944a 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -43,7 +43,7 @@ class EthereumResponse { abstract class EthereumAPI { static String get stackBaseServer => - Ethereum(CryptoCurrencyNetwork.main).defaultNode.host; + Ethereum(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true).host; static HTTP client = HTTP(); diff --git a/lib/services/node_service.dart b/lib/services/node_service.dart index 3fb226809..c1bc338b3 100644 --- a/lib/services/node_service.dart +++ b/lib/services/node_service.dart @@ -74,7 +74,9 @@ class NodeService extends ChangeNotifier { } } - for (final defaultNode in AppConfig.coins.map((e) => e.defaultNode)) { + for (final defaultNode in AppConfig.coins.map( + (e) => e.defaultNode(isPrimary: true), + )) { final savedNode = DB.instance.get( boxName: DB.boxNameNodeModels, key: defaultNode.id, @@ -102,26 +104,8 @@ class NodeService extends ChangeNotifier { torEnabled: savedNode.torEnabled, clearnetEnabled: savedNode.clearnetEnabled, loginName: savedNode.loginName, - ), - ); - } - - // check if a default node is the primary node for the crypto currency - // and update it if needed - final coin = AppConfig.getCryptoCurrencyByPrettyName( - defaultNode.coinName, - ); - final primaryNode = getPrimaryNodeFor(currency: coin); - if (primaryNode != null && primaryNode.id == defaultNode.id) { - await setPrimaryNodeFor( - coin: coin, - node: defaultNode.copyWith( - enabled: primaryNode.enabled, - isFailover: primaryNode.isFailover, - trusted: primaryNode.trusted, - torEnabled: primaryNode.torEnabled, - clearnetEnabled: primaryNode.clearnetEnabled, - loginName: primaryNode.loginName, + isPrimary: savedNode.isPrimary, + forceNoTor: savedNode.forceNoTor, ), ); } @@ -226,17 +210,6 @@ class NodeService extends ChangeNotifier { String? password, bool shouldNotifyListeners, ) async { - // Handle primary node updates (logic from edit()) - final coin = AppConfig.getCryptoCurrencyByPrettyName(node.coinName); - final primaryNode = getPrimaryNodeFor(currency: coin); - if (primaryNode?.id == node.id) { - await setPrimaryNodeFor( - coin: coin, - node: node, - shouldNotifyListeners: true, - ); - } - // Save to database (logic from add()). await DB.instance.put( boxName: DB.boxNameNodeModels, diff --git a/lib/utilities/show_node_tor_settings_mismatch.dart b/lib/utilities/show_node_tor_settings_mismatch.dart index 6c2490b51..ce9f595f1 100644 --- a/lib/utilities/show_node_tor_settings_mismatch.dart +++ b/lib/utilities/show_node_tor_settings_mismatch.dart @@ -20,7 +20,8 @@ Future checkShowNodeTorSettingsMismatch({ bool rootNavigator = false, }) async { final node = - nodeService.getPrimaryNodeFor(currency: currency) ?? currency.defaultNode; + nodeService.getPrimaryNodeFor(currency: currency) ?? + currency.defaultNode(isPrimary: true); if (prefs.useTor) { if (node.torEnabled) { return true; @@ -34,63 +35,57 @@ Future checkShowNodeTorSettingsMismatch({ final result = await showDialog( context: context, barrierDismissible: false, - builder: (context) => ConditionalParent( - condition: Util.isDesktop, - builder: (child) => DesktopDialog( - maxHeight: double.infinity, - child: Padding( - padding: const EdgeInsets.all(32), - child: child, - ), - ), - child: ConditionalParent( - condition: !Util.isDesktop, - builder: (child) => StackDialogBase( - child: child, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Attention! Node connection issue detected. " - "The current node will not sync due to its connectivity settings. " - "Please adjust the node settings or enable/disable TOR.", - style: STextStyles.w600_16(context), - ), - SizedBox( - height: Util.isDesktop ? 32 : 24, - ), - Row( + builder: + (context) => ConditionalParent( + condition: Util.isDesktop, + builder: + (child) => DesktopDialog( + maxHeight: double.infinity, + child: Padding(padding: const EdgeInsets.all(32), child: child), + ), + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => StackDialogBase(child: child), + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - allowCancel - ? Expanded( - child: SecondaryButton( - buttonHeight: Util.isDesktop ? ButtonHeight.l : null, - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - ) - : const Spacer(), - SizedBox( - width: Util.isDesktop ? 24 : 16, + Text( + "Attention! Node connection issue detected. " + "The current node will not sync due to its connectivity settings. " + "Please adjust the node settings or enable/disable TOR.", + style: STextStyles.w600_16(context), ), - Expanded( - child: PrimaryButton( - buttonHeight: Util.isDesktop ? ButtonHeight.l : null, - label: "Continue", - onPressed: () { - Navigator.of(context).pop(true); - }, - ), + SizedBox(height: Util.isDesktop ? 32 : 24), + Row( + children: [ + allowCancel + ? Expanded( + child: SecondaryButton( + buttonHeight: + Util.isDesktop ? ButtonHeight.l : null, + label: "Cancel", + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + ) + : const Spacer(), + SizedBox(width: Util.isDesktop ? 24 : 16), + Expanded( + child: PrimaryButton( + buttonHeight: Util.isDesktop ? ButtonHeight.l : null, + label: "Continue", + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), + ], ), ], ), - ], + ), ), - ), - ), ); return result ?? true; diff --git a/lib/wallets/crypto_currency/coins/banano.dart b/lib/wallets/crypto_currency/coins/banano.dart index 8b1e1114b..2a62acb57 100644 --- a/lib/wallets/crypto_currency/coins/banano.dart +++ b/lib/wallets/crypto_currency/coins/banano.dart @@ -45,9 +45,7 @@ class Banano extends NanoCurrency { int get fractionDigits => 29; @override - BigInt get satsPerCoin => BigInt.parse( - "100000000000000000000000000000", - ); // 1*10^29 + BigInt get satsPerCoin => BigInt.parse("100000000000000000000000000000"); // 1*10^29 @override int get minConfirms => 1; @@ -63,7 +61,7 @@ class Banano extends NanoCurrency { int get nanoAccountType => NanoAccountType.BANANO; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -79,6 +77,7 @@ class Banano extends NanoCurrency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -99,7 +98,8 @@ class Banano extends NanoCurrency { } @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); } diff --git a/lib/wallets/crypto_currency/coins/bitcoin.dart b/lib/wallets/crypto_currency/coins/bitcoin.dart index 35a9cf8f0..e6862edb5 100644 --- a/lib/wallets/crypto_currency/coins/bitcoin.dart +++ b/lib/wallets/crypto_currency/coins/bitcoin.dart @@ -62,11 +62,11 @@ class Bitcoin extends Bip39HDCurrency @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - DerivePathType.bip49, - DerivePathType.bip84, - DerivePathType.bip86, // P2TR. - ]; + DerivePathType.bip44, + DerivePathType.bip49, + DerivePathType.bip84, + DerivePathType.bip86, // P2TR. + ]; @override String get genesisHash { @@ -83,10 +83,8 @@ class Bitcoin extends Bip39HDCurrency } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(294), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(294), fractionDigits: fractionDigits); @override coinlib.Network get networkParams { @@ -180,10 +178,11 @@ class Bitcoin extends Bip39HDCurrency // TODO: [prio=high] verify this works similarly to bitcoindart's p2sh or something(!!) case DerivePathType.bip49: - final p2wpkhScript = coinlib.P2WPKHAddress.fromPublicKey( - publicKey, - hrp: networkParams.bech32Hrp, - ).program.script; + final p2wpkhScript = + coinlib.P2WPKHAddress.fromPublicKey( + publicKey, + hrp: networkParams.bech32Hrp, + ).program.script; final addr = coinlib.P2SHAddress.fromRedeemScript( p2wpkhScript, @@ -226,7 +225,7 @@ class Bitcoin extends Bip39HDCurrency } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -241,6 +240,7 @@ class Bitcoin extends Bip39HDCurrency isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -256,6 +256,7 @@ class Bitcoin extends Bip39HDCurrency isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test4: @@ -271,6 +272,7 @@ class Bitcoin extends Bip39HDCurrency isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart index d1f22227e..330d3cb86 100644 --- a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart +++ b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart @@ -60,7 +60,7 @@ class BitcoinFrost extends FrostCurrency { bool get torSupport => true; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -75,6 +75,7 @@ class BitcoinFrost extends FrostCurrency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -90,6 +91,7 @@ class BitcoinFrost extends FrostCurrency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test4: @@ -105,6 +107,7 @@ class BitcoinFrost extends FrostCurrency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -127,10 +130,8 @@ class BitcoinFrost extends FrostCurrency { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(294), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(294), fractionDigits: fractionDigits); @override Uint8List addressToPubkey({required String address}) { @@ -222,7 +223,8 @@ class BitcoinFrost extends FrostCurrency { int get targetBlockTimeSeconds => 600; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/bitcoincash.dart b/lib/wallets/crypto_currency/coins/bitcoincash.dart index 6f6d5e4b5..6ea2a8c3e 100644 --- a/lib/wallets/crypto_currency/coins/bitcoincash.dart +++ b/lib/wallets/crypto_currency/coins/bitcoincash.dart @@ -65,9 +65,9 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - if (network != CryptoCurrencyNetwork.test) DerivePathType.bch44, - ]; + DerivePathType.bip44, + if (network != CryptoCurrencyNetwork.test) DerivePathType.bch44, + ]; @override String get genesisHash { @@ -82,10 +82,8 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(546), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(546), fractionDigits: fractionDigits); @override coinlib.Network get networkParams { @@ -285,7 +283,7 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -300,6 +298,7 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -315,6 +314,7 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/cardano.dart b/lib/wallets/crypto_currency/coins/cardano.dart index 71ea2c372..976093a03 100644 --- a/lib/wallets/crypto_currency/coins/cardano.dart +++ b/lib/wallets/crypto_currency/coins/cardano.dart @@ -52,7 +52,8 @@ class Cardano extends Bip39Currency { switch (network) { case CryptoCurrencyNetwork.main: return Uri.parse( - "https://explorer.cardano.org/en/transaction?id=$txid"); + "https://explorer.cardano.org/en/transaction?id=$txid", + ); default: throw Exception( "Unsupported network for defaultBlockExplorer(): $network", @@ -64,7 +65,7 @@ class Cardano extends Bip39Currency { DerivePathType get defaultDerivePathType => DerivePathType.cardanoShelley; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -79,6 +80,7 @@ class Cardano extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/dash.dart b/lib/wallets/crypto_currency/coins/dash.dart index 1a63f1811..e2ad041ea 100644 --- a/lib/wallets/crypto_currency/coins/dash.dart +++ b/lib/wallets/crypto_currency/coins/dash.dart @@ -52,8 +52,8 @@ class Dash extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - ]; + DerivePathType.bip44, + ]; @override String constructDerivePath({ @@ -89,10 +89,8 @@ class Dash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(1000000), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(1000000), fractionDigits: fractionDigits); @override String get genesisHash { @@ -107,10 +105,7 @@ class Dash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - ({ - coinlib.Address address, - AddressType addressType, - }) getAddressForPublicKey({ + ({coinlib.Address address, AddressType addressType}) getAddressForPublicKey({ required coinlib.ECPublicKey publicKey, required DerivePathType derivePathType, }) { @@ -176,7 +171,7 @@ class Dash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -191,6 +186,7 @@ class Dash extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/dogecoin.dart b/lib/wallets/crypto_currency/coins/dogecoin.dart index ce10bc0d7..1d281f5bb 100644 --- a/lib/wallets/crypto_currency/coins/dogecoin.dart +++ b/lib/wallets/crypto_currency/coins/dogecoin.dart @@ -52,8 +52,8 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - ]; + DerivePathType.bip44, + ]; @override String constructDerivePath({ @@ -89,10 +89,8 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(1000000), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(1000000), fractionDigits: fractionDigits); @override String get genesisHash { @@ -107,10 +105,7 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - ({ - coinlib.Address address, - AddressType addressType, - }) getAddressForPublicKey({ + ({coinlib.Address address, AddressType addressType}) getAddressForPublicKey({ required coinlib.ECPublicKey publicKey, required DerivePathType derivePathType, }) { @@ -176,7 +171,7 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -191,6 +186,7 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -206,6 +202,7 @@ class Dogecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/ecash.dart b/lib/wallets/crypto_currency/coins/ecash.dart index 4074b249d..a41a47394 100644 --- a/lib/wallets/crypto_currency/coins/ecash.dart +++ b/lib/wallets/crypto_currency/coins/ecash.dart @@ -60,9 +60,9 @@ class Ecash extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.eCash44, - DerivePathType.bip44, - ]; + DerivePathType.eCash44, + DerivePathType.bip44, + ]; @override String get genesisHash { @@ -77,10 +77,8 @@ class Ecash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(546), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(546), fractionDigits: fractionDigits); @override coinlib.Network get networkParams { @@ -276,7 +274,7 @@ class Ecash extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -291,6 +289,7 @@ class Ecash extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/epiccash.dart b/lib/wallets/crypto_currency/coins/epiccash.dart index 25fdd6c9c..d35c0fb74 100644 --- a/lib/wallets/crypto_currency/coins/epiccash.dart +++ b/lib/wallets/crypto_currency/coins/epiccash.dart @@ -67,7 +67,7 @@ class Epiccash extends Bip39Currency { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -82,6 +82,7 @@ class Epiccash extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -114,7 +115,8 @@ class Epiccash extends Bip39Currency { int get targetBlockTimeSeconds => 60; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/ethereum.dart b/lib/wallets/crypto_currency/coins/ethereum.dart index cd908b9e6..f6f3601a1 100644 --- a/lib/wallets/crypto_currency/coins/ethereum.dart +++ b/lib/wallets/crypto_currency/coins/ethereum.dart @@ -48,7 +48,7 @@ class Ethereum extends Bip39Currency { bool get hasTokenSupport => true; @override - NodeModel get defaultNode => NodeModel( + NodeModel defaultNode({required bool isPrimary}) => NodeModel( host: "https://eth2.stackwallet.com", port: 443, name: DefaultNodes.defaultName, @@ -60,6 +60,7 @@ class Ethereum extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); @override diff --git a/lib/wallets/crypto_currency/coins/fact0rn.dart b/lib/wallets/crypto_currency/coins/fact0rn.dart index 84fc902b5..a168c9dec 100644 --- a/lib/wallets/crypto_currency/coins/fact0rn.dart +++ b/lib/wallets/crypto_currency/coins/fact0rn.dart @@ -171,7 +171,7 @@ class Fact0rn extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -186,6 +186,7 @@ class Fact0rn extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: false, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/firo.dart b/lib/wallets/crypto_currency/coins/firo.dart index 79ed783f8..f432bd77b 100644 --- a/lib/wallets/crypto_currency/coins/firo.dart +++ b/lib/wallets/crypto_currency/coins/firo.dart @@ -62,8 +62,8 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - ]; + DerivePathType.bip44, + ]; @override String get genesisHash { @@ -78,10 +78,8 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(1000), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(1000), fractionDigits: fractionDigits); Uint8List get exAddressVersion { switch (network) { @@ -207,10 +205,7 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { bool isExchangeAddress(String address) { try { - EXP2PKHAddress.fromString( - address, - exAddressVersion, - ); + EXP2PKHAddress.fromString(address, exAddressVersion); return true; } catch (_) { return false; @@ -218,7 +213,7 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -233,6 +228,7 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -248,6 +244,7 @@ class Firo extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/litecoin.dart b/lib/wallets/crypto_currency/coins/litecoin.dart index 91b444f73..4ab8ec0c2 100644 --- a/lib/wallets/crypto_currency/coins/litecoin.dart +++ b/lib/wallets/crypto_currency/coins/litecoin.dart @@ -56,10 +56,10 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - DerivePathType.bip49, - DerivePathType.bip84, - ]; + DerivePathType.bip44, + DerivePathType.bip49, + DerivePathType.bip84, + ]; @override String get genesisHash { @@ -74,15 +74,11 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - Amount get dustLimit => Amount( - rawValue: BigInt.from(294), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(294), fractionDigits: fractionDigits); - Amount get dustLimitP2PKH => Amount( - rawValue: BigInt.from(546), - fractionDigits: fractionDigits, - ); + Amount get dustLimitP2PKH => + Amount(rawValue: BigInt.from(546), fractionDigits: fractionDigits); @override coinlib.Network get networkParams { @@ -171,10 +167,11 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { return (address: addr, addressType: AddressType.p2pkh); case DerivePathType.bip49: - final p2wpkhScript = coinlib.P2WPKHAddress.fromPublicKey( - publicKey, - hrp: networkParams.bech32Hrp, - ).program.script; + final p2wpkhScript = + coinlib.P2WPKHAddress.fromPublicKey( + publicKey, + hrp: networkParams.bech32Hrp, + ).program.script; final addr = coinlib.P2SHAddress.fromRedeemScript( p2wpkhScript, @@ -207,7 +204,7 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -222,6 +219,7 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -237,6 +235,7 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/monero.dart b/lib/wallets/crypto_currency/coins/monero.dart index 4cbeeeb68..4d1535179 100644 --- a/lib/wallets/crypto_currency/coins/monero.dart +++ b/lib/wallets/crypto_currency/coins/monero.dart @@ -61,7 +61,7 @@ class Monero extends CryptonoteCurrency { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -77,6 +77,7 @@ class Monero extends CryptonoteCurrency { trusted: true, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -106,7 +107,8 @@ class Monero extends CryptonoteCurrency { int get targetBlockTimeSeconds => 120; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/namecoin.dart b/lib/wallets/crypto_currency/coins/namecoin.dart index 77940784e..7945e8bca 100644 --- a/lib/wallets/crypto_currency/coins/namecoin.dart +++ b/lib/wallets/crypto_currency/coins/namecoin.dart @@ -89,7 +89,7 @@ class Namecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -104,6 +104,7 @@ class Namecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); // case CryptoCurrencyNetwork.test: // TODO: [prio=low] Add testnet support. @@ -114,10 +115,8 @@ class Namecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override // See https://github.com/cypherstack/stack_wallet/blob/621aff47969761014e0a6c4e699cb637d5687ab3/lib/services/coins/namecoin/namecoin_wallet.dart#L60 - Amount get dustLimit => Amount( - rawValue: BigInt.from(546), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(546), fractionDigits: fractionDigits); @override // See https://github.com/cypherstack/stack_wallet/blob/621aff47969761014e0a6c4e699cb637d5687ab3/lib/services/coins/namecoin/namecoin_wallet.dart#L6 @@ -149,10 +148,11 @@ class Namecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { return (address: addr, addressType: AddressType.p2pkh); case DerivePathType.bip49: - final p2wpkhScript = coinlib.P2WPKHAddress.fromPublicKey( - publicKey, - hrp: networkParams.bech32Hrp, - ).program.script; + final p2wpkhScript = + coinlib.P2WPKHAddress.fromPublicKey( + publicKey, + hrp: networkParams.bech32Hrp, + ).program.script; final addr = coinlib.P2SHAddress.fromRedeemScript( p2wpkhScript, @@ -200,11 +200,11 @@ class Namecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - // DerivePathType.bip16, - DerivePathType.bip44, - DerivePathType.bip49, - DerivePathType.bip84, - ]; + // DerivePathType.bip16, + DerivePathType.bip44, + DerivePathType.bip49, + DerivePathType.bip84, + ]; @override bool validateAddress(String address) { diff --git a/lib/wallets/crypto_currency/coins/nano.dart b/lib/wallets/crypto_currency/coins/nano.dart index 0909b8aa8..07f464926 100644 --- a/lib/wallets/crypto_currency/coins/nano.dart +++ b/lib/wallets/crypto_currency/coins/nano.dart @@ -45,9 +45,7 @@ class Nano extends NanoCurrency { int get fractionDigits => 30; @override - BigInt get satsPerCoin => BigInt.parse( - "1000000000000000000000000000000", - ); // 1*10^30 + BigInt get satsPerCoin => BigInt.parse("1000000000000000000000000000000"); // 1*10^30 @override int get minConfirms => 1; @@ -63,7 +61,7 @@ class Nano extends NanoCurrency { int get nanoAccountType => NanoAccountType.NANO; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -79,6 +77,7 @@ class Nano extends NanoCurrency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -87,7 +86,8 @@ class Nano extends NanoCurrency { } @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/particl.dart b/lib/wallets/crypto_currency/coins/particl.dart index 8788b6114..2b07aad7e 100644 --- a/lib/wallets/crypto_currency/coins/particl.dart +++ b/lib/wallets/crypto_currency/coins/particl.dart @@ -84,7 +84,7 @@ class Particl extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -99,6 +99,7 @@ class Particl extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); // case CryptoCurrencyNetwork.test: // TODO: [prio=low] Add testnet. @@ -109,10 +110,8 @@ class Particl extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override // See https://github.com/cypherstack/stack_wallet/blob/d08b5c9b22b58db800ad07b2ceeb44c6d05f9cf3/lib/services/coins/particl/particl_wallet.dart#L58 - Amount get dustLimit => Amount( - rawValue: BigInt.from(294), - fractionDigits: fractionDigits, - ); + Amount get dustLimit => + Amount(rawValue: BigInt.from(294), fractionDigits: fractionDigits); @override // See https://github.com/cypherstack/stack_wallet/blob/d08b5c9b22b58db800ad07b2ceeb44c6d05f9cf3/lib/services/coins/particl/particl_wallet.dart#L63 @@ -180,9 +179,9 @@ class Particl extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - DerivePathType.bip84, - ]; + DerivePathType.bip44, + DerivePathType.bip84, + ]; @override bool validateAddress(String address) { diff --git a/lib/wallets/crypto_currency/coins/peercoin.dart b/lib/wallets/crypto_currency/coins/peercoin.dart index b67b0e1ab..0515beb4c 100644 --- a/lib/wallets/crypto_currency/coins/peercoin.dart +++ b/lib/wallets/crypto_currency/coins/peercoin.dart @@ -90,7 +90,7 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -105,6 +105,7 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -120,6 +121,7 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -129,10 +131,10 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override Amount get dustLimit => Amount( - // TODO should this be 10000 instead of 294 for peercoin? - rawValue: BigInt.from(294), - fractionDigits: fractionDigits, - ); + // TODO should this be 10000 instead of 294 for peercoin? + rawValue: BigInt.from(294), + fractionDigits: fractionDigits, + ); @override String get genesisHash { @@ -163,10 +165,11 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { return (address: addr, addressType: AddressType.p2pkh); case DerivePathType.bip49: - final p2wpkhScript = coinlib.P2WPKHAddress.fromPublicKey( - publicKey, - hrp: networkParams.bech32Hrp, - ).program.script; + final p2wpkhScript = + coinlib.P2WPKHAddress.fromPublicKey( + publicKey, + hrp: networkParams.bech32Hrp, + ).program.script; final addr = coinlib.P2SHAddress.fromRedeemScript( p2wpkhScript, @@ -202,9 +205,9 @@ class Peercoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { @override List get supportedDerivationPathTypes => [ - DerivePathType.bip44, - DerivePathType.bip84, - ]; + DerivePathType.bip44, + DerivePathType.bip84, + ]; @override bool validateAddress(String address) { diff --git a/lib/wallets/crypto_currency/coins/salvium.dart b/lib/wallets/crypto_currency/coins/salvium.dart index 1bbe599a3..d7618094c 100644 --- a/lib/wallets/crypto_currency/coins/salvium.dart +++ b/lib/wallets/crypto_currency/coins/salvium.dart @@ -61,7 +61,7 @@ class Salvium extends CryptonoteCurrency { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -77,6 +77,7 @@ class Salvium extends CryptonoteCurrency { trusted: true, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/solana.dart b/lib/wallets/crypto_currency/coins/solana.dart index 1db985c76..39d243a1c 100644 --- a/lib/wallets/crypto_currency/coins/solana.dart +++ b/lib/wallets/crypto_currency/coins/solana.dart @@ -42,7 +42,7 @@ class Solana extends Bip39Currency { String get ticker => _ticker; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -57,6 +57,7 @@ class Solana extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: throw Exception("Unsupported network: $network"); diff --git a/lib/wallets/crypto_currency/coins/stellar.dart b/lib/wallets/crypto_currency/coins/stellar.dart index d799de31b..077564a50 100644 --- a/lib/wallets/crypto_currency/coins/stellar.dart +++ b/lib/wallets/crypto_currency/coins/stellar.dart @@ -50,12 +50,10 @@ class Stellar extends Bip39Currency { bool get torSupport => true; @override - String get genesisHash => throw UnimplementedError( - "Not used for stellar", - ); + String get genesisHash => throw UnimplementedError("Not used for stellar"); @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -70,6 +68,7 @@ class Stellar extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -85,6 +84,7 @@ class Stellar extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -115,15 +115,14 @@ class Stellar extends Bip39Currency { AddressType get defaultAddressType => AddressType.stellar; @override - BigInt get satsPerCoin => BigInt.from( - 10000000, - ); // https://developers.stellar.org/docs/fundamentals-and-concepts/stellar-data-structures/assets#amount-precision + BigInt get satsPerCoin => BigInt.from(10000000); // https://developers.stellar.org/docs/fundamentals-and-concepts/stellar-data-structures/assets#amount-precision @override int get targetBlockTimeSeconds => 5; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/tezos.dart b/lib/wallets/crypto_currency/coins/tezos.dart index 0cb8cca0c..78d3c02ad 100644 --- a/lib/wallets/crypto_currency/coins/tezos.dart +++ b/lib/wallets/crypto_currency/coins/tezos.dart @@ -54,11 +54,11 @@ class Tezos extends Bip39Currency { DerivationPath()..value = "m/44'/1729'/0'/0'"; static List get possibleDerivationPaths => [ - standardDerivationPath, - DerivationPath()..value = "", - DerivationPath()..value = "m/44'/1729'/0'/0'/0'", - DerivationPath()..value = "m/44'/1729'/0'/0/0", - ]; + standardDerivationPath, + DerivationPath()..value = "", + DerivationPath()..value = "m/44'/1729'/0'/0'/0'", + DerivationPath()..value = "m/44'/1729'/0'/0/0", + ]; static Keystore mnemonicToKeyStore({ required String mnemonic, @@ -88,9 +88,8 @@ class Tezos extends Bip39Currency { // =========== Overrides ===================================================== @override - String get genesisHash => throw UnimplementedError( - "Not used in tezos at the moment", - ); + String get genesisHash => + throw UnimplementedError("Not used in tezos at the moment"); @override int get minConfirms => 1; @@ -104,7 +103,7 @@ class Tezos extends Bip39Currency { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -120,6 +119,7 @@ class Tezos extends Bip39Currency { isDown: false, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/coins/wownero.dart b/lib/wallets/crypto_currency/coins/wownero.dart index 2aea90aa8..0c702af40 100644 --- a/lib/wallets/crypto_currency/coins/wownero.dart +++ b/lib/wallets/crypto_currency/coins/wownero.dart @@ -61,7 +61,7 @@ class Wownero extends CryptonoteCurrency { } @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -77,6 +77,7 @@ class Wownero extends CryptonoteCurrency { trusted: true, torEnabled: true, clearnetEnabled: true, + isPrimary: isPrimary, ); default: @@ -106,7 +107,8 @@ class Wownero extends CryptonoteCurrency { int get targetBlockTimeSeconds => 120; @override - DerivePathType get defaultDerivePathType => throw UnsupportedError( + DerivePathType get defaultDerivePathType => + throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); diff --git a/lib/wallets/crypto_currency/coins/xelis.dart b/lib/wallets/crypto_currency/coins/xelis.dart index b05fce216..fc1eaaa20 100644 --- a/lib/wallets/crypto_currency/coins/xelis.dart +++ b/lib/wallets/crypto_currency/coins/xelis.dart @@ -1,3 +1,5 @@ +import 'package:xelis_flutter/src/api/utils.dart' as x_utils; + import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/node_model.dart'; import '../../../utilities/default_nodes.dart'; @@ -5,8 +7,6 @@ import '../../../utilities/enums/derive_path_type_enum.dart'; import '../crypto_currency.dart'; import '../intermediate/electrum_currency.dart'; -import 'package:xelis_flutter/src/api/utils.dart' as x_utils; - class Xelis extends ElectrumCurrency { Xelis(super.network) { _idMain = "xelis"; @@ -46,7 +46,7 @@ class Xelis extends ElectrumCurrency { String get ticker => _ticker; @override - NodeModel get defaultNode { + NodeModel defaultNode({required bool isPrimary}) { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( @@ -61,6 +61,7 @@ class Xelis extends ElectrumCurrency { isDown: false, torEnabled: false, clearnetEnabled: true, + isPrimary: isPrimary, ); case CryptoCurrencyNetwork.test: @@ -76,6 +77,7 @@ class Xelis extends ElectrumCurrency { isDown: false, torEnabled: false, clearnetEnabled: true, + isPrimary: isPrimary, ); default: diff --git a/lib/wallets/crypto_currency/crypto_currency.dart b/lib/wallets/crypto_currency/crypto_currency.dart index 363022e63..4f6c232e6 100644 --- a/lib/wallets/crypto_currency/crypto_currency.dart +++ b/lib/wallets/crypto_currency/crypto_currency.dart @@ -70,7 +70,7 @@ abstract class CryptoCurrency { bool validateAddress(String address); - NodeModel get defaultNode; + NodeModel defaultNode({required bool isPrimary}); int get defaultSeedPhraseLength; int get fractionDigits; diff --git a/lib/wallets/wallet/impl/solana_wallet.dart b/lib/wallets/wallet/impl/solana_wallet.dart index 0b7c2911d..5a5ef7c57 100644 --- a/lib/wallets/wallet/impl/solana_wallet.dart +++ b/lib/wallets/wallet/impl/solana_wallet.dart @@ -371,7 +371,7 @@ class SolanaWallet extends Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); await refresh(); } @@ -381,7 +381,7 @@ class SolanaWallet extends Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); return _solNode!; } diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index ae2183be0..53afa8df9 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -520,7 +520,7 @@ class TezosWallet extends Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); await refresh(); } @@ -531,7 +531,7 @@ class TezosWallet extends Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); } @override diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index 6ea950fe7..c2bfa5b41 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -506,7 +506,7 @@ abstract class Wallet { NodeModel getCurrentNode() { final node = nodeService.getPrimaryNodeFor(currency: cryptoCurrency) ?? - cryptoCurrency.defaultNode; + cryptoCurrency.defaultNode(isPrimary: true); return node; } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart index 4c3233de7..f9efe7975 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart @@ -324,7 +324,7 @@ mixin NanoInterface on Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); unawaited(refresh()); } @@ -335,7 +335,7 @@ mixin NanoInterface on Bip39Wallet { NodeService( secureStorageInterface: secureStorageInterface, ).getPrimaryNodeFor(currency: info.coin) ?? - info.coin.defaultNode; + info.coin.defaultNode(isPrimary: true); } @override diff --git a/test/services/node_service_test.dart b/test/services/node_service_test.dart index 8865c748c..cb0acd6de 100644 --- a/test/services/node_service_test.dart +++ b/test/services/node_service_test.dart @@ -166,8 +166,9 @@ void main() { ); setUp(() async { - await NodeService(secureStorageInterface: FakeSecureStorage()) - .updateDefaults(); + await NodeService( + secureStorageInterface: FakeSecureStorage(), + ).updateDefaults(); }); test("setPrimaryNodeFor and getPrimaryNodeFor", () async { @@ -181,7 +182,7 @@ void main() { ); await service.setPrimaryNodeFor( coin: Bitcoin(CryptoCurrencyNetwork.main), - node: Bitcoin(CryptoCurrencyNetwork.main).defaultNode, + node: Bitcoin(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true), ); expect( service @@ -197,17 +198,17 @@ void main() { final service = NodeService(secureStorageInterface: fakeStore); await service.setPrimaryNodeFor( coin: Bitcoin(CryptoCurrencyNetwork.main), - node: Bitcoin(CryptoCurrencyNetwork.main).defaultNode, + node: Bitcoin(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true), ); await service.setPrimaryNodeFor( coin: Monero(CryptoCurrencyNetwork.main), - node: Monero(CryptoCurrencyNetwork.main).defaultNode, + node: Monero(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true), ); expect( service.primaryNodes.toString(), [ - Bitcoin(CryptoCurrencyNetwork.main).defaultNode, - Monero(CryptoCurrencyNetwork.main).defaultNode, + Bitcoin(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true), + Monero(CryptoCurrencyNetwork.main).defaultNode(isPrimary: true), ].toString(), ); expect(fakeStore.interactions, 0); @@ -217,7 +218,8 @@ void main() { final fakeStore = FakeSecureStorage(); final service = NodeService(secureStorageInterface: fakeStore); final nodes = service.nodes; - final defaults = AppConfig.coins.map((e) => e.defaultNode).toList(); + final defaults = + AppConfig.coins.map((e) => e.defaultNode(isPrimary: true)).toList(); nodes.sort((a, b) => a.id.compareTo(b.id)); defaults.sort((a, b) => a.id.compareTo(b.id)); From b9d15c843327cde2d19024b2f19a931a04e13c22 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 2 Jun 2025 13:36:57 -0600 Subject: [PATCH 121/206] fix file closed error --- lib/db/db_version_migration.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/db/db_version_migration.dart b/lib/db/db_version_migration.dart index 2e5ebf219..9c278ff19 100644 --- a/lib/db/db_version_migration.dart +++ b/lib/db/db_version_migration.dart @@ -669,7 +669,6 @@ class DbVersionMigrator with WalletDB { ); } - await primariesBox.close(); await primariesBox.deleteFromDisk(); } } From bbbea431ab00ac399a5624a887149a86a6268069 Mon Sep 17 00:00:00 2001 From: Julian Date: Mon, 9 Jun 2025 12:22:05 -0600 Subject: [PATCH 122/206] More safearea wraps --- .../mnemonic_word_count_select_sheet.dart | 214 ++++---- lib/pages/wallet_view/wallet_view.dart | 493 +++++++++--------- 2 files changed, 353 insertions(+), 354 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart b/lib/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart index 933b72ba5..6cdaa5423 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart @@ -17,10 +17,7 @@ import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; class MnemonicWordCountSelectSheet extends ConsumerWidget { - const MnemonicWordCountSelectSheet({ - super.key, - required this.lengthOptions, - }); + const MnemonicWordCountSelectSheet({super.key, required this.lengthOptions}); final List lengthOptions; @@ -35,9 +32,7 @@ class MnemonicWordCountSelectSheet extends ConsumerWidget { child: Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(20), - ), + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Padding( padding: const EdgeInsets.only( @@ -46,116 +41,115 @@ class MnemonicWordCountSelectSheet extends ConsumerWidget { top: 10, bottom: 0, ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + child: SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), + width: 60, + height: 4, ), - width: 60, - height: 4, ), - ), - const SizedBox( - height: 36, - ), - // Expanded( - // child: SingleChildScrollView( - // child: - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Phrase length", - style: STextStyles.pageTitleH2(context), - textAlign: TextAlign.left, - ), - const SizedBox( - height: 16, - ), - for (int i = 0; i < lengthOptions.length; i++) - Column( - children: [ - GestureDetector( - onTap: () { - final state = ref - .read(mnemonicWordCountStateProvider.state) - .state; - if (state != lengthOptions[i]) { - ref - .read(mnemonicWordCountStateProvider.state) - .state = lengthOptions[i]; - } + const SizedBox(height: 36), + // Expanded( + // child: SingleChildScrollView( + // child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Phrase length", + style: STextStyles.pageTitleH2(context), + textAlign: TextAlign.left, + ), + const SizedBox(height: 16), + for (int i = 0; i < lengthOptions.length; i++) + Column( + children: [ + GestureDetector( + onTap: () { + final state = + ref + .read( + mnemonicWordCountStateProvider.state, + ) + .state; + if (state != lengthOptions[i]) { + ref + .read(mnemonicWordCountStateProvider.state) + .state = lengthOptions[i]; + } - Navigator.of(context).pop(); - }, - child: Container( - color: Colors.transparent, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - // Column( - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: lengthOptions[i], - groupValue: ref - .watch( - mnemonicWordCountStateProvider.state, - ) - .state, - onChanged: (x) { - ref - .read( - mnemonicWordCountStateProvider - .state, - ) - .state = lengthOptions[i]; - Navigator.of(context).pop(); - }, + Navigator.of(context).pop(); + }, + child: Container( + color: Colors.transparent, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Column( + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: lengthOptions[i], + groupValue: + ref + .watch( + mnemonicWordCountStateProvider + .state, + ) + .state, + onChanged: (x) { + ref + .read( + mnemonicWordCountStateProvider + .state, + ) + .state = lengthOptions[i]; + Navigator.of(context).pop(); + }, + ), ), - ), - // ], - // ), - const SizedBox( - width: 12, - ), - Text( - "${lengthOptions[i]} words", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + // ], + // ), + const SizedBox(width: 12), + Text( + "${lengthOptions[i]} words", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), - ), - const SizedBox( - height: 16, - ), - ], - ), - const SizedBox( - height: 8, - ), - ], - ), - // ), - // ) - ], + const SizedBox(height: 16), + ], + ), + const SizedBox(height: 8), + ], + ), + // ), + // ) + ], + ), ), ), ), diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 2c8c6a301..06697a1d9 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -989,267 +989,272 @@ class _WalletViewState extends ConsumerState { ), ), ), - WalletNavigationBar( - items: [ - WalletNavigationBarItemData( - label: "Receive", - icon: const ReceiveNavIcon(), - onTap: () { - if (mounted) { - unawaited( - Navigator.of(context).pushNamed( - ReceiveView.routeName, - arguments: walletId, - ), - ); - } - }, - ), - if (ref.watch(pWalletCoin(walletId)) is FrostCurrency) - WalletNavigationBarItemData( - label: "Sign", - icon: const FrostSignNavIcon(), - onTap: () => _onFrostSignPressed(context), - ), - if (!viewOnly) - WalletNavigationBarItemData( - label: "Send", - icon: const SendNavIcon(), - onTap: () { - // not sure what this is supposed to accomplish? - // switch (ref - // .read(walletBalanceToggleStateProvider.state) - // .state) { - // case WalletBalanceToggleState.full: - // ref - // .read(publicPrivateBalanceStateProvider.state) - // .state = "Public"; - // break; - // case WalletBalanceToggleState.available: - // ref - // .read(publicPrivateBalanceStateProvider.state) - // .state = "Private"; - // break; - // } - Navigator.of(context).pushNamed( - wallet is BitcoinFrostWallet - ? FrostSendView.routeName - : SendView.routeName, - arguments: (walletId: walletId, coin: coin), - ); - }, - ), - if (!viewOnly && - Constants.enableExchange && - ref.watch(pWalletCoin(walletId)) is! FrostCurrency && - AppConfig.hasFeature(AppFeature.swap) && - showExchange) - WalletNavigationBarItemData( - label: "Swap", - icon: const ExchangeNavIcon(), - onTap: () => _onExchangePressed(context), - ), - if (Constants.enableExchange && - ref.watch(pWalletCoin(walletId)) is! FrostCurrency && - AppConfig.hasFeature(AppFeature.buy) && - showExchange) - WalletNavigationBarItemData( - label: "Buy", - icon: const BuyNavIcon(), - onTap: () => _onBuyPressed(context), - ), - ], - moreItems: [ - if (ref.watch( - pWallets.select( - (value) => - value - .getWallet(widget.walletId) - .cryptoCurrency - .hasTokenSupport, - ), - )) + SafeArea( + child: WalletNavigationBar( + items: [ WalletNavigationBarItemData( - label: "Tokens", - icon: const CoinControlNavIcon(), + label: "Receive", + icon: const ReceiveNavIcon(), onTap: () { - Navigator.of(context).pushNamed( - MyTokensView.routeName, - arguments: walletId, - ); + if (mounted) { + unawaited( + Navigator.of(context).pushNamed( + ReceiveView.routeName, + arguments: walletId, + ), + ); + } }, ), - if (coin is Banano) - WalletNavigationBarItemData( - icon: SvgPicture.asset( - Assets.svg.monkey, - height: 20, - width: 20, - color: - Theme.of( - context, - ).extension()!.bottomNavIconIcon, + if (ref.watch(pWalletCoin(walletId)) is FrostCurrency) + WalletNavigationBarItemData( + label: "Sign", + icon: const FrostSignNavIcon(), + onTap: () => _onFrostSignPressed(context), ), - label: "MonKey", - onTap: () { - Navigator.of(context).pushNamed( - MonkeyView.routeName, - arguments: widget.walletId, - ); - }, - ), - if (wallet is CoinControlInterface && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.enableCoinControl, + if (!viewOnly) + WalletNavigationBarItemData( + label: "Send", + icon: const SendNavIcon(), + onTap: () { + // not sure what this is supposed to accomplish? + // switch (ref + // .read(walletBalanceToggleStateProvider.state) + // .state) { + // case WalletBalanceToggleState.full: + // ref + // .read(publicPrivateBalanceStateProvider.state) + // .state = "Public"; + // break; + // case WalletBalanceToggleState.available: + // ref + // .read(publicPrivateBalanceStateProvider.state) + // .state = "Private"; + // break; + // } + Navigator.of(context).pushNamed( + wallet is BitcoinFrostWallet + ? FrostSendView.routeName + : SendView.routeName, + arguments: (walletId: walletId, coin: coin), + ); + }, + ), + if (!viewOnly && + Constants.enableExchange && + ref.watch(pWalletCoin(walletId)) is! FrostCurrency && + AppConfig.hasFeature(AppFeature.swap) && + showExchange) + WalletNavigationBarItemData( + label: "Swap", + icon: const ExchangeNavIcon(), + onTap: () => _onExchangePressed(context), + ), + if (Constants.enableExchange && + ref.watch(pWalletCoin(walletId)) is! FrostCurrency && + AppConfig.hasFeature(AppFeature.buy) && + showExchange) + WalletNavigationBarItemData( + label: "Buy", + icon: const BuyNavIcon(), + onTap: () => _onBuyPressed(context), + ), + ], + moreItems: [ + if (ref.watch( + pWallets.select( + (value) => + value + .getWallet(widget.walletId) + .cryptoCurrency + .hasTokenSupport, + ), + )) + WalletNavigationBarItemData( + label: "Tokens", + icon: const CoinControlNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + MyTokensView.routeName, + arguments: walletId, + ); + }, + ), + if (coin is Banano) + WalletNavigationBarItemData( + icon: SvgPicture.asset( + Assets.svg.monkey, + height: 20, + width: 20, + color: + Theme.of( + context, + ).extension()!.bottomNavIconIcon, ), - )) - WalletNavigationBarItemData( - label: "Coin control", - icon: const CoinControlNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - CoinControlView.routeName, - arguments: Tuple2( - widget.walletId, - CoinControlViewType.manage, + label: "MonKey", + onTap: () { + Navigator.of(context).pushNamed( + MonkeyView.routeName, + arguments: widget.walletId, + ); + }, + ), + if (wallet is CoinControlInterface && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableCoinControl, ), - ); - }, - ), - if (wallet is FiroWallet && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.advancedFiroFeatures, - ), - )) - WalletNavigationBarItemData( - label: "Spark coins", - icon: const CoinControlNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - SparkCoinsView.routeName, - arguments: widget.walletId, - ); - }, - ), - if (wallet is NamecoinWallet) - WalletNavigationBarItemData( - label: "Domains", - icon: const PaynymNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - NamecoinNamesHomeView.routeName, - arguments: widget.walletId, - ); - }, - ), - if (wallet is SparkInterface) - WalletNavigationBarItemData( - label: "Names", - icon: const PaynymNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - SparkNamesHomeView.routeName, - arguments: widget.walletId, - ); - }, - ), - if (!viewOnly && wallet is PaynymInterface) - WalletNavigationBarItemData( - label: "PayNym", - icon: const PaynymNavIcon(), - onTap: () async { - unawaited( - showDialog( - context: context, - builder: - (context) => const LoadingIndicator(width: 100), + )) + WalletNavigationBarItemData( + label: "Coin control", + icon: const CoinControlNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + CoinControlView.routeName, + arguments: Tuple2( + widget.walletId, + CoinControlViewType.manage, + ), + ); + }, + ), + if (wallet is FiroWallet && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.advancedFiroFeatures, ), - ); + )) + WalletNavigationBarItemData( + label: "Spark coins", + icon: const CoinControlNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + SparkCoinsView.routeName, + arguments: widget.walletId, + ); + }, + ), + if (wallet is NamecoinWallet) + WalletNavigationBarItemData( + label: "Domains", + icon: const PaynymNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + NamecoinNamesHomeView.routeName, + arguments: widget.walletId, + ); + }, + ), + if (wallet is SparkInterface) + WalletNavigationBarItemData( + label: "Names", + icon: const PaynymNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + SparkNamesHomeView.routeName, + arguments: widget.walletId, + ); + }, + ), + if (!viewOnly && wallet is PaynymInterface) + WalletNavigationBarItemData( + label: "PayNym", + icon: const PaynymNavIcon(), + onTap: () async { + unawaited( + showDialog( + context: context, + builder: + (context) => + const LoadingIndicator(width: 100), + ), + ); - final wallet = ref - .read(pWallets) - .getWallet(widget.walletId); + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); - final paynymInterface = wallet as PaynymInterface; + final paynymInterface = wallet as PaynymInterface; - final code = await paynymInterface.getPaymentCode( - isSegwit: false, - ); + final code = await paynymInterface.getPaymentCode( + isSegwit: false, + ); - final account = await ref - .read(paynymAPIProvider) - .nym(code.toString()); + final account = await ref + .read(paynymAPIProvider) + .nym(code.toString()); - Logging.instance.d("my nym account: $account"); + Logging.instance.d("my nym account: $account"); - if (context.mounted) { - Navigator.of(context).pop(); + if (context.mounted) { + Navigator.of(context).pop(); - // check if account exists and for matching code to see if claimed - if (account.value != null && - account.value!.nonSegwitPaymentCode.claimed - // && - // account.value!.segwit - ) { - ref.read(myPaynymAccountStateProvider.state).state = - account.value!; + // check if account exists and for matching code to see if claimed + if (account.value != null && + account.value!.nonSegwitPaymentCode.claimed + // && + // account.value!.segwit + ) { + ref + .read(myPaynymAccountStateProvider.state) + .state = account.value!; - await Navigator.of(context).pushNamed( - PaynymHomeView.routeName, - arguments: widget.walletId, - ); - } else { - await Navigator.of(context).pushNamed( - PaynymClaimView.routeName, - arguments: widget.walletId, - ); + await Navigator.of(context).pushNamed( + PaynymHomeView.routeName, + arguments: widget.walletId, + ); + } else { + await Navigator.of(context).pushNamed( + PaynymClaimView.routeName, + arguments: widget.walletId, + ); + } } - } - }, - ), - if (ref.watch( - pWallets.select( - (value) => - value.getWallet(widget.walletId) is OrdinalsInterface, - ), - )) - WalletNavigationBarItemData( - label: "Ordinals", - icon: const OrdinalsNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - OrdinalsView.routeName, - arguments: widget.walletId, - ); - }, - ), - if (wallet is CashFusionInterface && !viewOnly) - WalletNavigationBarItemData( - label: "Fusion", - icon: const FusionNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - CashFusionView.routeName, - arguments: walletId, - ); - }, - ), - if ((wallet is LibMoneroWallet || - wallet is LibSalviumWallet) && - !viewOnly) - WalletNavigationBarItemData( - label: "Churn", - icon: const ChurnNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - ChurningView.routeName, - arguments: walletId, - ); - }, - ), - ], + }, + ), + if (ref.watch( + pWallets.select( + (value) => + value.getWallet(widget.walletId) + is OrdinalsInterface, + ), + )) + WalletNavigationBarItemData( + label: "Ordinals", + icon: const OrdinalsNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + OrdinalsView.routeName, + arguments: widget.walletId, + ); + }, + ), + if (wallet is CashFusionInterface && !viewOnly) + WalletNavigationBarItemData( + label: "Fusion", + icon: const FusionNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + CashFusionView.routeName, + arguments: walletId, + ); + }, + ), + if ((wallet is LibMoneroWallet || + wallet is LibSalviumWallet) && + !viewOnly) + WalletNavigationBarItemData( + label: "Churn", + icon: const ChurnNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + ChurningView.routeName, + arguments: walletId, + ); + }, + ), + ], + ), ), ], ), From 09c9104269d72620e542e2132fae519cf8471689 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 9 Jun 2025 15:11:39 -0600 Subject: [PATCH 123/206] WIP setup mweb --- .../isar/models/blockchain_data/address.dart | 5 ++++- lib/wallets/wallet/impl/litecoin_wallet.dart | 4 +++- .../mweb_interface.dart | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart diff --git a/lib/models/isar/models/blockchain_data/address.dart b/lib/models/isar/models/blockchain_data/address.dart index cb239bc5e..c1dfb3a24 100644 --- a/lib/models/isar/models/blockchain_data/address.dart +++ b/lib/models/isar/models/blockchain_data/address.dart @@ -175,7 +175,8 @@ enum AddressType { solana, cardanoShelley, xelis, - fact0rn; + fact0rn, + mweb; String get readableName { switch (this) { @@ -217,6 +218,8 @@ enum AddressType { return "Xelis"; case AddressType.fact0rn: return "FACT0RN"; + case AddressType.mweb: + return "MWEB"; } } } diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index e72b8e633..7f0c4fd8b 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -16,6 +16,7 @@ import '../intermediate/bip39_hd_wallet.dart'; import '../wallet_mixin_interfaces/coin_control_interface.dart'; import '../wallet_mixin_interfaces/electrumx_interface.dart'; import '../wallet_mixin_interfaces/extended_keys_interface.dart'; +import '../wallet_mixin_interfaces/mweb_interface.dart'; import '../wallet_mixin_interfaces/ordinals_interface.dart'; import '../wallet_mixin_interfaces/rbf_interface.dart'; @@ -26,7 +27,8 @@ class LitecoinWallet ExtendedKeysInterface, CoinControlInterface, RbfInterface, - OrdinalsInterface { + OrdinalsInterface, + MwebInterface { @override int get isarTransactionVersion => 2; diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart new file mode 100644 index 000000000..1de1577cc --- /dev/null +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -0,0 +1,20 @@ +import 'package:isar/isar.dart'; + +import '../../../models/isar/models/isar_models.dart'; +import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; +import 'electrumx_interface.dart'; + +mixin MwebInterface + on ElectrumXInterface { + // TODO + + Future getCurrentReceivingMwebAddress() async { + return await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.mweb) + .sortByDerivationIndexDesc() + .findFirst(); + } +} From 06d513a1434a49a98977959ad9b5edf89bc2ce62 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 10 Jun 2025 13:51:09 -0600 Subject: [PATCH 124/206] replace barcode_scan2 with mobile_scanner --- .../restore/restore_frost_ms_wallet_view.dart | 2 +- .../restore_wallet_view.dart | 2 +- .../new_contact_address_entry_form.dart | 2 +- lib/pages/buy_view/buy_form.dart | 2 +- .../exchange_step_views/step_2_view.dart | 4 +- .../sub_widgets/transfer_option_widget.dart | 2 +- .../paynym/add_new_paynym_follow_view.dart | 2 +- lib/pages/send_view/frost_ms/recipient.dart | 2 +- lib/pages/send_view/send_view.dart | 2 +- lib/pages/send_view/token_send_view.dart | 2 +- .../add_edit_node_view.dart | 2 +- .../sub_widgets/desktop_token_send.dart | 17 +++++-- lib/utilities/barcode_scanner_interface.dart | 20 ++++++-- lib/widgets/qr_scanner.dart | 48 +++++++++++++++++++ lib/widgets/textfields/frost_step_field.dart | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 18 +++---- scripts/app_config/templates/pubspec.template | 3 +- 18 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 lib/widgets/qr_scanner.dart diff --git a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart index 9b388a5a3..facaeed44 100644 --- a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart @@ -212,7 +212,7 @@ class _RestoreFrostMsWalletViewState await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); configFieldController.text = qrResult.rawContent; diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 535fbe07a..aeb9ff845 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -596,7 +596,7 @@ class _RestoreWalletViewState extends ConsumerState { Future scanMnemonicQr() async { try { - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); final results = AddressUtils.decodeQRSeedData(qrResult.rawContent); diff --git a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart index 818393aec..b6dcd7bde 100644 --- a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart +++ b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart @@ -70,7 +70,7 @@ class _NewContactAddressEntryFormState // .read(shouldShowLockscreenOnResumeStateProvider // .state) // .state = false; - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); // Future.delayed( // const Duration(seconds: 2), diff --git a/lib/pages/buy_view/buy_form.dart b/lib/pages/buy_view/buy_form.dart index d62a2bdc4..c194ec9ee 100644 --- a/lib/pages/buy_view/buy_form.dart +++ b/lib/pages/buy_view/buy_form.dart @@ -693,7 +693,7 @@ class _BuyFormState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); diff --git a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart index 621b981ec..a731bf9df 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart @@ -69,7 +69,7 @@ class _Step2ViewState extends ConsumerState { void _onRefundQrTapped() async { try { - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); final paymentData = AddressUtils.parsePaymentUri( qrResult.rawContent, @@ -122,7 +122,7 @@ class _Step2ViewState extends ConsumerState { void _onToQrTapped() async { try { - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); final paymentData = AddressUtils.parsePaymentUri( qrResult.rawContent, diff --git a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart index 1061eb128..6aaad59c0 100644 --- a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart @@ -236,7 +236,7 @@ class _TransferOptionWidgetState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); final coin = ref.read(pWalletCoin(walletId)); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); diff --git a/lib/pages/paynym/add_new_paynym_follow_view.dart b/lib/pages/paynym/add_new_paynym_follow_view.dart index d74a17429..85e4c3ac7 100644 --- a/lib/pages/paynym/add_new_paynym_follow_view.dart +++ b/lib/pages/paynym/add_new_paynym_follow_view.dart @@ -121,7 +121,7 @@ class _AddNewPaynymFollowViewState await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); final pCodeString = qrResult.rawContent; diff --git a/lib/pages/send_view/frost_ms/recipient.dart b/lib/pages/send_view/frost_ms/recipient.dart index 36122962c..150eecb0b 100644 --- a/lib/pages/send_view/frost_ms/recipient.dart +++ b/lib/pages/send_view/frost_ms/recipient.dart @@ -121,7 +121,7 @@ class _RecipientState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); Logging.instance.d("qrResult content: ${qrResult.rawContent}"); diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 54a2f2f8c..3fca255c7 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -268,7 +268,7 @@ class _SendViewState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); // Future.delayed( // const Duration(seconds: 2), diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 635df7e89..fe7f4bb46 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -151,7 +151,7 @@ class _TokenSendViewState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); // Future.delayed( // const Duration(seconds: 2), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 27b50796d..ca5b825ad 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -377,7 +377,7 @@ class _AddEditNodeViewState extends ConsumerState { } } else { try { - final result = await ref.read(pBarcodeScanner).scan(); + final result = await ref.read(pBarcodeScanner).scan(context: context); await _processQrData(result.rawContent); } on PlatformException catch (e, s) { if (mounted) { diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 34071ea8e..aac8ec01d 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -43,6 +43,7 @@ import '../../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/desktop/qr_code_scanner_dialog.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/eth_fee_form.dart'; import '../../../../widgets/icon_widgets/addressbook_icon.dart'; @@ -420,12 +421,20 @@ class _DesktopTokenSendState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await showDialog( + context: context, + builder: (context) => const QrCodeScannerDialog(), + ); + + if (qrResult == null) { + Logging.instance.w("Qr scanning cancelled"); + return; + } - Logging.instance.d("qrResult content: ${qrResult.rawContent}"); + Logging.instance.d("qrResult content: $qrResult"); final paymentData = AddressUtils.parsePaymentUri( - qrResult.rawContent, + qrResult, logging: Logging.instance, ); @@ -464,7 +473,7 @@ class _DesktopTokenSendState extends ConsumerState { // now check for non standard encoded basic address } else { - _address = qrResult.rawContent.split("\n").first.trim(); + _address = qrResult.split("\n").first.trim(); sendToController.text = _address ?? ""; _updatePreviewButtonState(_address, _amountToSend); diff --git a/lib/utilities/barcode_scanner_interface.dart b/lib/utilities/barcode_scanner_interface.dart index 87b079d03..f8256f2e5 100644 --- a/lib/utilities/barcode_scanner_interface.dart +++ b/lib/utilities/barcode_scanner_interface.dart @@ -10,27 +10,37 @@ import 'dart:io'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; import '../widgets/desktop/primary_button.dart'; import '../widgets/desktop/secondary_button.dart'; +import '../widgets/qr_scanner.dart'; import '../widgets/stack_dialog.dart'; import 'logger.dart'; +class ScanResult { + final String rawContent; + + ScanResult({required this.rawContent}); +} + abstract class BarcodeScannerInterface { - Future scan({ScanOptions options = const ScanOptions()}); + Future scan({required BuildContext context}); } class BarcodeScannerWrapper implements BarcodeScannerInterface { const BarcodeScannerWrapper(); @override - Future scan({ScanOptions options = const ScanOptions()}) async { + Future scan({required BuildContext context}) async { try { - final result = await BarcodeScanner.scan(options: options); - return result; + final data = await showDialog( + context: context, + builder: (context) => const QrScanner(), + ); + + return ScanResult(rawContent: data.toString()); } catch (e) { rethrow; } diff --git a/lib/widgets/qr_scanner.dart b/lib/widgets/qr_scanner.dart new file mode 100644 index 000000000..66941ac9d --- /dev/null +++ b/lib/widgets/qr_scanner.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; + +import '../themes/stack_colors.dart'; +import '../utilities/logger.dart'; +import '../utilities/text_styles.dart'; +import 'background.dart'; +import 'custom_buttons/app_bar_icon_button.dart'; + +class QrScanner extends ConsumerWidget { + const QrScanner({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Background( + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.backgroundAppBar, + leading: const AppBarBackButton(), + title: Text("Scan QR code", style: STextStyles.navBarTitle(context)), + ), + body: MobileScanner( + onDetect: (capture) { + final data = + ((capture.raw as Map?)?["data"] as List?)?.firstOrNull as Map?; + + final value = + data?["rawValue"] as String? ?? + data?["displayValue"] as String?; + + Navigator.of(context).pop(value); + }, + onDetectError: (error, stackTrace) { + Logging.instance.w( + "Mobile scanner", + error: error, + stackTrace: stackTrace, + ); + Navigator.of(context).pop(); + }, + ), + ), + ); + } +} diff --git a/lib/widgets/textfields/frost_step_field.dart b/lib/widgets/textfields/frost_step_field.dart index 31364555b..f94fac2b4 100644 --- a/lib/widgets/textfields/frost_step_field.dart +++ b/lib/widgets/textfields/frost_step_field.dart @@ -79,7 +79,7 @@ class _FrostStepFieldState extends ConsumerState { await Future.delayed(const Duration(milliseconds: 75)); } - final qrResult = await ref.read(pBarcodeScanner).scan(); + final qrResult = await ref.read(pBarcodeScanner).scan(context: context); widget.controller.text = qrResult.rawContent; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d2bf8597f..b30b6bead 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -18,6 +18,7 @@ import flutter_local_notifications import flutter_secure_storage_macos import isar_flutter_libs import local_auth_darwin +import mobile_scanner import package_info_plus import path_provider_foundation import share_plus @@ -41,6 +42,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin")) FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) + MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) diff --git a/pubspec.lock b/pubspec.lock index c5dda1160..c5630097a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -70,14 +70,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.12.0" - barcode_scan2: - dependency: "direct main" - description: - name: barcode_scan2 - sha256: efbe38629e6df2200e4d60ebe252e8e041cd5ae7b50f194a20f01779ade9d1c3 - url: "https://pub.dev" - source: hosted - version: "4.5.0" basic_utils: dependency: "direct main" description: @@ -1229,7 +1221,7 @@ packages: source: hosted version: "1.0.3" image: - dependency: transitive + dependency: "direct main" description: name: image sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d @@ -1482,6 +1474,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + sha256: "54005bdea7052d792d35b4fef0f84ec5ddc3a844b250ecd48dc192fb9b4ebc95" + url: "https://pub.dev" + source: hosted + version: "7.0.1" mockingjay: dependency: "direct dev" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index e70887c87..45cf268ff 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -122,7 +122,8 @@ dependencies: event_bus: ^2.0.0 uuid: ^3.0.5 crypto: ^3.0.2 - barcode_scan2: ^4.5.0 + mobile_scanner: ^7.0.1 + image: ^4.3.0 wakelock_plus: ^1.2.8 intl: ^0.17.0 devicelocale: From a28b629ef3726d00214fc4d0c5471c5e6976e3cc Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 10 Jun 2025 16:32:26 -0600 Subject: [PATCH 125/206] update fusiondart --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c5630097a..274c5a07d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1111,8 +1111,8 @@ packages: dependency: "direct main" description: path: "." - ref: "9dc883f4432c8db4ec44cb8cc836963295d63952" - resolved-ref: "9dc883f4432c8db4ec44cb8cc836963295d63952" + ref: afaad488f5215a9c2c211e5e2f8460237eef60f1 + resolved-ref: afaad488f5215a9c2c211e5e2f8460237eef60f1 url: "https://github.com/cypherstack/fusiondart.git" source: git version: "1.0.0" diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 45cf268ff..02a8b55f5 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -70,7 +70,7 @@ dependencies: fusiondart: git: url: https://github.com/cypherstack/fusiondart.git - ref: 9dc883f4432c8db4ec44cb8cc836963295d63952 + ref: afaad488f5215a9c2c211e5e2f8460237eef60f1 # Utility plugins http: ^0.13.0 From 518888ae3ad43ae7b537d99e3a00e401e052c6ff Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 10 Jun 2025 16:34:36 -0600 Subject: [PATCH 126/206] add mweb dependencies --- linux/flutter/generated_plugins.cmake | 1 + pubspec.lock | 54 +++++++++++++++++-- scripts/app_config/templates/pubspec.template | 2 + windows/flutter/generated_plugins.cmake | 1 + 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 8bca8e723..239136a98 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -20,6 +20,7 @@ list(APPEND FLUTTER_FFI_PLUGIN_LIST camera_linux coinlib_flutter flutter_libsparkmobile + flutter_mwebd frostdart tor_ffi_plugin xelis_flutter diff --git a/pubspec.lock b/pubspec.lock index 274c5a07d..563118121 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -981,6 +981,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.2.0" + flutter_mwebd: + dependency: "direct main" + description: + name: flutter_mwebd + sha256: b390f5c99aaddec5d4c785c6c3d96b786b4eb333e5e1fd0051079cec1aacf40a + url: "https://pub.dev" + source: hosted + version: "0.0.1-pre.1" flutter_native_splash: dependency: "direct main" description: @@ -1132,6 +1140,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.5" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" + url: "https://pub.dev" + source: hosted + version: "0.3.3+1" + googleapis_auth: + dependency: transitive + description: + name: googleapis_auth + sha256: b81fe352cc4a330b3710d2b7ad258d9bcef6f909bb759b306bf42973a7d046db + url: "https://pub.dev" + source: hosted + version: "2.0.0" graphs: dependency: transitive description: @@ -1140,6 +1164,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + grpc: + dependency: transitive + description: + name: grpc + sha256: "30e1edae6846b163a64f6d8716e3443980fe1f7d2d1f086f011d24ea186f2582" + url: "https://pub.dev" + source: hosted + version: "4.0.4" hex: dependency: "direct main" description: @@ -1196,6 +1228,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.6" + http2: + dependency: transitive + description: + name: http2 + sha256: "382d3aefc5bd6dc68c6b892d7664f29b5beb3251611ae946a98d35158a82bbfa" + url: "https://pub.dev" + source: hosted + version: "2.3.1" http_multi_server: dependency: transitive description: @@ -1522,6 +1562,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0" + mweb_client: + dependency: "direct main" + description: + name: mweb_client + sha256: "8c9498adaaa1166a49ee114b03498268aff176778eeb311ed049fd22657feacb" + url: "https://pub.dev" + source: hosted + version: "0.1.0" namecoin: dependency: "direct main" description: @@ -1767,10 +1815,10 @@ packages: dependency: transitive description: name: protobuf - sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + sha256: "579fe5557eae58e3adca2e999e38f02441d8aa908703854a9e0a0f47fa857731" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.1.0" pub_semver: dependency: transitive description: @@ -2513,5 +2561,5 @@ packages: source: hosted version: "0.2.3" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.7.2 <4.0.0" flutter: ">=3.29.0" diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 02a8b55f5..3fa0f3077 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -221,6 +221,8 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 + flutter_mwebd: ^0.0.1-pre.1 + mweb_client: ^0.1.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b7bea9e3f..ac0ec291d 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -23,6 +23,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST coinlib_flutter flutter_libsparkmobile + flutter_mwebd frostdart tor_ffi_plugin xelis_flutter From a41a5fa666121616ebd362ca428e3438f6948deb Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 11 Jun 2025 15:33:25 -0600 Subject: [PATCH 127/206] WIP drift mweb outputs and build runner gen updates --- lib/db/drift/database.dart | 26 +- lib/db/drift/database.g.dart | 1120 ++++++++++++++--- .../models/blockchain_data/address.g.dart | 4 + lib/wallets/isar/models/wallet_info.g.dart | 4 + test/cached_electrumx_test.mocks.dart | 15 + .../pages/send_view/send_view_test.mocks.dart | 36 +- ...d_address_book_view_screen_test.mocks.dart | 45 +- .../exchange/exchange_view_test.mocks.dart | 15 + .../lockscreen_view_screen_test.mocks.dart | 21 +- .../create_pin_view_screen_test.mocks.dart | 21 +- ...restore_wallet_view_screen_test.mocks.dart | 94 +- ...dd_custom_node_view_screen_test.mocks.dart | 21 +- .../node_details_view_screen_test.mocks.dart | 21 +- ...twork_settings_view_screen_test.mocks.dart | 21 +- ...allet_settings_view_screen_test.mocks.dart | 107 +- .../send_view_screen_test.mocks.dart | 19 +- .../bitcoin/bitcoin_wallet_test.mocks.dart | 37 - .../bitcoincash_wallet_test.mocks.dart | 37 - .../dogecoin/dogecoin_wallet_test.mocks.dart | 37 - .../namecoin/namecoin_wallet_test.mocks.dart | 37 - .../particl/particl_wallet_test.mocks.dart | 37 - .../managed_favorite_test.mocks.dart | 36 +- test/widget_tests/node_card_test.mocks.dart | 21 +- .../node_options_sheet_test.mocks.dart | 36 +- .../transaction_card_test.mocks.dart | 26 +- ...et_info_row_balance_future_test.mocks.dart | 21 +- .../wallet_info_row_test.mocks.dart | 21 +- 27 files changed, 1197 insertions(+), 739 deletions(-) diff --git a/lib/db/drift/database.dart b/lib/db/drift/database.dart index 36cb67150..c2ed93a46 100644 --- a/lib/db/drift/database.dart +++ b/lib/db/drift/database.dart @@ -44,13 +44,35 @@ class SparkNames extends Table { Set get primaryKey => {name}; } -@DriftDatabase(tables: [SparkNames]) +class MwebUtxos extends Table { + TextColumn get outputId => text()(); + TextColumn get address => text()(); + IntColumn get value => integer()(); + IntColumn get height => integer()(); + IntColumn get blockTime => integer()(); + BoolColumn get blocked => boolean()(); + BoolColumn get used => boolean()(); + + @override + Set get primaryKey => {outputId}; +} + +@DriftDatabase(tables: [SparkNames, MwebUtxos]) final class WalletDatabase extends _$WalletDatabase { WalletDatabase._(String walletId, [QueryExecutor? executor]) : super(executor ?? _openConnection(walletId)); @override - int get schemaVersion => 1; + int get schemaVersion => 2; + + @override + MigrationStrategy get migration => MigrationStrategy( + onUpgrade: (m, from, to) async { + if (from == 1 && to == 2) { + await m.createTable(mwebUtxos); + } + }, + ); static QueryExecutor _openConnection(String walletId) { return driftDatabase( diff --git a/lib/db/drift/database.g.dart b/lib/db/drift/database.g.dart index 42113b071..416fa4170 100644 --- a/lib/db/drift/database.g.dart +++ b/lib/db/drift/database.g.dart @@ -12,66 +12,97 @@ class $SparkNamesTable extends SparkNames static const VerificationMeta _nameMeta = const VerificationMeta('name'); @override late final GeneratedColumn name = GeneratedColumn( - 'name', aliasedName, false, - type: DriftSqlType.string, - requiredDuringInsert: true, - $customConstraints: 'UNIQUE NOT NULL COLLATE NOCASE'); - static const VerificationMeta _addressMeta = - const VerificationMeta('address'); + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'UNIQUE NOT NULL COLLATE NOCASE', + ); + static const VerificationMeta _addressMeta = const VerificationMeta( + 'address', + ); @override late final GeneratedColumn address = GeneratedColumn( - 'address', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _validUntilMeta = - const VerificationMeta('validUntil'); + 'address', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _validUntilMeta = const VerificationMeta( + 'validUntil', + ); @override late final GeneratedColumn validUntil = GeneratedColumn( - 'valid_until', aliasedName, false, - type: DriftSqlType.int, requiredDuringInsert: true); - static const VerificationMeta _additionalInfoMeta = - const VerificationMeta('additionalInfo'); + 'valid_until', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _additionalInfoMeta = const VerificationMeta( + 'additionalInfo', + ); @override late final GeneratedColumn additionalInfo = GeneratedColumn( - 'additional_info', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); + 'additional_info', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); @override - List get $columns => - [name, address, validUntil, additionalInfo]; + List get $columns => [ + name, + address, + validUntil, + additionalInfo, + ]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; static const String $name = 'spark_names'; @override - VerificationContext validateIntegrity(Insertable instance, - {bool isInserting = false}) { + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { final context = VerificationContext(); final data = instance.toColumns(true); if (data.containsKey('name')) { context.handle( - _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); } else if (isInserting) { context.missing(_nameMeta); } if (data.containsKey('address')) { - context.handle(_addressMeta, - address.isAcceptableOrUnknown(data['address']!, _addressMeta)); + context.handle( + _addressMeta, + address.isAcceptableOrUnknown(data['address']!, _addressMeta), + ); } else if (isInserting) { context.missing(_addressMeta); } if (data.containsKey('valid_until')) { context.handle( - _validUntilMeta, - validUntil.isAcceptableOrUnknown( - data['valid_until']!, _validUntilMeta)); + _validUntilMeta, + validUntil.isAcceptableOrUnknown(data['valid_until']!, _validUntilMeta), + ); } else if (isInserting) { context.missing(_validUntilMeta); } if (data.containsKey('additional_info')) { context.handle( + _additionalInfoMeta, + additionalInfo.isAcceptableOrUnknown( + data['additional_info']!, _additionalInfoMeta, - additionalInfo.isAcceptableOrUnknown( - data['additional_info']!, _additionalInfoMeta)); + ), + ); } return context; } @@ -82,14 +113,25 @@ class $SparkNamesTable extends SparkNames SparkName map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return SparkName( - name: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}name'])!, - address: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}address'])!, - validUntil: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}valid_until'])!, - additionalInfo: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}additional_info']), + name: + attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + address: + attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}address'], + )!, + validUntil: + attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}valid_until'], + )!, + additionalInfo: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}additional_info'], + ), ); } @@ -104,11 +146,12 @@ class SparkName extends DataClass implements Insertable { final String address; final int validUntil; final String? additionalInfo; - const SparkName( - {required this.name, - required this.address, - required this.validUntil, - this.additionalInfo}); + const SparkName({ + required this.name, + required this.address, + required this.validUntil, + this.additionalInfo, + }); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -126,14 +169,17 @@ class SparkName extends DataClass implements Insertable { name: Value(name), address: Value(address), validUntil: Value(validUntil), - additionalInfo: additionalInfo == null && nullToAbsent - ? const Value.absent() - : Value(additionalInfo), + additionalInfo: + additionalInfo == null && nullToAbsent + ? const Value.absent() + : Value(additionalInfo), ); } - factory SparkName.fromJson(Map json, - {ValueSerializer? serializer}) { + factory SparkName.fromJson( + Map json, { + ValueSerializer? serializer, + }) { serializer ??= driftRuntimeOptions.defaultSerializer; return SparkName( name: serializer.fromJson(json['name']), @@ -153,27 +199,28 @@ class SparkName extends DataClass implements Insertable { }; } - SparkName copyWith( - {String? name, - String? address, - int? validUntil, - Value additionalInfo = const Value.absent()}) => - SparkName( - name: name ?? this.name, - address: address ?? this.address, - validUntil: validUntil ?? this.validUntil, - additionalInfo: - additionalInfo.present ? additionalInfo.value : this.additionalInfo, - ); + SparkName copyWith({ + String? name, + String? address, + int? validUntil, + Value additionalInfo = const Value.absent(), + }) => SparkName( + name: name ?? this.name, + address: address ?? this.address, + validUntil: validUntil ?? this.validUntil, + additionalInfo: + additionalInfo.present ? additionalInfo.value : this.additionalInfo, + ); SparkName copyWithCompanion(SparkNamesCompanion data) { return SparkName( name: data.name.present ? data.name.value : this.name, address: data.address.present ? data.address.value : this.address, validUntil: data.validUntil.present ? data.validUntil.value : this.validUntil, - additionalInfo: data.additionalInfo.present - ? data.additionalInfo.value - : this.additionalInfo, + additionalInfo: + data.additionalInfo.present + ? data.additionalInfo.value + : this.additionalInfo, ); } @@ -219,9 +266,9 @@ class SparkNamesCompanion extends UpdateCompanion { required int validUntil, this.additionalInfo = const Value.absent(), this.rowid = const Value.absent(), - }) : name = Value(name), - address = Value(address), - validUntil = Value(validUntil); + }) : name = Value(name), + address = Value(address), + validUntil = Value(validUntil); static Insertable custom({ Expression? name, Expression? address, @@ -238,12 +285,13 @@ class SparkNamesCompanion extends UpdateCompanion { }); } - SparkNamesCompanion copyWith( - {Value? name, - Value? address, - Value? validUntil, - Value? additionalInfo, - Value? rowid}) { + SparkNamesCompanion copyWith({ + Value? name, + Value? address, + Value? validUntil, + Value? additionalInfo, + Value? rowid, + }) { return SparkNamesCompanion( name: name ?? this.name, address: address ?? this.address, @@ -287,31 +335,503 @@ class SparkNamesCompanion extends UpdateCompanion { } } +class $MwebUtxosTable extends MwebUtxos + with TableInfo<$MwebUtxosTable, MwebUtxo> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $MwebUtxosTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _outputIdMeta = const VerificationMeta( + 'outputId', + ); + @override + late final GeneratedColumn outputId = GeneratedColumn( + 'output_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _addressMeta = const VerificationMeta( + 'address', + ); + @override + late final GeneratedColumn address = GeneratedColumn( + 'address', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _valueMeta = const VerificationMeta('value'); + @override + late final GeneratedColumn value = GeneratedColumn( + 'value', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _heightMeta = const VerificationMeta('height'); + @override + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _blockTimeMeta = const VerificationMeta( + 'blockTime', + ); + @override + late final GeneratedColumn blockTime = GeneratedColumn( + 'block_time', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _blockedMeta = const VerificationMeta( + 'blocked', + ); + @override + late final GeneratedColumn blocked = GeneratedColumn( + 'blocked', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("blocked" IN (0, 1))', + ), + ); + static const VerificationMeta _usedMeta = const VerificationMeta('used'); + @override + late final GeneratedColumn used = GeneratedColumn( + 'used', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("used" IN (0, 1))', + ), + ); + @override + List get $columns => [ + outputId, + address, + value, + height, + blockTime, + blocked, + used, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'mweb_utxos'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('output_id')) { + context.handle( + _outputIdMeta, + outputId.isAcceptableOrUnknown(data['output_id']!, _outputIdMeta), + ); + } else if (isInserting) { + context.missing(_outputIdMeta); + } + if (data.containsKey('address')) { + context.handle( + _addressMeta, + address.isAcceptableOrUnknown(data['address']!, _addressMeta), + ); + } else if (isInserting) { + context.missing(_addressMeta); + } + if (data.containsKey('value')) { + context.handle( + _valueMeta, + value.isAcceptableOrUnknown(data['value']!, _valueMeta), + ); + } else if (isInserting) { + context.missing(_valueMeta); + } + if (data.containsKey('height')) { + context.handle( + _heightMeta, + height.isAcceptableOrUnknown(data['height']!, _heightMeta), + ); + } else if (isInserting) { + context.missing(_heightMeta); + } + if (data.containsKey('block_time')) { + context.handle( + _blockTimeMeta, + blockTime.isAcceptableOrUnknown(data['block_time']!, _blockTimeMeta), + ); + } else if (isInserting) { + context.missing(_blockTimeMeta); + } + if (data.containsKey('blocked')) { + context.handle( + _blockedMeta, + blocked.isAcceptableOrUnknown(data['blocked']!, _blockedMeta), + ); + } else if (isInserting) { + context.missing(_blockedMeta); + } + if (data.containsKey('used')) { + context.handle( + _usedMeta, + used.isAcceptableOrUnknown(data['used']!, _usedMeta), + ); + } else if (isInserting) { + context.missing(_usedMeta); + } + return context; + } + + @override + Set get $primaryKey => {outputId}; + @override + MwebUtxo map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MwebUtxo( + outputId: + attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}output_id'], + )!, + address: + attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}address'], + )!, + value: + attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}value'], + )!, + height: + attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + )!, + blockTime: + attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}block_time'], + )!, + blocked: + attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}blocked'], + )!, + used: + attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}used'], + )!, + ); + } + + @override + $MwebUtxosTable createAlias(String alias) { + return $MwebUtxosTable(attachedDatabase, alias); + } +} + +class MwebUtxo extends DataClass implements Insertable { + final String outputId; + final String address; + final int value; + final int height; + final int blockTime; + final bool blocked; + final bool used; + const MwebUtxo({ + required this.outputId, + required this.address, + required this.value, + required this.height, + required this.blockTime, + required this.blocked, + required this.used, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['output_id'] = Variable(outputId); + map['address'] = Variable(address); + map['value'] = Variable(value); + map['height'] = Variable(height); + map['block_time'] = Variable(blockTime); + map['blocked'] = Variable(blocked); + map['used'] = Variable(used); + return map; + } + + MwebUtxosCompanion toCompanion(bool nullToAbsent) { + return MwebUtxosCompanion( + outputId: Value(outputId), + address: Value(address), + value: Value(value), + height: Value(height), + blockTime: Value(blockTime), + blocked: Value(blocked), + used: Value(used), + ); + } + + factory MwebUtxo.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MwebUtxo( + outputId: serializer.fromJson(json['outputId']), + address: serializer.fromJson(json['address']), + value: serializer.fromJson(json['value']), + height: serializer.fromJson(json['height']), + blockTime: serializer.fromJson(json['blockTime']), + blocked: serializer.fromJson(json['blocked']), + used: serializer.fromJson(json['used']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'outputId': serializer.toJson(outputId), + 'address': serializer.toJson(address), + 'value': serializer.toJson(value), + 'height': serializer.toJson(height), + 'blockTime': serializer.toJson(blockTime), + 'blocked': serializer.toJson(blocked), + 'used': serializer.toJson(used), + }; + } + + MwebUtxo copyWith({ + String? outputId, + String? address, + int? value, + int? height, + int? blockTime, + bool? blocked, + bool? used, + }) => MwebUtxo( + outputId: outputId ?? this.outputId, + address: address ?? this.address, + value: value ?? this.value, + height: height ?? this.height, + blockTime: blockTime ?? this.blockTime, + blocked: blocked ?? this.blocked, + used: used ?? this.used, + ); + MwebUtxo copyWithCompanion(MwebUtxosCompanion data) { + return MwebUtxo( + outputId: data.outputId.present ? data.outputId.value : this.outputId, + address: data.address.present ? data.address.value : this.address, + value: data.value.present ? data.value.value : this.value, + height: data.height.present ? data.height.value : this.height, + blockTime: data.blockTime.present ? data.blockTime.value : this.blockTime, + blocked: data.blocked.present ? data.blocked.value : this.blocked, + used: data.used.present ? data.used.value : this.used, + ); + } + + @override + String toString() { + return (StringBuffer('MwebUtxo(') + ..write('outputId: $outputId, ') + ..write('address: $address, ') + ..write('value: $value, ') + ..write('height: $height, ') + ..write('blockTime: $blockTime, ') + ..write('blocked: $blocked, ') + ..write('used: $used') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(outputId, address, value, height, blockTime, blocked, used); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MwebUtxo && + other.outputId == this.outputId && + other.address == this.address && + other.value == this.value && + other.height == this.height && + other.blockTime == this.blockTime && + other.blocked == this.blocked && + other.used == this.used); +} + +class MwebUtxosCompanion extends UpdateCompanion { + final Value outputId; + final Value address; + final Value value; + final Value height; + final Value blockTime; + final Value blocked; + final Value used; + final Value rowid; + const MwebUtxosCompanion({ + this.outputId = const Value.absent(), + this.address = const Value.absent(), + this.value = const Value.absent(), + this.height = const Value.absent(), + this.blockTime = const Value.absent(), + this.blocked = const Value.absent(), + this.used = const Value.absent(), + this.rowid = const Value.absent(), + }); + MwebUtxosCompanion.insert({ + required String outputId, + required String address, + required int value, + required int height, + required int blockTime, + required bool blocked, + required bool used, + this.rowid = const Value.absent(), + }) : outputId = Value(outputId), + address = Value(address), + value = Value(value), + height = Value(height), + blockTime = Value(blockTime), + blocked = Value(blocked), + used = Value(used); + static Insertable custom({ + Expression? outputId, + Expression? address, + Expression? value, + Expression? height, + Expression? blockTime, + Expression? blocked, + Expression? used, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (outputId != null) 'output_id': outputId, + if (address != null) 'address': address, + if (value != null) 'value': value, + if (height != null) 'height': height, + if (blockTime != null) 'block_time': blockTime, + if (blocked != null) 'blocked': blocked, + if (used != null) 'used': used, + if (rowid != null) 'rowid': rowid, + }); + } + + MwebUtxosCompanion copyWith({ + Value? outputId, + Value? address, + Value? value, + Value? height, + Value? blockTime, + Value? blocked, + Value? used, + Value? rowid, + }) { + return MwebUtxosCompanion( + outputId: outputId ?? this.outputId, + address: address ?? this.address, + value: value ?? this.value, + height: height ?? this.height, + blockTime: blockTime ?? this.blockTime, + blocked: blocked ?? this.blocked, + used: used ?? this.used, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (outputId.present) { + map['output_id'] = Variable(outputId.value); + } + if (address.present) { + map['address'] = Variable(address.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (blockTime.present) { + map['block_time'] = Variable(blockTime.value); + } + if (blocked.present) { + map['blocked'] = Variable(blocked.value); + } + if (used.present) { + map['used'] = Variable(used.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MwebUtxosCompanion(') + ..write('outputId: $outputId, ') + ..write('address: $address, ') + ..write('value: $value, ') + ..write('height: $height, ') + ..write('blockTime: $blockTime, ') + ..write('blocked: $blocked, ') + ..write('used: $used, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + abstract class _$WalletDatabase extends GeneratedDatabase { _$WalletDatabase(QueryExecutor e) : super(e); $WalletDatabaseManager get managers => $WalletDatabaseManager(this); late final $SparkNamesTable sparkNames = $SparkNamesTable(this); + late final $MwebUtxosTable mwebUtxos = $MwebUtxosTable(this); @override Iterable> get allTables => allSchemaEntities.whereType>(); @override - List get allSchemaEntities => [sparkNames]; + List get allSchemaEntities => [sparkNames, mwebUtxos]; } -typedef $$SparkNamesTableCreateCompanionBuilder = SparkNamesCompanion Function({ - required String name, - required String address, - required int validUntil, - Value additionalInfo, - Value rowid, -}); -typedef $$SparkNamesTableUpdateCompanionBuilder = SparkNamesCompanion Function({ - Value name, - Value address, - Value validUntil, - Value additionalInfo, - Value rowid, -}); +typedef $$SparkNamesTableCreateCompanionBuilder = + SparkNamesCompanion Function({ + required String name, + required String address, + required int validUntil, + Value additionalInfo, + Value rowid, + }); +typedef $$SparkNamesTableUpdateCompanionBuilder = + SparkNamesCompanion Function({ + Value name, + Value address, + Value validUntil, + Value additionalInfo, + Value rowid, + }); class $$SparkNamesTableFilterComposer extends Composer<_$WalletDatabase, $SparkNamesTable> { @@ -323,17 +843,24 @@ class $$SparkNamesTableFilterComposer super.$removeJoinBuilderFromRootComposer, }); ColumnFilters get name => $composableBuilder( - column: $table.name, builder: (column) => ColumnFilters(column)); + column: $table.name, + builder: (column) => ColumnFilters(column), + ); ColumnFilters get address => $composableBuilder( - column: $table.address, builder: (column) => ColumnFilters(column)); + column: $table.address, + builder: (column) => ColumnFilters(column), + ); ColumnFilters get validUntil => $composableBuilder( - column: $table.validUntil, builder: (column) => ColumnFilters(column)); + column: $table.validUntil, + builder: (column) => ColumnFilters(column), + ); ColumnFilters get additionalInfo => $composableBuilder( - column: $table.additionalInfo, - builder: (column) => ColumnFilters(column)); + column: $table.additionalInfo, + builder: (column) => ColumnFilters(column), + ); } class $$SparkNamesTableOrderingComposer @@ -346,17 +873,24 @@ class $$SparkNamesTableOrderingComposer super.$removeJoinBuilderFromRootComposer, }); ColumnOrderings get name => $composableBuilder( - column: $table.name, builder: (column) => ColumnOrderings(column)); + column: $table.name, + builder: (column) => ColumnOrderings(column), + ); ColumnOrderings get address => $composableBuilder( - column: $table.address, builder: (column) => ColumnOrderings(column)); + column: $table.address, + builder: (column) => ColumnOrderings(column), + ); ColumnOrderings get validUntil => $composableBuilder( - column: $table.validUntil, builder: (column) => ColumnOrderings(column)); + column: $table.validUntil, + builder: (column) => ColumnOrderings(column), + ); ColumnOrderings get additionalInfo => $composableBuilder( - column: $table.additionalInfo, - builder: (column) => ColumnOrderings(column)); + column: $table.additionalInfo, + builder: (column) => ColumnOrderings(column), + ); } class $$SparkNamesTableAnnotationComposer @@ -375,85 +909,353 @@ class $$SparkNamesTableAnnotationComposer $composableBuilder(column: $table.address, builder: (column) => column); GeneratedColumn get validUntil => $composableBuilder( - column: $table.validUntil, builder: (column) => column); + column: $table.validUntil, + builder: (column) => column, + ); GeneratedColumn get additionalInfo => $composableBuilder( - column: $table.additionalInfo, builder: (column) => column); + column: $table.additionalInfo, + builder: (column) => column, + ); } -class $$SparkNamesTableTableManager extends RootTableManager< - _$WalletDatabase, - $SparkNamesTable, - SparkName, - $$SparkNamesTableFilterComposer, - $$SparkNamesTableOrderingComposer, - $$SparkNamesTableAnnotationComposer, - $$SparkNamesTableCreateCompanionBuilder, - $$SparkNamesTableUpdateCompanionBuilder, - (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), - SparkName, - PrefetchHooks Function()> { +class $$SparkNamesTableTableManager + extends + RootTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + ( + SparkName, + BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>, + ), + SparkName, + PrefetchHooks Function() + > { $$SparkNamesTableTableManager(_$WalletDatabase db, $SparkNamesTable table) - : super(TableManagerState( + : super( + TableManagerState( db: db, table: table, - createFilteringComposer: () => - $$SparkNamesTableFilterComposer($db: db, $table: table), - createOrderingComposer: () => - $$SparkNamesTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: () => - $$SparkNamesTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: ({ - Value name = const Value.absent(), - Value address = const Value.absent(), - Value validUntil = const Value.absent(), - Value additionalInfo = const Value.absent(), - Value rowid = const Value.absent(), - }) => - SparkNamesCompanion( - name: name, - address: address, - validUntil: validUntil, - additionalInfo: additionalInfo, - rowid: rowid, - ), - createCompanionCallback: ({ - required String name, - required String address, - required int validUntil, - Value additionalInfo = const Value.absent(), - Value rowid = const Value.absent(), - }) => - SparkNamesCompanion.insert( - name: name, - address: address, - validUntil: validUntil, - additionalInfo: additionalInfo, - rowid: rowid, + createFilteringComposer: + () => $$SparkNamesTableFilterComposer($db: db, $table: table), + createOrderingComposer: + () => $$SparkNamesTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: + () => $$SparkNamesTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value name = const Value.absent(), + Value address = const Value.absent(), + Value validUntil = const Value.absent(), + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => SparkNamesCompanion( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String name, + required String address, + required int validUntil, + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => SparkNamesCompanion.insert( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + withReferenceMapper: + (p0) => + p0 + .map( + (e) => ( + e.readTable(table), + BaseReferences(db, table, e), + ), + ) + .toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $$SparkNamesTableProcessedTableManager = + ProcessedTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + ( + SparkName, + BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>, + ), + SparkName, + PrefetchHooks Function() + >; +typedef $$MwebUtxosTableCreateCompanionBuilder = + MwebUtxosCompanion Function({ + required String outputId, + required String address, + required int value, + required int height, + required int blockTime, + required bool blocked, + required bool used, + Value rowid, + }); +typedef $$MwebUtxosTableUpdateCompanionBuilder = + MwebUtxosCompanion Function({ + Value outputId, + Value address, + Value value, + Value height, + Value blockTime, + Value blocked, + Value used, + Value rowid, + }); + +class $$MwebUtxosTableFilterComposer + extends Composer<_$WalletDatabase, $MwebUtxosTable> { + $$MwebUtxosTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get outputId => $composableBuilder( + column: $table.outputId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get address => $composableBuilder( + column: $table.address, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get value => $composableBuilder( + column: $table.value, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get height => $composableBuilder( + column: $table.height, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get blockTime => $composableBuilder( + column: $table.blockTime, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get blocked => $composableBuilder( + column: $table.blocked, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get used => $composableBuilder( + column: $table.used, + builder: (column) => ColumnFilters(column), + ); +} + +class $$MwebUtxosTableOrderingComposer + extends Composer<_$WalletDatabase, $MwebUtxosTable> { + $$MwebUtxosTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get outputId => $composableBuilder( + column: $table.outputId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get address => $composableBuilder( + column: $table.address, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get value => $composableBuilder( + column: $table.value, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get height => $composableBuilder( + column: $table.height, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get blockTime => $composableBuilder( + column: $table.blockTime, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get blocked => $composableBuilder( + column: $table.blocked, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get used => $composableBuilder( + column: $table.used, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$MwebUtxosTableAnnotationComposer + extends Composer<_$WalletDatabase, $MwebUtxosTable> { + $$MwebUtxosTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get outputId => + $composableBuilder(column: $table.outputId, builder: (column) => column); + + GeneratedColumn get address => + $composableBuilder(column: $table.address, builder: (column) => column); + + GeneratedColumn get value => + $composableBuilder(column: $table.value, builder: (column) => column); + + GeneratedColumn get height => + $composableBuilder(column: $table.height, builder: (column) => column); + + GeneratedColumn get blockTime => + $composableBuilder(column: $table.blockTime, builder: (column) => column); + + GeneratedColumn get blocked => + $composableBuilder(column: $table.blocked, builder: (column) => column); + + GeneratedColumn get used => + $composableBuilder(column: $table.used, builder: (column) => column); +} + +class $$MwebUtxosTableTableManager + extends + RootTableManager< + _$WalletDatabase, + $MwebUtxosTable, + MwebUtxo, + $$MwebUtxosTableFilterComposer, + $$MwebUtxosTableOrderingComposer, + $$MwebUtxosTableAnnotationComposer, + $$MwebUtxosTableCreateCompanionBuilder, + $$MwebUtxosTableUpdateCompanionBuilder, + ( + MwebUtxo, + BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>, ), - withReferenceMapper: (p0) => p0 - .map((e) => (e.readTable(table), BaseReferences(db, table, e))) - .toList(), + MwebUtxo, + PrefetchHooks Function() + > { + $$MwebUtxosTableTableManager(_$WalletDatabase db, $MwebUtxosTable table) + : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: + () => $$MwebUtxosTableFilterComposer($db: db, $table: table), + createOrderingComposer: + () => $$MwebUtxosTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: + () => $$MwebUtxosTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value outputId = const Value.absent(), + Value address = const Value.absent(), + Value value = const Value.absent(), + Value height = const Value.absent(), + Value blockTime = const Value.absent(), + Value blocked = const Value.absent(), + Value used = const Value.absent(), + Value rowid = const Value.absent(), + }) => MwebUtxosCompanion( + outputId: outputId, + address: address, + value: value, + height: height, + blockTime: blockTime, + blocked: blocked, + used: used, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String outputId, + required String address, + required int value, + required int height, + required int blockTime, + required bool blocked, + required bool used, + Value rowid = const Value.absent(), + }) => MwebUtxosCompanion.insert( + outputId: outputId, + address: address, + value: value, + height: height, + blockTime: blockTime, + blocked: blocked, + used: used, + rowid: rowid, + ), + withReferenceMapper: + (p0) => + p0 + .map( + (e) => ( + e.readTable(table), + BaseReferences(db, table, e), + ), + ) + .toList(), prefetchHooksCallback: null, - )); + ), + ); } -typedef $$SparkNamesTableProcessedTableManager = ProcessedTableManager< - _$WalletDatabase, - $SparkNamesTable, - SparkName, - $$SparkNamesTableFilterComposer, - $$SparkNamesTableOrderingComposer, - $$SparkNamesTableAnnotationComposer, - $$SparkNamesTableCreateCompanionBuilder, - $$SparkNamesTableUpdateCompanionBuilder, - (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), - SparkName, - PrefetchHooks Function()>; +typedef $$MwebUtxosTableProcessedTableManager = + ProcessedTableManager< + _$WalletDatabase, + $MwebUtxosTable, + MwebUtxo, + $$MwebUtxosTableFilterComposer, + $$MwebUtxosTableOrderingComposer, + $$MwebUtxosTableAnnotationComposer, + $$MwebUtxosTableCreateCompanionBuilder, + $$MwebUtxosTableUpdateCompanionBuilder, + (MwebUtxo, BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>), + MwebUtxo, + PrefetchHooks Function() + >; class $WalletDatabaseManager { final _$WalletDatabase _db; $WalletDatabaseManager(this._db); $$SparkNamesTableTableManager get sparkNames => $$SparkNamesTableTableManager(_db, _db.sparkNames); + $$MwebUtxosTableTableManager get mwebUtxos => + $$MwebUtxosTableTableManager(_db, _db.mwebUtxos); } diff --git a/lib/models/isar/models/blockchain_data/address.g.dart b/lib/models/isar/models/blockchain_data/address.g.dart index a9289a481..e3df46a6b 100644 --- a/lib/models/isar/models/blockchain_data/address.g.dart +++ b/lib/models/isar/models/blockchain_data/address.g.dart @@ -280,6 +280,8 @@ const _AddresstypeEnumValueMap = { 'solana': 15, 'cardanoShelley': 16, 'xelis': 17, + 'fact0rn': 18, + 'mweb': 19, }; const _AddresstypeValueEnumMap = { 0: AddressType.p2pkh, @@ -300,6 +302,8 @@ const _AddresstypeValueEnumMap = { 15: AddressType.solana, 16: AddressType.cardanoShelley, 17: AddressType.xelis, + 18: AddressType.fact0rn, + 19: AddressType.mweb, }; Id _addressGetId(Address object) { diff --git a/lib/wallets/isar/models/wallet_info.g.dart b/lib/wallets/isar/models/wallet_info.g.dart index 5e93564c0..3dda37c77 100644 --- a/lib/wallets/isar/models/wallet_info.g.dart +++ b/lib/wallets/isar/models/wallet_info.g.dart @@ -270,6 +270,8 @@ const _WalletInfomainAddressTypeEnumValueMap = { 'solana': 15, 'cardanoShelley': 16, 'xelis': 17, + 'fact0rn': 18, + 'mweb': 19, }; const _WalletInfomainAddressTypeValueEnumMap = { 0: AddressType.p2pkh, @@ -290,6 +292,8 @@ const _WalletInfomainAddressTypeValueEnumMap = { 15: AddressType.solana, 16: AddressType.cardanoShelley, 17: AddressType.xelis, + 18: AddressType.fact0rn, + 19: AddressType.mweb, }; Id _walletInfoGetId(WalletInfo object) { diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index 22ab2a712..0d5b6a2f4 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -1261,6 +1261,21 @@ class MockPrefs extends _i1.Mock implements _i10.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index 436a918fd..84a91812a 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -348,7 +348,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -395,25 +395,6 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { returnValueForMissingStub: _i10.Future.value(), ) as _i10.Future); - @override - _i10.Future edit( - _i13.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - @override _i10.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( @@ -1200,6 +1181,21 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart index 25bfa08e4..192ce703a 100644 --- a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart +++ b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart @@ -3,14 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; +import 'dart:async' as _i4; import 'dart:ui' as _i7; -import 'package:barcode_scan2/barcode_scan2.dart' as _i2; +import 'package:flutter/material.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i3; import 'package:stackwallet/services/address_book_service.dart' as _i6; -import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i4; +import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -49,29 +49,28 @@ class _FakeContactEntry_1 extends _i1.SmartFake implements _i3.ContactEntry { /// /// See the documentation for Mockito's code generation for more information. class MockBarcodeScannerWrapper extends _i1.Mock - implements _i4.BarcodeScannerWrapper { + implements _i2.BarcodeScannerWrapper { MockBarcodeScannerWrapper() { _i1.throwOnMissingStub(this); } @override - _i5.Future<_i2.ScanResult> scan( - {_i2.ScanOptions? options = const _i2.ScanOptions()}) => + _i4.Future<_i2.ScanResult> scan({required _i5.BuildContext? context}) => (super.noSuchMethod( Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), - returnValue: _i5.Future<_i2.ScanResult>.value(_FakeScanResult_0( + returnValue: _i4.Future<_i2.ScanResult>.value(_FakeScanResult_0( this, Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), )), - ) as _i5.Future<_i2.ScanResult>); + ) as _i4.Future<_i2.ScanResult>); } /// A class which mocks [AddressBookService]. @@ -111,15 +110,15 @@ class MockAddressBookService extends _i1.Mock ) as _i3.ContactEntry); @override - _i5.Future> search(String? text) => + _i4.Future> search(String? text) => (super.noSuchMethod( Invocation.method( #search, [text], ), returnValue: - _i5.Future>.value(<_i3.ContactEntry>[]), - ) as _i5.Future>); + _i4.Future>.value(<_i3.ContactEntry>[]), + ) as _i4.Future>); @override bool matches( @@ -138,33 +137,33 @@ class MockAddressBookService extends _i1.Mock ) as bool); @override - _i5.Future addContact(_i3.ContactEntry? contact) => (super.noSuchMethod( + _i4.Future addContact(_i3.ContactEntry? contact) => (super.noSuchMethod( Invocation.method( #addContact, [contact], ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override - _i5.Future editContact(_i3.ContactEntry? editedContact) => + _i4.Future editContact(_i3.ContactEntry? editedContact) => (super.noSuchMethod( Invocation.method( #editContact, [editedContact], ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override - _i5.Future removeContact(String? id) => (super.noSuchMethod( + _i4.Future removeContact(String? id) => (super.noSuchMethod( Invocation.method( #removeContact, [id], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 643d6cc6b..1f78d9ce4 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -622,6 +622,21 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/screen_tests/lockscreen_view_screen_test.mocks.dart b/test/screen_tests/lockscreen_view_screen_test.mocks.dart index c68851019..804721d4c 100644 --- a/test/screen_tests/lockscreen_view_screen_test.mocks.dart +++ b/test/screen_tests/lockscreen_view_screen_test.mocks.dart @@ -209,7 +209,7 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -256,25 +256,6 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); - @override - _i4.Future edit( - _i7.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); - @override _i4.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart index 08e96b5a3..9218bd83e 100644 --- a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart @@ -209,7 +209,7 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -256,25 +256,6 @@ class MockNodeService extends _i1.Mock implements _i6.NodeService { returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); - @override - _i4.Future edit( - _i7.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); - @override _i4.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart index 3c66bf1f3..68ac1be3e 100644 --- a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart @@ -3,15 +3,15 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; +import 'dart:async' as _i4; import 'dart:ui' as _i7; -import 'package:barcode_scan2/barcode_scan2.dart' as _i2; +import 'package:flutter/material.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/models/node_model.dart' as _i9; import 'package:stackwallet/services/node_service.dart' as _i8; import 'package:stackwallet/services/wallets_service.dart' as _i6; -import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i4; +import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i2; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' as _i3; import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart' @@ -55,29 +55,28 @@ class _FakeSecureStorageInterface_1 extends _i1.SmartFake /// /// See the documentation for Mockito's code generation for more information. class MockBarcodeScannerWrapper extends _i1.Mock - implements _i4.BarcodeScannerWrapper { + implements _i2.BarcodeScannerWrapper { MockBarcodeScannerWrapper() { _i1.throwOnMissingStub(this); } @override - _i5.Future<_i2.ScanResult> scan( - {_i2.ScanOptions? options = const _i2.ScanOptions()}) => + _i4.Future<_i2.ScanResult> scan({required _i5.BuildContext? context}) => (super.noSuchMethod( Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), - returnValue: _i5.Future<_i2.ScanResult>.value(_FakeScanResult_0( + returnValue: _i4.Future<_i2.ScanResult>.value(_FakeScanResult_0( this, Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), )), - ) as _i5.Future<_i2.ScanResult>); + ) as _i4.Future<_i2.ScanResult>); } /// A class which mocks [WalletsService]. @@ -89,12 +88,12 @@ class MockWalletsService extends _i1.Mock implements _i6.WalletsService { } @override - _i5.Future> get walletNames => + _i4.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i5.Future>.value( + returnValue: _i4.Future>.value( {}), - ) as _i5.Future>); + ) as _i4.Future>); @override bool get hasListeners => (super.noSuchMethod( @@ -175,17 +174,17 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { ) as bool); @override - _i5.Future updateDefaults() => (super.noSuchMethod( + _i4.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i5.Future setPrimaryNodeFor({ + _i4.Future setPrimaryNodeFor({ required _i10.CryptoCurrency? coin, required _i9.NodeModel? node, bool? shouldNotifyListeners = false, @@ -200,9 +199,9 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override _i9.NodeModel? getPrimaryNodeFor({required _i10.CryptoCurrency? currency}) => @@ -243,26 +242,26 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { ) as List<_i9.NodeModel>); @override - _i5.Future save( + _i4.Future save( _i9.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, shouldNotifyListeners, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i5.Future delete( + _i4.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -274,12 +273,12 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { shouldNotifyListeners, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i5.Future setEnabledState( + _i4.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -293,38 +292,19 @@ class MockNodeService extends _i1.Mock implements _i8.NodeService { shouldNotifyListeners, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i5.Future edit( - _i9.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - - @override - _i5.Future updateCommunityNodes() => (super.noSuchMethod( + _i4.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart index d6d788327..b4eb99213 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart @@ -149,7 +149,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -196,25 +196,6 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); - @override - _i5.Future edit( - _i4.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - @override _i5.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart index 6a4ad08ce..787f1f801 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart @@ -149,7 +149,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -196,25 +196,6 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); - @override - _i5.Future edit( - _i4.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - @override _i5.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart index b8fee8040..6a2a923e0 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_view_screen_test.mocks.dart @@ -149,7 +149,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -196,25 +196,6 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); - @override - _i5.Future edit( - _i4.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - @override _i5.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart index 40a295640..d3a16fd4f 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart @@ -3,7 +3,7 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; +import 'dart:async' as _i5; import 'dart:ui' as _i13; import 'package:local_auth/local_auth.dart' as _i7; @@ -11,13 +11,13 @@ import 'package:local_auth_android/local_auth_android.dart' as _i8; import 'package:local_auth_darwin/local_auth_darwin.dart' as _i9; import 'package:local_auth_windows/local_auth_windows.dart' as _i10; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i6; +import 'package:mockito/src/dummies.dart' as _i4; import 'package:stackwallet/electrumx_rpc/cached_electrumx_client.dart' as _i3; import 'package:stackwallet/electrumx_rpc/electrumx_client.dart' as _i2; import 'package:stackwallet/services/wallets_service.dart' as _i12; import 'package:stackwallet/utilities/biometrics.dart' as _i11; import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart' - as _i5; + as _i6; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -61,33 +61,13 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i2.ElectrumXClient); - @override - _i4.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i5.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i4.Future>.value({}), - ) as _i4.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( #base64ToHex, [source], ), - returnValue: _i6.dummyValue( + returnValue: _i4.dummyValue( this, Invocation.method( #base64ToHex, @@ -102,7 +82,7 @@ class MockCachedElectrumXClient extends _i1.Mock #base64ToReverseHex, [source], ), - returnValue: _i6.dummyValue( + returnValue: _i4.dummyValue( this, Invocation.method( #base64ToReverseHex, @@ -112,9 +92,9 @@ class MockCachedElectrumXClient extends _i1.Mock ) as String); @override - _i4.Future> getTransaction({ + _i5.Future> getTransaction({ required String? txHash, - required _i5.CryptoCurrency? cryptoCurrency, + required _i6.CryptoCurrency? cryptoCurrency, bool? verbose = true, }) => (super.noSuchMethod( @@ -128,38 +108,21 @@ class MockCachedElectrumXClient extends _i1.Mock }, ), returnValue: - _i4.Future>.value({}), - ) as _i4.Future>); - - @override - _i4.Future> getUsedCoinSerials({ - required _i5.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i4.Future>.value([]), - ) as _i4.Future>); + _i5.Future>.value({}), + ) as _i5.Future>); @override - _i4.Future clearSharedTransactionCache( - {required _i5.CryptoCurrency? cryptoCurrency}) => + _i5.Future clearSharedTransactionCache( + {required _i6.CryptoCurrency? cryptoCurrency}) => (super.noSuchMethod( Invocation.method( #clearSharedTransactionCache, [], {#cryptoCurrency: cryptoCurrency}, ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); } /// A class which mocks [LocalAuthentication]. @@ -172,13 +135,13 @@ class MockLocalAuthentication extends _i1.Mock } @override - _i4.Future get canCheckBiometrics => (super.noSuchMethod( + _i5.Future get canCheckBiometrics => (super.noSuchMethod( Invocation.getter(#canCheckBiometrics), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + returnValue: _i5.Future.value(false), + ) as _i5.Future); @override - _i4.Future authenticate({ + _i5.Future authenticate({ required String? localizedReason, Iterable<_i8.AuthMessages>? authMessages = const [ _i9.IOSAuthMessages(), @@ -197,37 +160,37 @@ class MockLocalAuthentication extends _i1.Mock #options: options, }, ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + returnValue: _i5.Future.value(false), + ) as _i5.Future); @override - _i4.Future stopAuthentication() => (super.noSuchMethod( + _i5.Future stopAuthentication() => (super.noSuchMethod( Invocation.method( #stopAuthentication, [], ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + returnValue: _i5.Future.value(false), + ) as _i5.Future); @override - _i4.Future isDeviceSupported() => (super.noSuchMethod( + _i5.Future isDeviceSupported() => (super.noSuchMethod( Invocation.method( #isDeviceSupported, [], ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + returnValue: _i5.Future.value(false), + ) as _i5.Future); @override - _i4.Future> getAvailableBiometrics() => + _i5.Future> getAvailableBiometrics() => (super.noSuchMethod( Invocation.method( #getAvailableBiometrics, [], ), returnValue: - _i4.Future>.value(<_i8.BiometricType>[]), - ) as _i4.Future>); + _i5.Future>.value(<_i8.BiometricType>[]), + ) as _i5.Future>); } /// A class which mocks [Biometrics]. @@ -239,7 +202,7 @@ class MockBiometrics extends _i1.Mock implements _i11.Biometrics { } @override - _i4.Future authenticate({ + _i5.Future authenticate({ required String? cancelButtonText, required String? localizedReason, required String? title, @@ -254,8 +217,8 @@ class MockBiometrics extends _i1.Mock implements _i11.Biometrics { #title: title, }, ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + returnValue: _i5.Future.value(false), + ) as _i5.Future); } /// A class which mocks [WalletsService]. @@ -267,12 +230,12 @@ class MockWalletsService extends _i1.Mock implements _i12.WalletsService { } @override - _i4.Future> get walletNames => + _i5.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i4.Future>.value( + returnValue: _i5.Future>.value( {}), - ) as _i4.Future>); + ) as _i5.Future>); @override bool get hasListeners => (super.noSuchMethod( diff --git a/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart b/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart index a7a3ad695..cd4db9558 100644 --- a/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart +++ b/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart @@ -3,11 +3,11 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; +import 'dart:async' as _i3; -import 'package:barcode_scan2/barcode_scan2.dart' as _i2; +import 'package:flutter/material.dart' as _i4; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i3; +import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -36,27 +36,26 @@ class _FakeScanResult_0 extends _i1.SmartFake implements _i2.ScanResult { /// /// See the documentation for Mockito's code generation for more information. class MockBarcodeScannerWrapper extends _i1.Mock - implements _i3.BarcodeScannerWrapper { + implements _i2.BarcodeScannerWrapper { MockBarcodeScannerWrapper() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i2.ScanResult> scan( - {_i2.ScanOptions? options = const _i2.ScanOptions()}) => + _i3.Future<_i2.ScanResult> scan({required _i4.BuildContext? context}) => (super.noSuchMethod( Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), - returnValue: _i4.Future<_i2.ScanResult>.value(_FakeScanResult_0( + returnValue: _i3.Future<_i2.ScanResult>.value(_FakeScanResult_0( this, Invocation.method( #scan, [], - {#options: options}, + {#context: context}, ), )), - ) as _i4.Future<_i2.ScanResult>); + ) as _i3.Future<_i2.ScanResult>); } diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart index c840f4b50..35fbc67a1 100644 --- a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart +++ b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart @@ -733,26 +733,6 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i5.ElectrumXClient); - @override - _i8.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i2.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i8.Future>.value({}), - ) as _i8.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( @@ -803,23 +783,6 @@ class MockCachedElectrumXClient extends _i1.Mock _i8.Future>.value({}), ) as _i8.Future>); - @override - _i8.Future> getUsedCoinSerials({ - required _i2.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i8.Future>.value([]), - ) as _i8.Future>); - @override _i8.Future clearSharedTransactionCache( {required _i2.CryptoCurrency? cryptoCurrency}) => diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart index 50706b9cc..7c455f73d 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart @@ -733,26 +733,6 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i5.ElectrumXClient); - @override - _i8.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i2.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i8.Future>.value({}), - ) as _i8.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( @@ -803,23 +783,6 @@ class MockCachedElectrumXClient extends _i1.Mock _i8.Future>.value({}), ) as _i8.Future>); - @override - _i8.Future> getUsedCoinSerials({ - required _i2.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i8.Future>.value([]), - ) as _i8.Future>); - @override _i8.Future clearSharedTransactionCache( {required _i2.CryptoCurrency? cryptoCurrency}) => diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index 93185c901..86090d418 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -733,26 +733,6 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i5.ElectrumXClient); - @override - _i8.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i2.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i8.Future>.value({}), - ) as _i8.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( @@ -803,23 +783,6 @@ class MockCachedElectrumXClient extends _i1.Mock _i8.Future>.value({}), ) as _i8.Future>); - @override - _i8.Future> getUsedCoinSerials({ - required _i2.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i8.Future>.value([]), - ) as _i8.Future>); - @override _i8.Future clearSharedTransactionCache( {required _i2.CryptoCurrency? cryptoCurrency}) => diff --git a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart index 287146e12..a397b611a 100644 --- a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart +++ b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart @@ -733,26 +733,6 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i5.ElectrumXClient); - @override - _i8.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i2.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i8.Future>.value({}), - ) as _i8.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( @@ -803,23 +783,6 @@ class MockCachedElectrumXClient extends _i1.Mock _i8.Future>.value({}), ) as _i8.Future>); - @override - _i8.Future> getUsedCoinSerials({ - required _i2.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i8.Future>.value([]), - ) as _i8.Future>); - @override _i8.Future clearSharedTransactionCache( {required _i2.CryptoCurrency? cryptoCurrency}) => diff --git a/test/services/coins/particl/particl_wallet_test.mocks.dart b/test/services/coins/particl/particl_wallet_test.mocks.dart index 8a1cce451..861fa4327 100644 --- a/test/services/coins/particl/particl_wallet_test.mocks.dart +++ b/test/services/coins/particl/particl_wallet_test.mocks.dart @@ -733,26 +733,6 @@ class MockCachedElectrumXClient extends _i1.Mock ), ) as _i5.ElectrumXClient); - @override - _i8.Future> getAnonymitySet({ - required String? groupId, - String? blockhash = r'', - required _i2.CryptoCurrency? cryptoCurrency, - }) => - (super.noSuchMethod( - Invocation.method( - #getAnonymitySet, - [], - { - #groupId: groupId, - #blockhash: blockhash, - #cryptoCurrency: cryptoCurrency, - }, - ), - returnValue: - _i8.Future>.value({}), - ) as _i8.Future>); - @override String base64ToHex(String? source) => (super.noSuchMethod( Invocation.method( @@ -803,23 +783,6 @@ class MockCachedElectrumXClient extends _i1.Mock _i8.Future>.value({}), ) as _i8.Future>); - @override - _i8.Future> getUsedCoinSerials({ - required _i2.CryptoCurrency? cryptoCurrency, - int? startNumber = 0, - }) => - (super.noSuchMethod( - Invocation.method( - #getUsedCoinSerials, - [], - { - #cryptoCurrency: cryptoCurrency, - #startNumber: startNumber, - }, - ), - returnValue: _i8.Future>.value([]), - ) as _i8.Future>); - @override _i8.Future clearSharedTransactionCache( {required _i2.CryptoCurrency? cryptoCurrency}) => diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index 4b1944af8..14bc27820 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -905,6 +905,21 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), @@ -1263,7 +1278,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -1310,25 +1325,6 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { returnValueForMissingStub: _i10.Future.value(), ) as _i10.Future); - @override - _i10.Future edit( - _i23.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - @override _i10.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/widget_tests/node_card_test.mocks.dart b/test/widget_tests/node_card_test.mocks.dart index 808f10fab..19c8c5166 100644 --- a/test/widget_tests/node_card_test.mocks.dart +++ b/test/widget_tests/node_card_test.mocks.dart @@ -149,7 +149,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -196,25 +196,6 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); - @override - _i5.Future edit( - _i4.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - @override _i5.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index d01578f3f..a346758aa 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -780,6 +780,21 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), @@ -1067,7 +1082,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -1114,25 +1129,6 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { returnValueForMissingStub: _i10.Future.value(), ) as _i10.Future); - @override - _i10.Future edit( - _i19.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - @override _i10.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index a090e757e..939703910 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -878,6 +878,21 @@ class MockPrefs extends _i1.Mock implements _i13.Prefs { returnValueForMissingStub: null, ); + @override + bool get useMweb => (super.noSuchMethod( + Invocation.getter(#useMweb), + returnValue: false, + ) as bool); + + @override + set useMweb(bool? useMweb) => super.noSuchMethod( + Invocation.setter( + #useMweb, + useMweb, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), @@ -1976,17 +1991,6 @@ class MockMainDB extends _i1.Mock implements _i3.MainDB { returnValue: _i10.Future.value(), returnValueForMissingStub: _i10.Future.value(), ) as _i10.Future); - - @override - _i10.Future getHighestUsedMintIndex({required String? walletId}) => - (super.noSuchMethod( - Invocation.method( - #getHighestUsedMintIndex, - [], - {#walletId: walletId}, - ), - returnValue: _i10.Future.value(), - ) as _i10.Future); } /// A class which mocks [IThemeAssets]. diff --git a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart index fc2c10fbb..d406a0c35 100644 --- a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart @@ -316,7 +316,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -363,25 +363,6 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { returnValueForMissingStub: _i8.Future.value(), ) as _i8.Future); - @override - _i8.Future edit( - _i11.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - @override _i8.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart index 5f16a8a2e..6018c1f93 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart @@ -456,7 +456,7 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { ) => (super.noSuchMethod( Invocation.method( - #add, + #save, [ node, password, @@ -503,25 +503,6 @@ class MockNodeService extends _i1.Mock implements _i2.NodeService { returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); - @override - _i9.Future edit( - _i15.NodeModel? editedNode, - String? password, - bool? shouldNotifyListeners, - ) => - (super.noSuchMethod( - Invocation.method( - #edit, - [ - editedNode, - password, - shouldNotifyListeners, - ], - ), - returnValue: _i9.Future.value(), - returnValueForMissingStub: _i9.Future.value(), - ) as _i9.Future); - @override _i9.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( From 009a90d737cc0c12897718de8d3a379cc6849cc1 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 11 Jun 2025 15:34:08 -0600 Subject: [PATCH 128/206] mweb utils --- .../global/mweb_status_changed_event.dart | 24 +++++++++++++ lib/utilities/prefs.dart | 34 +++++++++++++++++++ lib/utilities/stack_file_system.dart | 9 +++++ 3 files changed, 67 insertions(+) create mode 100644 lib/services/event_bus/events/global/mweb_status_changed_event.dart diff --git a/lib/services/event_bus/events/global/mweb_status_changed_event.dart b/lib/services/event_bus/events/global/mweb_status_changed_event.dart new file mode 100644 index 000000000..70dd4f3d6 --- /dev/null +++ b/lib/services/event_bus/events/global/mweb_status_changed_event.dart @@ -0,0 +1,24 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import '../../../../utilities/logger.dart'; + +enum MwebStatus { enabled, disabled } + +class MwebPreferenceChangedEvent { + String? message; + MwebStatus status; + + MwebPreferenceChangedEvent({required this.status, this.message}) { + Logging.instance.w( + "MwebPreferenceChangedEvent changed to \"$status\" with message: $message", + ); + } +} diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 087aaa631..fa3872a7c 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -16,6 +16,7 @@ import 'package:uuid/uuid.dart'; import '../app_config.dart'; import '../db/hive/db.dart'; +import '../services/event_bus/events/global/mweb_status_changed_event.dart'; import '../services/event_bus/events/global/tor_status_changed_event.dart'; import '../services/event_bus/global_event_bus.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; @@ -1347,4 +1348,37 @@ class Prefs extends ChangeNotifier { return Level.warning; } } + + // enabled mweb + + bool _useMweb = false; + + bool get useMweb => _useMweb; + + set useMweb(bool useMweb) { + if (_useMweb != useMweb) { + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "useMweb", + value: useMweb, + ); + _useMweb = useMweb; + notifyListeners(); + GlobalEventBus.instance.fire( + MwebPreferenceChangedEvent( + status: useMweb ? MwebStatus.enabled : MwebStatus.disabled, + message: "useMweb updated in prefs", + ), + ); + } + } + + Future _getUseMweb() async { + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "useMweb", + ) + as bool? ?? + false; + } } diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index 7a254dffe..c7b91eca1 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -139,6 +139,15 @@ abstract class StackFileSystem { } } + static Future applicationMwebdDirectory(String network) async { + final root = await applicationRootDirectory(); + final dir = Directory(path.join(root.path, "mwebd", network)); + if (!dir.existsSync()) { + await dir.create(); + } + return dir; + } + static Future applicationFiroCacheSQLiteDirectory() async { final root = await applicationRootDirectory(); if (_createSubDirs) { From f57e53c749549db39cb32a303bc374c5c416aa13 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 12 Jun 2025 09:56:32 -0600 Subject: [PATCH 129/206] formatting --- .../sub_widgets/desktop_receive.dart | 350 +++++++++--------- 1 file changed, 166 insertions(+), 184 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index b90cc2f6a..51422b09c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -22,7 +22,6 @@ import '../../../../models/isar/models/isar_models.dart'; import '../../../../models/keys/view_only_wallet_data.dart'; import '../../../../notifications/show_flush_bar.dart'; import '../../../../pages/receive_view/generate_receiving_uri_qr_code_view.dart'; -import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../route_generator.dart'; import '../../../../themes/stack_colors.dart'; @@ -91,10 +90,9 @@ class _DesktopReceiveState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -109,8 +107,9 @@ class _DesktopReceiveState extends ConsumerState { if (wallet is Bip39HDWallet && wallet is! BCashInterface) { DerivePathType? type; if (wallet.isViewOnly && wallet is ExtendedKeysInterface) { - final voData = await wallet.getViewOnlyWalletData() - as ExtendedKeysViewOnlyWalletData; + final voData = + await wallet.getViewOnlyWalletData() + as ExtendedKeysViewOnlyWalletData; for (final t in wallet.cryptoCurrency.supportedDerivationPathTypes) { final testPath = wallet.cryptoCurrency.constructDerivePath( derivePathType: t, @@ -168,10 +167,9 @@ class _DesktopReceiveState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -209,7 +207,8 @@ class _DesktopReceiveState extends ConsumerState { if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { showMultiType = false; } else { - showMultiType = supportsSpark || + showMultiType = + supportsSpark || (wallet is! BCashInterface && wallet is Bip39HDWallet && wallet.supportedAddressTypes.length > 1); @@ -222,9 +221,9 @@ class _DesktopReceiveState extends ConsumerState { _walletAddressTypes.insert(0, AddressType.spark); } else { _walletAddressTypes.addAll( - (wallet as Bip39HDWallet) - .supportedAddressTypes - .where((e) => e != wallet.info.mainAddressType), + (wallet as Bip39HDWallet).supportedAddressTypes.where( + (e) => e != wallet.info.mainAddressType, + ), ); } } @@ -233,8 +232,9 @@ class _DesktopReceiveState extends ConsumerState { _walletAddressTypes.removeWhere((e) => e == AddressType.p2pkh); } - _addressMap[_walletAddressTypes[_currentIndex]] = - ref.read(pWalletReceivingAddress(walletId)); + _addressMap[_walletAddressTypes[_currentIndex]] = ref.read( + pWalletReceivingAddress(walletId), + ); if (showMultiType) { for (final type in _walletAddressTypes) { @@ -250,15 +250,15 @@ class _DesktopReceiveState extends ConsumerState { .findFirst() .asStream() .listen((event) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - setState(() { - _addressMap[type] = - event?.value ?? _addressMap[type] ?? "[No address yet]"; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _addressMap[type] = + event?.value ?? _addressMap[type] ?? "[No address yet]"; + }); + } }); - } - }); - }); + }); } } @@ -284,8 +284,9 @@ class _DesktopReceiveState extends ConsumerState { address = ref.watch(pWalletReceivingAddress(walletId)); } - final wallet = - ref.watch(pWallets.select((value) => value.getWallet(walletId))); + final wallet = ref.watch( + pWallets.select((value) => value.getWallet(walletId)), + ); final bool canGen; if (wallet is ViewOnlyOptionInterface && @@ -301,91 +302,90 @@ class _DesktopReceiveState extends ConsumerState { children: [ ConditionalParent( condition: showMultiType, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - DropdownButtonHideUnderline( - child: DropdownButton2( - value: _currentIndex, - items: [ - for (int i = 0; i < _walletAddressTypes.length; i++) - DropdownMenuItem( - value: i, - child: Text( - supportsSpark && - _walletAddressTypes[i] == AddressType.p2pkh - ? "Transparent address" - : "${_walletAddressTypes[i].readableName} address", - style: STextStyles.w500_14(context), + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton2( + value: _currentIndex, + items: [ + for (int i = 0; i < _walletAddressTypes.length; i++) + DropdownMenuItem( + value: i, + child: Text( + supportsSpark && + _walletAddressTypes[i] == + AddressType.p2pkh + ? "Transparent address" + : "${_walletAddressTypes[i].readableName} address", + style: STextStyles.w500_14(context), + ), + ), + ], + onChanged: (value) { + if (value != null && value != _currentIndex) { + setState(() { + _currentIndex = value; + }); + } + }, + isExpanded: true, + iconStyleData: IconStyleData( + icon: Padding( + padding: const EdgeInsets.only(right: 10), + child: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), ), ), - ], - onChanged: (value) { - if (value != null && value != _currentIndex) { - setState(() { - _currentIndex = value; - }); - } - }, - isExpanded: true, - iconStyleData: IconStyleData( - icon: Padding( - padding: const EdgeInsets.only(right: 10), - child: SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + buttonStyleData: ButtonStyleData( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), ), - ), - ), - buttonStyleData: ButtonStyleData( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), ), - ), - ), - dropdownStyleData: DropdownStyleData( - offset: const Offset(0, -10), - elevation: 0, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), ), ), ), - menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - ), - ), - ), - const SizedBox( - height: 12, + const SizedBox(height: 12), + child, + ], ), - child, - ], - ), child: MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( onTap: () { - clipboard.setData( - ClipboardData( - text: address, - ), - ); + clipboard.setData(ClipboardData(text: address)); showFloatingFlushBar( type: FlushBarType.info, message: "Copied to clipboard", @@ -396,9 +396,10 @@ class _DesktopReceiveState extends ConsumerState { child: Container( decoration: BoxDecoration( border: Border.all( - color: Theme.of(context) - .extension()! - .backgroundAppBar, + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, width: 1, ), borderRadius: BorderRadius.circular( @@ -411,11 +412,7 @@ class _DesktopReceiveState extends ConsumerState { Row( children: [ Text( - "Your ${widget.contractAddress == null ? coin.ticker : ref.watch( - pCurrentTokenWallet.select( - (value) => value!.tokenContract.symbol, - ), - )} address", + "Your ${widget.contractAddress == null ? coin.ticker : ref.watch(pCurrentTokenWallet.select((value) => value!.tokenContract.symbol))} address", style: STextStyles.itemSubtitle(context), ), const Spacer(), @@ -425,24 +422,18 @@ class _DesktopReceiveState extends ConsumerState { Assets.svg.copy, width: 15, height: 15, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Copy", - style: STextStyles.link2(context), + color: + Theme.of( + context, + ).extension()!.infoItemIcons, ), + const SizedBox(width: 4), + Text("Copy", style: STextStyles.link2(context)), ], ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Row( children: [ Expanded( @@ -451,9 +442,10 @@ class _DesktopReceiveState extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), @@ -467,85 +459,75 @@ class _DesktopReceiveState extends ConsumerState { ), ), - if (canGen) - const SizedBox( - height: 20, - ), + if (canGen) const SizedBox(height: 20), if (canGen) SecondaryButton( buttonHeight: ButtonHeight.l, - onPressed: supportsSpark && - _walletAddressTypes[_currentIndex] == AddressType.spark - ? generateNewSparkAddress - : generateNewAddress, + onPressed: + supportsSpark && + _walletAddressTypes[_currentIndex] == AddressType.spark + ? generateNewSparkAddress + : generateNewAddress, label: "Generate new address", ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), Center( child: QR( - data: AddressUtils.buildUriString( - coin.uriScheme, - address, - {}, - ), + data: AddressUtils.buildUriString(coin.uriScheme, address, {}), size: 200, ), ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), // TODO: create transparent button class to account for hover GestureDetector( onTap: () async { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => DesktopDialog( - maxHeight: double.infinity, - maxWidth: 580, - child: Column( - children: [ - Row( + builder: + (context) => DesktopDialog( + maxHeight: double.infinity, + maxWidth: 580, + child: Column( children: [ - const AppBarBackButton( - size: 40, - iconSize: 24, + Row( + children: [ + const AppBarBackButton(size: 40, iconSize: 24), + Text( + "Generate QR code", + style: STextStyles.desktopH3(context), + ), + ], ), - Text( - "Generate QR code", - style: STextStyles.desktopH3(context), + IntrinsicHeight( + child: Navigator( + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: + (_, __) => [ + RouteGenerator.generateRoute( + RouteSettings( + name: GenerateUriQrCodeView.routeName, + arguments: Tuple2(coin, address), + ), + ), + ], + ), ), ], ), - IntrinsicHeight( - child: Navigator( - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) => [ - RouteGenerator.generateRoute( - RouteSettings( - name: GenerateUriQrCodeView.routeName, - arguments: Tuple2(coin, address), - ), - ), - ], - ), - ), - ], - ), - ), + ), ); } else { unawaited( Navigator.of(context).push( RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => GenerateUriQrCodeView( - coin: coin, - receivingAddress: address, - ), + builder: + (_) => GenerateUriQrCodeView( + coin: coin, + receivingAddress: address, + ), settings: const RouteSettings( name: GenerateUriQrCodeView.routeName, ), @@ -564,21 +546,21 @@ class _DesktopReceiveState extends ConsumerState { Assets.svg.qrcode, width: 14, height: 16, - color: Theme.of(context) - .extension()! - .accentColorBlue, - ), - const SizedBox( - width: 8, + color: + Theme.of( + context, + ).extension()!.accentColorBlue, ), + const SizedBox(width: 8), Padding( padding: const EdgeInsets.only(bottom: 2), child: Text( "Create new QR code", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorBlue, + color: + Theme.of( + context, + ).extension()!.accentColorBlue, ), ), ), From 6a055951d476e3bcdc2b15d0a6a3bf01affb9dfc Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 12 Jun 2025 16:23:21 -0600 Subject: [PATCH 130/206] WIP: mweb integration - desktop focus --- lib/db/drift/database.dart | 22 + .../wallet_network_settings_view.dart | 39 +- .../mweb_utxos_view.dart | 281 +++++++++ .../sub_widgets/desktop_receive.dart | 96 ++- .../sub_widgets/desktop_wallet_features.dart | 23 +- .../more_features/more_features_dialog.dart | 159 ++++- .../sub_widgets/network_info_button.dart | 176 +++--- lib/route_generator.dart | 11 + lib/services/mwebd_service.dart | 228 ++++++++ lib/utilities/prefs.dart | 34 -- lib/utilities/stack_file_system.dart | 2 +- lib/wallets/isar/models/wallet_info.dart | 16 + lib/wallets/models/tx_data.dart | 18 + lib/wallets/wallet/impl/litecoin_wallet.dart | 2 + .../mweb_interface.dart | 552 ++++++++++++++++++ pubspec.lock | 6 +- scripts/app_config/templates/pubspec.template | 3 +- 17 files changed, 1514 insertions(+), 154 deletions(-) create mode 100644 lib/pages_desktop_specific/mweb_utxos_view.dart create mode 100644 lib/services/mwebd_service.dart diff --git a/lib/db/drift/database.dart b/lib/db/drift/database.dart index c2ed93a46..4bfd94341 100644 --- a/lib/db/drift/database.dart +++ b/lib/db/drift/database.dart @@ -9,6 +9,7 @@ */ import 'dart:async'; +import 'dart:math' as math; import 'package:drift/drift.dart'; import 'package:drift_flutter/drift_flutter.dart'; @@ -57,6 +58,27 @@ class MwebUtxos extends Table { Set get primaryKey => {outputId}; } +extension MwebUtxoExt on MwebUtxo { + int getConfirmations(int currentChainHeight) { + if (blockTime <= 0) return 0; + if (height <= 0) return 0; + return math.max(0, currentChainHeight - (height - 1)); + } + + bool isConfirmed( + int currentChainHeight, + int minimumConfirms, { + int? overrideMinConfirms, + }) { + final confirmations = getConfirmations(currentChainHeight); + + if (overrideMinConfirms != null) { + return confirmations >= overrideMinConfirms; + } + return confirmations >= minimumConfirms; + } +} + @DriftDatabase(tables: [SparkNames, MwebUtxos]) final class WalletDatabase extends _$WalletDatabase { WalletDatabase._(String walletId, [QueryExecutor? executor]) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index 506f1167c..27e7cc63c 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -33,13 +33,16 @@ import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/coins/epiccash.dart'; +import '../../../../wallets/crypto_currency/coins/litecoin.dart'; import '../../../../wallets/crypto_currency/coins/monero.dart'; +import '../../../../wallets/crypto_currency/coins/salvium.dart'; import '../../../../wallets/crypto_currency/coins/wownero.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/impl/epiccash_wallet.dart'; -import '../../../../wallets/wallet/impl/monero_wallet.dart'; -import '../../../../wallets/wallet/impl/wownero_wallet.dart'; +import '../../../../wallets/wallet/impl/salvium_wallet.dart'; +import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../widgets/animated_text.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/conditional_parent.dart'; @@ -269,7 +272,13 @@ class _WalletNetworkSettingsViewState final coin = ref.read(pWalletCoin(widget.walletId)); - if (coin is Monero || coin is Wownero || coin is Epiccash) { + // TODO: handle isMwebEnabled toggled + if (coin is Monero || + coin is Wownero || + coin is Epiccash || + coin is Salvium || + (coin is Litecoin && + ref.read(pWalletInfo(widget.walletId)).isMwebEnabled)) { _blocksRemainingSubscription = eventBus.on().listen( (event) async { if (event.walletId == widget.walletId) { @@ -329,16 +338,23 @@ class _WalletNetworkSettingsViewState final coin = ref.watch(pWalletCoin(widget.walletId)); - if (coin is Monero) { + if (coin is Salvium) { final double highestPercent = - (ref.read(pWallets).getWallet(widget.walletId) as MoneroWallet) + (ref.read(pWallets).getWallet(widget.walletId) as SalviumWallet) .highestPercentCached; if (_percent < highestPercent) { _percent = highestPercent.clamp(0.0, 1.0); } - } else if (coin is Wownero) { + } else if (coin is Monero || coin is Wownero) { final double highestPercent = - (ref.watch(pWallets).getWallet(widget.walletId) as WowneroWallet) + (ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet) + .highestPercentCached; + if (_percent < highestPercent) { + _percent = highestPercent.clamp(0.0, 1.0); + } + } else if (coin is Litecoin) { + final double highestPercent = + (ref.watch(pWallets).getWallet(widget.walletId) as MwebInterface) .highestPercentCached; if (_percent < highestPercent) { _percent = highestPercent.clamp(0.0, 1.0); @@ -637,7 +653,14 @@ class _WalletNetworkSettingsViewState ), if (coin is Monero || coin is Wownero || - coin is Epiccash) + coin is Epiccash || + coin is Salvium || + (coin is Litecoin && + ref.watch( + pWalletInfo( + widget.walletId, + ).select((s) => s.isMwebEnabled), + ))) Text( " (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})", style: STextStyles.syncPercent( diff --git a/lib/pages_desktop_specific/mweb_utxos_view.dart b/lib/pages_desktop_specific/mweb_utxos_view.dart new file mode 100644 index 000000000..0c28cdf66 --- /dev/null +++ b/lib/pages_desktop_specific/mweb_utxos_view.dart @@ -0,0 +1,281 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2025-06-12 + * + */ + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../themes/stack_colors.dart'; +import '../../utilities/assets.dart'; +import '../../utilities/text_styles.dart'; +import '../../utilities/util.dart'; +import '../../widgets/background.dart'; +import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/desktop/desktop_app_bar.dart'; +import '../../widgets/desktop/desktop_scaffold.dart'; +import '../db/drift/database.dart'; +import '../providers/providers.dart'; +import '../widgets/detail_item.dart'; +import '../widgets/rounded_white_container.dart'; + +class MwebUtxosView extends ConsumerWidget { + const MwebUtxosView({super.key, required this.walletId}); + + static const title = "MWEB outputs"; + static const String routeName = "/mwebUtxosView"; + + final String walletId; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return ConditionalParent( + condition: Util.isDesktop, + builder: (child) { + return DesktopScaffold( + appBar: DesktopAppBar( + background: Theme.of(context).extension()!.popupBG, + leading: Expanded( + child: Row( + children: [ + const SizedBox(width: 32), + AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + const SizedBox(width: 12), + Text(title, style: STextStyles.desktopH3(context)), + const Spacer(), + ], + ), + ), + useSpacers: false, + isCompactHeight: true, + ), + body: Padding(padding: const EdgeInsets.all(24), child: child), + ); + }, + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) { + return Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: AppBarBackButton( + onPressed: () => Navigator.of(context).pop(), + ), + title: Text(title, style: STextStyles.navBarTitle(context)), + ), + body: SafeArea(child: child), + ), + ); + }, + child: StreamViewList( + itemName: title, + stream: + ref + .read(pDrift(walletId)) + .select(ref.read(pDrift(walletId)).mwebUtxos) + .watch(), + itemBuilder: (MwebUtxo? coin) { + return [ + ("Output Id", coin?.outputId ?? "", 9), + ("Address", coin?.address ?? "", 9), + ("Value (sats)", coin?.value.toString() ?? "", 3), + ("Height", coin?.height.toString() ?? "", 2), + ("Block time", coin?.blockTime.toString() ?? "", 2), + ("Blocked", coin?.blocked.toString() ?? "", 2), + ("Used", coin?.used.toString() ?? "", 2), + ]; + }, + ), + ), + ); + } +} + +class StreamViewList extends StatefulWidget { + const StreamViewList({ + super.key, + required this.stream, + required this.itemBuilder, + required this.itemName, + }); + + final Stream> stream; + final String itemName; + final List<(String title, String value, int flex)> Function(T?) itemBuilder; + + @override + State> createState() => _StreamViewListState(); +} + +class _StreamViewListState extends State> { + List _items = []; + + late final StreamSubscription> _streamSubscription; + + void _onMwebUtxossCollectionWatcherEvent(List items) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _items = items; + }); + } + }); + } + + @override + void initState() { + super.initState(); + + _streamSubscription = widget.stream.listen( + (data) => _onMwebUtxossCollectionWatcherEvent(data), + ); + } + + @override + void dispose() { + _streamSubscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (Util.isDesktop) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(4), + child: RoundedWhiteContainer( + child: Row( + children: [ + Text( + "Total ${widget.itemName}: ${_items.length}", + style: STextStyles.itemSubtitle(context), + textAlign: TextAlign.left, + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(4), + child: RoundedWhiteContainer( + child: Row( + children: [ + ...widget + .itemBuilder(null) + .map( + (e) => Expanded( + flex: e.$3, + child: Text( + e.$1, + style: STextStyles.itemSubtitle(context), + textAlign: TextAlign.left, + ), + ), + ), + ], + ), + ), + ), + Expanded( + child: ListView.separated( + shrinkWrap: true, + itemCount: _items.length, + separatorBuilder: + (_, __) => Container( + height: 1, + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + ), + itemBuilder: + (_, index) => Padding( + padding: const EdgeInsets.all(4), + child: RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ...widget + .itemBuilder(_items[index]) + .map( + (e) => Expanded( + flex: e.$3, + child: SelectableText( + e.$2, + style: STextStyles.itemSubtitle12(context), + textAlign: TextAlign.left, + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } else { + return ListView.builder( + itemCount: _items.length + 1, + itemBuilder: (ctx, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 16, left: 16, right: 16), + child: RoundedWhiteContainer( + child: + index == 0 + ? Row( + children: [ + Text( + "Total ${widget.itemName}: ${_items.length}", + style: STextStyles.itemSubtitle(context), + ), + ], + ) + : Column( + mainAxisSize: MainAxisSize.min, + children: [ + ...widget + .itemBuilder(_items[index - 1]) + .map( + (e) => DetailItem(title: e.$1, detail: e.$2), + ), + ], + ), + ), + ); + }, + ); + } + } +} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index 51422b09c..20e780c97 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -30,6 +30,7 @@ import '../../../../utilities/assets.dart'; import '../../../../utilities/clipboard_interface.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/enums/derive_path_type_enum.dart'; +import '../../../../utilities/show_loading.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; @@ -40,6 +41,7 @@ import '../../../../wallets/wallet/intermediate/bip39_hd_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../../widgets/conditional_parent.dart'; @@ -71,6 +73,7 @@ class _DesktopReceiveState extends ConsumerState { late final String walletId; late final ClipboardInterface clipboard; late final bool supportsSpark; + late bool supportsMweb; late final bool showMultiType; int _currentIndex = 0; @@ -196,19 +199,50 @@ class _DesktopReceiveState extends ConsumerState { } } + Future
      _generateNewMwebAddress() async { + final wallet = ref.read(pWallets).getWallet(walletId) as MwebInterface; + + final address = await wallet.generateNextMwebAddress(); + await ref.read(mainDBProvider).isar.writeTxn(() async { + await ref.read(mainDBProvider).isar.addresses.put(address); + }); + + return address; + } + + Future generateNewMwebAddress() async { + final address = await showLoading
      ( + whileFuture: _generateNewMwebAddress(), + context: context, + message: "Generating address", + rootNavigator: Util.isDesktop, + ); + + if (mounted && address != null) { + setState(() { + _addressMap[AddressType.mweb] = address.value; + }); + } + } + @override void initState() { walletId = widget.walletId; coin = ref.read(pWalletInfo(walletId)).coin; clipboard = widget.clipboard; final wallet = ref.read(pWallets).getWallet(walletId); - supportsSpark = ref.read(pWallets).getWallet(walletId) is SparkInterface; + supportsSpark = wallet is SparkInterface; + supportsMweb = + wallet is MwebInterface && + !wallet.info.isViewOnly && + wallet.info.isMwebEnabled; if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { showMultiType = false; } else { showMultiType = supportsSpark || + supportsMweb || (wallet is! BCashInterface && wallet is Bip39HDWallet && wallet.supportedAddressTypes.length > 1); @@ -225,6 +259,10 @@ class _DesktopReceiveState extends ConsumerState { (e) => e != wallet.info.mainAddressType, ), ); + + if (supportsMweb) { + _walletAddressTypes.insert(0, AddressType.mweb); + } } } @@ -277,6 +315,54 @@ class _DesktopReceiveState extends ConsumerState { Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); + ref.listen(pWalletInfo(walletId), (prev, next) { + if (prev?.isMwebEnabled != next.isMwebEnabled) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + supportsMweb = next.isMwebEnabled; + + if (supportsMweb && + !_walletAddressTypes.contains(AddressType.mweb)) { + _walletAddressTypes.insert(0, AddressType.mweb); + _addressSubMap[AddressType.mweb] = ref + .read(mainDBProvider) + .isar + .addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.mweb) + .sortByDerivationIndexDesc() + .findFirst() + .asStream() + .listen((event) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _addressMap[AddressType.mweb] = + event?.value ?? + _addressMap[AddressType.mweb] ?? + "[No address yet]"; + }); + } + }); + }); + } else { + _walletAddressTypes.remove(AddressType.mweb); + _addressSubMap[AddressType.mweb]?.cancel(); + _addressSubMap.remove(AddressType.mweb); + } + + if (_currentIndex >= _walletAddressTypes.length) { + _currentIndex = _walletAddressTypes.length - 1; + } + }); + } + }); + } + }); + final String address; if (showMultiType) { address = _addressMap[_walletAddressTypes[_currentIndex]]!; @@ -294,7 +380,8 @@ class _DesktopReceiveState extends ConsumerState { wallet.viewOnlyType == ViewOnlyWalletType.addressOnly) { canGen = false; } else { - canGen = (wallet is MultiAddressInterface || supportsSpark); + canGen = + (wallet is MultiAddressInterface || supportsSpark || supportsMweb); } return Column( @@ -465,7 +552,10 @@ class _DesktopReceiveState extends ConsumerState { SecondaryButton( buttonHeight: ButtonHeight.l, onPressed: - supportsSpark && + supportsMweb && + _walletAddressTypes[_currentIndex] == AddressType.mweb + ? generateNewMwebAddress + : supportsSpark && _walletAddressTypes[_currentIndex] == AddressType.spark ? generateNewSparkAddress : generateNewAddress, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 2456a909c..d06d84400 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -44,6 +44,7 @@ import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet.dart' show Wallet; import '../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; @@ -59,6 +60,7 @@ import '../../../cashfusion/desktop_cashfusion_view.dart'; import '../../../churning/desktop_churning_view.dart'; import '../../../coin_control/desktop_coin_control_view.dart'; import '../../../desktop_menu.dart'; +import '../../../mweb_utxos_view.dart'; import '../../../ordinals/desktop_ordinals_view.dart'; import '../../../spark_coins/spark_coins_view.dart'; import '../desktop_wallet_view.dart'; @@ -74,6 +76,7 @@ enum WalletFeature { "Control, freeze, and utilize outputs at your discretion", ), sparkCoins("Spark coins", "View wallet spark coins"), + mwebUtxos("MWEB outputs", "View wallet MWEB outputs"), ordinals("Ordinals", "View and control your ordinals in ${AppConfig.prefix}"), monkey("MonKey", "Generate Banano MonKey"), fusion("Fusion", "Decentralized mixing protocol"), @@ -84,7 +87,8 @@ enum WalletFeature { // special cases clearSparkCache("", ""), rbf("", ""), - reuseAddress("", ""); + reuseAddress("", ""), + enableMweb("", ""); final String label; final String description; @@ -138,6 +142,12 @@ class _DesktopWalletFeaturesState extends ConsumerState { ).pushNamed(SparkCoinsView.routeName, arguments: widget.walletId); } + void _onMwebUtxosPressed() { + Navigator.of( + context, + ).pushNamed(MwebUtxosView.routeName, arguments: widget.walletId); + } + Future _onAnonymizeAllPressed() async { await showDialog( context: context, @@ -413,6 +423,13 @@ class _DesktopWalletFeaturesState extends ConsumerState { _onSparkCoinsPressed, ), + if (!isViewOnly && wallet is MwebInterface) + ( + WalletFeature.mwebUtxos, + Assets.svg.coinControl.gamePad, + _onMwebUtxosPressed, + ), + if (!isViewOnly && wallet is PaynymInterface) (WalletFeature.paynym, Assets.svg.robotHead, _onPaynymPressed), @@ -461,6 +478,8 @@ class _DesktopWalletFeaturesState extends ConsumerState { wallet.isViewOnly && wallet.viewOnlyType == ViewOnlyWalletType.addressOnly; + final showMwebOption = wallet is MwebInterface && !wallet.isViewOnly; + final extraOptions = [ if (wallet is SparkInterface && !isViewOnly) (WalletFeature.clearSparkCache, Assets.svg.key, () => ()), @@ -469,6 +488,8 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (!isViewOnlyNoAddressGen) (WalletFeature.reuseAddress, Assets.svg.key, () => ()), + + if (showMwebOption) (WalletFeature.enableMweb, Assets.svg.key, () => ()), ]; return StaticOverflowRow( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index ab48068b4..80f55b664 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -69,7 +69,8 @@ class _MoreFeaturesDialogState extends ConsumerState { } } - late final DSBController _switchController; + late final DSBController _switchControllerAddressReuse; + late final DSBController _switchControllerMwebToggle; bool _switchReuseAddressToggledLock = false; // Mutex. Future _switchReuseAddressToggled() async { @@ -79,7 +80,7 @@ class _MoreFeaturesDialogState extends ConsumerState { _switchReuseAddressToggledLock = true; // Lock mutex. try { - if (_switchController.isOn?.call() != true) { + if (_switchControllerAddressReuse.isOn?.call() != true) { final canContinue = await showDialog( context: context, builder: (context) { @@ -168,16 +169,123 @@ class _MoreFeaturesDialogState extends ConsumerState { isar: ref.read(mainDBProvider).isar, ); - if (_switchController.isOn != null) { - if (_switchController.isOn!.call() != shouldReuse) { - _switchController.activate?.call(); + if (_switchControllerAddressReuse.isOn != null) { + if (_switchControllerAddressReuse.isOn!.call() != shouldReuse) { + _switchControllerAddressReuse.activate?.call(); + } + } + } + + bool _switchMwebToggleToggledLock = false; // Mutex. + Future _switchMwebToggleToggled() async { + if (_switchMwebToggleToggledLock) { + return; + } + _switchMwebToggleToggledLock = true; // Lock mutex. + + try { + if (_switchControllerMwebToggle.isOn?.call() != true) { + final canContinue = await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 576, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Warning!", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.only( + top: 8, + left: 32, + right: 32, + bottom: 32, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "TODO warning about extra data downloaded and initial sync/scan time", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 43), + Row( + children: [ + Expanded( + child: SecondaryButton( + buttonHeight: ButtonHeight.l, + onPressed: () { + Navigator.of(context).pop(false); + }, + label: "Cancel", + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + buttonHeight: ButtonHeight.l, + onPressed: () { + Navigator.of(context).pop(true); + }, + label: "Continue", + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + }, + ); + + if (canContinue == true) { + await _updateMwebToggle(true); + + unawaited(ref.read(pWallets).getWallet(widget.walletId).init()); + } + } else { + await _updateMwebToggle(false); + } + } finally { + // ensure _switchMwebToggleToggledLock is set to false no matter what. + _switchMwebToggleToggledLock = false; + } + } + + Future _updateMwebToggle(bool shouldReuse) async { + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.mwebEnabled: shouldReuse}, + isar: ref.read(mainDBProvider).isar, + ); + + if (_switchControllerMwebToggle.isOn != null) { + if (_switchControllerMwebToggle.isOn!.call() != shouldReuse) { + _switchControllerMwebToggle.activate?.call(); } } } @override void initState() { - _switchController = DSBController(); + _switchControllerAddressReuse = DSBController(); + _switchControllerMwebToggle = DSBController(); super.initState(); } @@ -281,7 +389,7 @@ class _MoreFeaturesDialogState extends ConsumerState { )[WalletInfoKeys.reuseAddress] as bool? ?? false, - controller: _switchController, + controller: _switchControllerAddressReuse, ), ), ), @@ -299,6 +407,43 @@ class _MoreFeaturesDialogState extends ConsumerState { ), ); + case WalletFeature.enableMweb: + return _MoreFeaturesItemBase( + onPressed: _switchMwebToggleToggled, + child: Row( + children: [ + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.mwebEnabled] + as bool? ?? + false, + controller: _switchControllerMwebToggle, + ), + ), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Enable MWEB", + style: STextStyles.w600_20(context), + ), + ], + ), + ], + ), + ); + default: return _MoreFeaturesItem( label: option.$1.label, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart index 7fbcef510..7a7bc88ca 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart @@ -30,11 +30,7 @@ import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; class NetworkInfoButton extends ConsumerStatefulWidget { - const NetworkInfoButton({ - super.key, - required this.walletId, - this.eventBus, - }); + const NetworkInfoButton({super.key, required this.walletId, this.eventBus}); final String walletId; final EventBus? eventBus; @@ -74,27 +70,25 @@ class _NetworkInfoButtonState extends ConsumerState { } } - _syncStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _currentSyncStatus = event.newStatus; - }); - } - }, - ); + _syncStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentSyncStatus = event.newStatus; + }); + } + }); - _nodeStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _currentNodeStatus = event.newStatus; - }); - } - }, - ); + _nodeStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentNodeStatus = event.newStatus; + }); + } + }); super.initState(); } @@ -151,9 +145,9 @@ class _NetworkInfoButtonState extends ConsumerState { return Text( label, - style: STextStyles.desktopMenuItemSelected(context).copyWith( - color: _getColor(status, context), - ), + style: STextStyles.desktopMenuItemSelected( + context, + ).copyWith(color: _getColor(status, context)), ); } @@ -172,9 +166,7 @@ class _NetworkInfoButtonState extends ConsumerState { Widget build(BuildContext context) { return RawMaterialButton( hoverColor: _getColor(_currentSyncStatus, context).withOpacity(0.1), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(1000), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(1000)), onPressed: () { if (Util.isDesktop) { // showDialog( @@ -220,88 +212,80 @@ class _NetworkInfoButtonState extends ConsumerState { showDialog( context: context, - builder: (context) => Navigator( - initialRoute: WalletNetworkSettingsView.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - FadePageRoute( - DesktopDialog( - maxHeight: null, - maxWidth: 580, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Network", - style: STextStyles.desktopH3(context), - ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + builder: + (context) => Navigator( + initialRoute: WalletNetworkSettingsView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + DesktopDialog( + maxHeight: null, + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Network", + style: STextStyles.desktopH3(context), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + ], ), - ], - ), - ), - Flexible( - child: Padding( - padding: const EdgeInsets.only( - top: 16, - left: 32, - right: 32, - bottom: 32, ), - child: SingleChildScrollView( - child: WalletNetworkSettingsView( - walletId: walletId, - initialSyncStatus: _currentSyncStatus, - initialNodeStatus: _currentNodeStatus, + Flexible( + child: Padding( + padding: const EdgeInsets.only( + top: 16, + left: 32, + right: 32, + bottom: 32, + ), + child: SingleChildScrollView( + child: WalletNetworkSettingsView( + walletId: walletId, + initialSyncStatus: _currentSyncStatus, + initialNodeStatus: _currentNodeStatus, + ), + ), ), ), - ), + ], ), - ], + ), + const RouteSettings( + name: WalletNetworkSettingsView.routeName, + ), ), - ), - const RouteSettings( - name: WalletNetworkSettingsView.routeName, - ), - ), - ]; - }, - ), + ]; + }, + ), ); } else { Navigator.of(context).pushNamed( WalletNetworkSettingsView.routeName, - arguments: Tuple3( - walletId, - _currentSyncStatus, - _currentNodeStatus, - ), + arguments: Tuple3(walletId, _currentSyncStatus, _currentNodeStatus), ); } }, child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, - horizontal: 32, - ), + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 32), child: Row( children: [ _buildNetworkIcon(_currentSyncStatus, context), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), _buildText(_currentSyncStatus, context), ], ), diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 7c0f4ea13..3266d1273 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -178,6 +178,7 @@ import 'pages_desktop_specific/desktop_buy/desktop_buy_view.dart'; import 'pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart'; import 'pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart'; import 'pages_desktop_specific/desktop_home_view.dart'; +import 'pages_desktop_specific/mweb_utxos_view.dart'; import 'pages_desktop_specific/my_stack_view/my_stack_view.dart'; import 'pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart'; import 'pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart'; @@ -2227,6 +2228,16 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case MwebUtxosView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => MwebUtxosView(walletId: args), + settings: RouteSettings(name: settings.name), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case DesktopCoinControlView.routeName: if (args is String) { return getRoute( diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart new file mode 100644 index 000000000..00ace0d24 --- /dev/null +++ b/lib/services/mwebd_service.dart @@ -0,0 +1,228 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; + +import 'package:flutter_mwebd/flutter_mwebd.dart'; +import 'package:mutex/mutex.dart'; +import 'package:mweb_client/mweb_client.dart'; + +import '../utilities/logger.dart'; +import '../utilities/prefs.dart'; +import '../utilities/stack_file_system.dart'; +import '../wallets/crypto_currency/crypto_currency.dart'; +import 'event_bus/events/global/mweb_status_changed_event.dart'; +import 'event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'event_bus/events/global/tor_status_changed_event.dart'; +import 'event_bus/global_event_bus.dart'; +import 'tor_service.dart'; + +final class MwebdService { + final Map + _map = {}; + + late final StreamSubscription + _torStatusListener; + late final StreamSubscription + _torPreferenceListener; + late final StreamSubscription + _mwebPreferenceListener; + + final Mutex _torConnectingLock = Mutex(); + + static final instance = MwebdService._(); + + MwebdService._() { + final bus = GlobalEventBus.instance; + + // Listen for tor status changes. + _torStatusListener = bus.on().listen(( + event, + ) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + if (!_torConnectingLock.isLocked) { + await _torConnectingLock.acquire(); + } + break; + + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } + break; + } + }); + + // Listen for tor preference changes. + _torPreferenceListener = bus.on().listen(( + event, + ) async { + if (Prefs.instance.useTor) { + return await _torConnectingLock.protect(() async { + final proxyInfo = TorService.sharedInstance.getProxyInfo(); + return await _update(proxyInfo); + }); + } else { + return await _update(null); + } + }); + + // Listen for mweb preference changes. + _mwebPreferenceListener = bus.on().listen(( + event, + ) async { + switch (event.status) { + case MwebStatus.enabled: + // as we don't know which network(s) to use here + // we will rely on status checks and init as required within wallets + break; + + case MwebStatus.disabled: + final nets = _map.keys; + for (final net in nets) { + final old = _map.remove(net)!; + await old.client.cleanup(); + await old.server.stopServer(); + } + break; + } + }); + } + + // locked while mweb servers and clients are updating + final _updateLock = Mutex(); + + // update function called when Tor pref changed + Future _update(({InternetAddress host, int port})? proxyInfo) async { + await _updateLock.protect(() async { + final proxy = + proxyInfo == null + ? "" + : "${proxyInfo.host.address}:${proxyInfo.port}"; + final nets = _map.keys; + for (final net in nets) { + final old = _map.remove(net)!; + + await old.client.cleanup(); + await old.server.stopServer(); + + final port = await _getRandomUnusedPort(); + if (port == null) { + throw Exception("Could not find an unused port for mwebd"); + } + + final newServer = MwebdServer( + chain: old.server.chain, + dataDir: old.server.dataDir, + peer: old.server.peer, + proxy: proxy, + serverPort: port, + ); + await newServer.createServer(); + await newServer.startServer(); + + final newClient = MwebClient.fromHost( + "127.0.0.1", + newServer.serverPort, + ); + + _map[net] = (server: newServer, client: newClient); + } + }); + } + + Future init(CryptoCurrencyNetwork net) async { + Logging.instance.i("MwebdService init($net) called..."); + await _updateLock.protect(() async { + if (_map[net] != null) { + Logging.instance.i("MwebdService init($net) was already called."); + return; + } + + final port = await _getRandomUnusedPort(); + + if (port == null) { + throw Exception("Could not find an unused port for mwebd"); + } + + final chain = switch (net) { + CryptoCurrencyNetwork.main => "mainnet", + CryptoCurrencyNetwork.test => "testnet", + CryptoCurrencyNetwork.stage => throw UnimplementedError(), + CryptoCurrencyNetwork.test4 => throw UnimplementedError(), + }; + + final dir = await StackFileSystem.applicationMwebdDirectory(chain); + + final String proxy; + if (Prefs.instance.useTor) { + final proxyInfo = TorService.sharedInstance.getProxyInfo(); + proxy = "${proxyInfo.host.address}:${proxyInfo.port}"; + } else { + proxy = ""; + } + + final newServer = MwebdServer( + chain: chain, + dataDir: dir.path, + peer: "", + proxy: proxy, + serverPort: port, + ); + await newServer.createServer(); + await newServer.startServer(); + + final newClient = MwebClient.fromHost("127.0.0.1", newServer.serverPort); + + _map[net] = (server: newServer, client: newClient); + + Logging.instance.i("MwebdService init($net) completed!"); + }); + } + + /// Get server status. Returns null if no server was initialized. + Future getServerStatus(CryptoCurrencyNetwork net) async { + return await _updateLock.protect(() async { + return await _map[net]?.server.getStatus(); + }); + } + + /// Get client for network. Returns null if no server was initialized. + Future getClient(CryptoCurrencyNetwork net) async { + return await _updateLock.protect(() async { + return _map[net]?.client; + }); + } +} + +// ============================================================================ +Future _getRandomUnusedPort({Set excluded = const {}}) async { + const int minPort = 1024; + const int maxPort = 65535; + const int maxAttempts = 1000; + + final random = Random.secure(); + + for (int i = 0; i < maxAttempts; i++) { + final int potentialPort = minPort + random.nextInt(maxPort - minPort + 1); + + if (excluded.contains(potentialPort)) { + continue; + } + + try { + final ServerSocket socket = await ServerSocket.bind( + InternetAddress.anyIPv4, + potentialPort, + ); + await socket.close(); + return potentialPort; + } catch (_) { + excluded.add(potentialPort); + continue; + } + } + + return null; +} diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index fa3872a7c..087aaa631 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -16,7 +16,6 @@ import 'package:uuid/uuid.dart'; import '../app_config.dart'; import '../db/hive/db.dart'; -import '../services/event_bus/events/global/mweb_status_changed_event.dart'; import '../services/event_bus/events/global/tor_status_changed_event.dart'; import '../services/event_bus/global_event_bus.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; @@ -1348,37 +1347,4 @@ class Prefs extends ChangeNotifier { return Level.warning; } } - - // enabled mweb - - bool _useMweb = false; - - bool get useMweb => _useMweb; - - set useMweb(bool useMweb) { - if (_useMweb != useMweb) { - DB.instance.put( - boxName: DB.boxNamePrefs, - key: "useMweb", - value: useMweb, - ); - _useMweb = useMweb; - notifyListeners(); - GlobalEventBus.instance.fire( - MwebPreferenceChangedEvent( - status: useMweb ? MwebStatus.enabled : MwebStatus.disabled, - message: "useMweb updated in prefs", - ), - ); - } - } - - Future _getUseMweb() async { - return await DB.instance.get( - boxName: DB.boxNamePrefs, - key: "useMweb", - ) - as bool? ?? - false; - } } diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index c7b91eca1..e13557739 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -143,7 +143,7 @@ abstract class StackFileSystem { final root = await applicationRootDirectory(); final dir = Directory(path.join(root.path, "mwebd", network)); if (!dir.existsSync()) { - await dir.create(); + await dir.create(recursive: true); } return dir; } diff --git a/lib/wallets/isar/models/wallet_info.dart b/lib/wallets/isar/models/wallet_info.dart index bb4dd4ab2..6df8dc456 100644 --- a/lib/wallets/isar/models/wallet_info.dart +++ b/lib/wallets/isar/models/wallet_info.dart @@ -139,6 +139,10 @@ class WalletInfo implements IsarId { bool get isDuressVisible => otherData[WalletInfoKeys.duressMarkedVisibleWalletKey] as bool? ?? false; + @ignore + bool get isMwebEnabled => + otherData[WalletInfoKeys.mwebEnabled] as bool? ?? false; + //============================================================================ //============= Updaters ================================================ @@ -392,6 +396,16 @@ class WalletInfo implements IsarId { ); } + Future setMwebEnabled({ + required bool newValue, + required Isar isar, + }) async { + await updateOtherData( + newEntries: {WalletInfoKeys.mwebEnabled: newValue}, + isar: isar, + ); + } + //============================================================================ WalletInfo({ @@ -505,4 +519,6 @@ abstract class WalletInfoKeys { static const String viewOnlyTypeIndexKey = "viewOnlyTypeIndexKey"; static const String duressMarkedVisibleWalletKey = "duressMarkedVisibleWalletKey"; + static const String mwebEnabled = "mwebEnabledKey"; + static const String mwebScanHeight = "mwebScanHeightKey"; } diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 28b985be4..6353a330a 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -3,6 +3,7 @@ import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; import 'package:tezart/tezart.dart' as tezart; import 'package:web3dart/web3dart.dart' as web3dart; +import '../../db/drift/database.dart'; import '../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; @@ -82,6 +83,11 @@ class TxData { // Namecoin Name related final NameOpState? opNameState; + // MWEB + final bool isMweb; + final Set? mwebUtxos; + final List? usedMwebUtxos; + TxData({ this.feeRateType, this.feeRateAmount, @@ -116,6 +122,9 @@ class TxData { this.ignoreCachedBalanceChecks = false, this.opNameState, this.sparkNameInfo, + this.isMweb = false, + this.mwebUtxos, + this.usedMwebUtxos, }); Amount? get amount { @@ -263,6 +272,9 @@ class TxData { int validBlocks, })? sparkNameInfo, + bool? isMweb, + Set? mwebUtxos, + List? usedMwebUtxos, }) { return TxData( feeRateType: feeRateType ?? this.feeRateType, @@ -300,6 +312,9 @@ class TxData { ignoreCachedBalanceChecks ?? this.ignoreCachedBalanceChecks, opNameState: opNameState ?? this.opNameState, sparkNameInfo: sparkNameInfo ?? this.sparkNameInfo, + isMweb: isMweb ?? this.isMweb, + mwebUtxos: mwebUtxos ?? this.mwebUtxos, + usedMwebUtxos: usedMwebUtxos ?? this.usedMwebUtxos, ); } @@ -338,5 +353,8 @@ class TxData { 'ignoreCachedBalanceChecks: $ignoreCachedBalanceChecks, ' 'opNameState: $opNameState, ' 'sparkNameInfo: $sparkNameInfo, ' + 'isMweb: $isMweb, ' + 'mwebUtxos: $mwebUtxos, ' + 'usedMwebUtxos: $usedMwebUtxos, ' '}'; } diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index 7f0c4fd8b..db22a5b55 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -53,6 +53,8 @@ class LitecoinWallet .not() .group( (q) => q + .typeEqualTo(AddressType.mweb) + .or() .typeEqualTo(AddressType.nonWallet) .or() .subTypeEqualTo(AddressSubType.nonWallet), diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index 1de1577cc..b30fc1a30 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -1,13 +1,40 @@ +import 'dart:async'; +import 'dart:math' as math; + +import 'package:drift/drift.dart'; +import 'package:fixnum/fixnum.dart'; import 'package:isar/isar.dart'; +import 'package:mweb_client/mweb_client.dart'; +import '../../../db/drift/database.dart'; +import '../../../models/balance.dart'; import '../../../models/isar/models/isar_models.dart'; +import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; +import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; +import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import '../../../services/event_bus/global_event_bus.dart'; +import '../../../services/mwebd_service.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/extensions/extensions.dart'; +import '../../../utilities/logger.dart'; import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; +import '../../isar/models/wallet_info.dart'; +import '../../models/tx_data.dart'; import 'electrumx_interface.dart'; mixin MwebInterface on ElectrumXInterface { // TODO + StreamSubscription? _mwebUtxoSubscription; + + Future get _scanSecret async => + (await getRootHDNode()).derivePath("m/1000'/0'").privateKey.data; + Future get _spendSecret async => + (await getRootHDNode()).derivePath("m/1000'/1'").privateKey.data; + Future get _spendPub async => + (await getRootHDNode()).derivePath("m/1000'/1'").publicKey.data; + Future getCurrentReceivingMwebAddress() async { return await mainDB.isar.addresses .where() @@ -17,4 +44,529 @@ mixin MwebInterface .sortByDerivationIndexDesc() .findFirst(); } + + Future get _client async { + final client = await MwebdService.instance.getClient( + cryptoCurrency.network, + ); + if (client == null) { + throw Exception("Fetched mweb client returned null"); + } + return client; + } + + WalletSyncStatus? _syncStatus; + Timer? _mwebdPolling; + int currentKnownChainHeight = 0; + double highestPercentCached = 0; + void _startPollingMwebd() async { + _mwebdPolling?.cancel(); + _mwebdPolling = Timer.periodic(const Duration(seconds: 5), (_) async { + try { + final status = await MwebdService.instance.getServerStatus( + cryptoCurrency.network, + ); + + Logging.instance.i("_polling mwebd status: $status"); + + if (status == null) { + throw Exception( + "Mwebd server status is null. Was mwebd initialized?", + ); + } + + final currentKnownChainHeight = await chainHeight; + + final ({int remaining, double percent})? syncInfo; + + if (status.blockHeaderHeight < currentKnownChainHeight) { + syncInfo = ( + remaining: currentKnownChainHeight - status.blockHeaderHeight, + percent: status.blockHeaderHeight / currentKnownChainHeight, + ); + } else if (status.mwebHeaderHeight < currentKnownChainHeight) { + syncInfo = ( + remaining: currentKnownChainHeight - status.mwebHeaderHeight, + percent: status.mwebHeaderHeight / currentKnownChainHeight, + ); + } else if (status.mwebUtxosHeight < currentKnownChainHeight) { + syncInfo = (remaining: 1, percent: 0.99); + } else { + syncInfo = null; + } + + WalletSyncStatus? syncStatus; + + if (syncInfo != null) { + final previous = highestPercentCached; + highestPercentCached = math.max( + highestPercentCached, + syncInfo.percent, + ); + + if (previous != highestPercentCached) { + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(highestPercentCached, walletId), + ); + GlobalEventBus.instance.fire( + BlocksRemainingEvent(syncInfo.remaining, walletId), + ); + } + + syncStatus = WalletSyncStatus.syncing; + } else { + final walletMwebScanHeight = + info.otherData[WalletInfoKeys.mwebScanHeight] as int? ?? + info.restoreHeight; + + if (status.mwebUtxosHeight > walletMwebScanHeight) { + // TODO: check utxos and transactions? + + // then + await info.updateOtherData( + newEntries: { + WalletInfoKeys.mwebScanHeight: status.mwebUtxosHeight, + }, + isar: mainDB.isar, + ); + } + + syncStatus = WalletSyncStatus.synced; + } + + _syncStatus = syncStatus; + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent(syncStatus, walletId, info.coin), + ); + } catch (e, s) { + Logging.instance.e( + "mweb wallet polling error", + error: e, + stackTrace: s, + ); + _syncStatus = WalletSyncStatus.unableToSync; + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent(_syncStatus!, walletId, info.coin), + ); + } + }); + } + + Future _startUpdateMwebUtxos() async { + final client = await _client; + + Logging.instance.i("info.restoreHeight: ${info.restoreHeight}"); + final fromHeight = info.restoreHeight; + + final request = UtxosRequest( + fromHeight: fromHeight, + scanSecret: await _scanSecret, + ); + + await _mwebUtxoSubscription?.cancel(); + final db = Drift.get(walletId); + _mwebUtxoSubscription = (await client.utxos(request)).listen((utxo) async { + Logging.instance.i( + "Found UTXO in stream: Utxo(" + "height: ${utxo.height}, " + "value: ${utxo.value}, " + "address: ${utxo.address}, " + "outputId: ${utxo.outputId}, " + "blockTime: ${utxo.blockTime}" + ")", + ); + + if (utxo.address.isNotEmpty && utxo.outputId.isNotEmpty) { + try { + await db.transaction(() async { + final prev = + await (db.select(db.mwebUtxos)..where( + (e) => e.outputId.equals(utxo.outputId), + )).getSingleOrNull(); + + await db + .into(db.mwebUtxos) + .insertOnConflictUpdate( + MwebUtxosCompanion( + outputId: Value(prev?.outputId ?? utxo.outputId), + address: Value(prev?.address ?? utxo.address), + value: Value(utxo.value.toInt()), + height: Value(utxo.height), + blockTime: Value(utxo.blockTime), + blocked: Value(prev?.blocked ?? false), + used: Value(prev?.used ?? false), + ), + ); + }); + } catch (e, s) { + Logging.instance.f( + "Failed to insert/update mweb utxo", + error: e, + stackTrace: s, + ); + } + } else { + Logging.instance.w("Empty mweb utxo not added to db... ??"); + } + }); + } + + Future _initMweb() async { + try { + // check server is up + final status = await MwebdService.instance.getServerStatus( + cryptoCurrency.network, + ); + if (status == null) { + await MwebdService.instance.init(cryptoCurrency.network); + } + + _startPollingMwebd(); + } catch (e, s) { + Logging.instance.e("testing initMweb failed", error: e, stackTrace: s); + } + } + + Future
      generateNextMwebAddress() async { + if (!info.isMwebEnabled) { + throw Exception( + "Tried calling generateNextMwebAddress with mweb disabled for $walletId ${info.name}", + ); + } + final highestStoredIndex = + (await getCurrentReceivingMwebAddress())?.derivationIndex ?? -1; + + final nextIndex = highestStoredIndex + 1; + + final client = await _client; + + final response = await client.address( + await _scanSecret, + await _spendPub, + nextIndex, + ); + + return Address( + walletId: walletId, + value: response, + publicKey: [], + derivationIndex: nextIndex, + derivationPath: null, + type: AddressType.mweb, + subType: AddressSubType.receiving, + ); + } + + Future estimateFeeForMweb(Amount amount) async { + if (!info.isMwebEnabled) { + throw Exception( + "Tried calling estimateFeeForMweb with mweb disabled for $walletId ${info.name}", + ); + } + throw UnimplementedError(); + } + + Future prepareSendMweb({required TxData txData}) async { + if (!info.isMwebEnabled) { + throw Exception( + "Tried calling prepareSendMweb with mweb disabled for $walletId ${info.name}", + ); + } + if (!txData.isMweb) { + throw Exception("Invalid mweb flagged tx data"); + } + + final client = await _client; + + final response = await client.create( + CreateRequest( + rawTx: txData.raw!.toUint8ListFromHex, + scanSecret: await _scanSecret, + spendSecret: await _spendSecret, + feeRatePerKb: Int64(txData.feeRateAmount!.toInt()), + dryRun: false, + ), + ); + + return txData.copyWith(raw: Uint8List.fromList(response.rawTx).toHex); + } + + Future confirmSendMweb({required TxData txData}) async { + if (!info.isMwebEnabled) { + throw Exception( + "Tried calling confirmSendMweb with mweb disabled for $walletId ${info.name}", + ); + } + + try { + Logging.instance.d("confirmSend txData: $txData"); + + final txHash = await electrumXClient.broadcastTransaction( + rawTx: txData.raw!, + ); + Logging.instance.d("Sent txHash: $txHash"); + + txData = txData.copyWith(txHash: txHash, txid: txHash); + + // Update used mweb utxos as used in database. They should already have + // been marked as isUsed. + if (txData.usedMwebUtxos != null && txData.usedMwebUtxos!.isNotEmpty) { + final db = Drift.get(walletId); + await db.transaction(() async { + for (final utxo in txData.usedMwebUtxos!) { + await db + .into(db.mwebUtxos) + .insertOnConflictUpdate(utxo.toCompanion(false)); + } + }); + } else { + Logging.instance.w( + "txData.usedMwebUtxos is empty or null when it very " + "likely should not be!", + ); + } + + return await updateSentCachedTxData(txData: txData); + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from confirmSendMweb(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + } + + /// Should only be called within the standard wallet [recover] function due to + /// mutex locking. Otherwise behaviour MAY be undefined. + Future recoverMweb() async { + if (!info.isMwebEnabled) { + Logging.instance.e( + "Tried calling recoverMweb with mweb disabled for $walletId ${info.name}", + ); + return; + } + + throw UnimplementedError(); + } + + Future anonymizeAllMweb() async { + if (!info.isMwebEnabled) { + Logging.instance.e( + "Tried calling anonymizeAllMweb with mweb disabled for $walletId ${info.name}", + ); + return; + } + + try { + final currentHeight = await chainHeight; + + final spendableUtxos = + await mainDB.isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .isBlockedEqualTo(false) + .and() + .group((q) => q.usedEqualTo(false).or().usedIsNull()) + .and() + .valueGreaterThan(0) + .findAll(); + + spendableUtxos.removeWhere( + (e) => + !e.isConfirmed( + currentHeight, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + ), + ); + + if (spendableUtxos.isEmpty) { + throw Exception("No available UTXOs found to anonymize"); + } + + // TODO finish + final txData = await prepareSendMweb( + txData: TxData(utxos: spendableUtxos.toSet()), + ); + + await confirmSendMweb(txData: txData); + } catch (e, s) { + Logging.instance.w( + "Exception caught in anonymizeAllMweb(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + } + + // =========================================================================== + + @override + Future init() async { + if (info.isMwebEnabled) { + try { + await _initMweb(); + Address? address = await getCurrentReceivingMwebAddress(); + if (address == null) { + address = await generateNextMwebAddress(); + await mainDB.putAddress(address); + } + + unawaited(_startUpdateMwebUtxos()); + } catch (e, s) { + // do nothing, still allow user into wallet + Logging.instance.e( + "$runtimeType init() failed", + error: e, + stackTrace: s, + ); + } + } + + // await info.updateReceivingAddress( + // newAddress: address.value, + // isar: mainDB.isar, + // ); + + await super.init(); + } + + @override + Future updateBalance() async { + // call to super to update transparent balance + final normalBalanceFuture = super.updateBalance(); + + if (info.isMwebEnabled) { + final start = DateTime.now(); + try { + final currentHeight = await chainHeight; + final db = Drift.get(walletId); + final mwebUtxos = + await (db.select(db.mwebUtxos) + ..where((e) => e.used.equals(false))).get(); + + Amount satoshiBalanceTotal = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); + Amount satoshiBalancePending = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); + Amount satoshiBalanceSpendable = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); + Amount satoshiBalanceBlocked = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); + + for (final utxo in mwebUtxos) { + final utxoAmount = Amount( + rawValue: BigInt.from(utxo.value), + fractionDigits: cryptoCurrency.fractionDigits, + ); + + satoshiBalanceTotal += utxoAmount; + + if (utxo.blocked) { + satoshiBalanceBlocked += utxoAmount; + } else { + if (utxo.isConfirmed( + currentHeight, + cryptoCurrency.minConfirms, + // overrideMinConfirms: TODO: set this??? + )) { + satoshiBalanceSpendable += utxoAmount; + } else { + satoshiBalancePending += utxoAmount; + } + } + } + + final balance = Balance( + total: satoshiBalanceTotal, + spendable: satoshiBalanceSpendable, + blockedTotal: satoshiBalanceBlocked, + pendingSpendable: satoshiBalancePending, + ); + + await info.updateBalanceSecondary( + newBalance: balance, + isar: mainDB.isar, + ); + } catch (e, s) { + Logging.instance.e( + "$runtimeType updateBalance mweb $walletId ${info.name}: ", + error: e, + stackTrace: s, + ); + } finally { + Logging.instance.d( + "${info.name} updateBalance mweb duration:" + " ${DateTime.now().difference(start)}", + ); + } + } + + // wait for normalBalanceFuture to complete before returning + await normalBalanceFuture; + } + + @override + Future refresh() async { + if (isViewOnly || !info.isMwebEnabled) { + await super.refresh(); + return; + } + + // Awaiting this lock could be dangerous. + // Since refresh is periodic (generally) + if (refreshMutex.isLocked) { + return; + } + + // TODO + + // final node = getCurrentNode(); + // + // if (_torNodeMismatchGuard(node)) { + // throw Exception("TOR – clearnet mismatch"); + // } + // + // // this acquire should be almost instant due to above check. + // // Slight possibility of race but should be irrelevant + // await refreshMutex.acquire(); + // + // libMoneroWallet?.startSyncing(); + // _setSyncStatus(lib_monero_compat.StartingSyncStatus()); + // + // await updateTransactions(); + // await updateBalance(); + // + // if (info.otherData[WalletInfoKeys.reuseAddress] != true) { + // await checkReceivingAddressForTransactions(); + // } + // + // if (refreshMutex.isLocked) { + // refreshMutex.release(); + // } + // + // final synced = await libMoneroWallet?.isSynced(); + // + // if (synced == true) { + // _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); + // } + } + + @override + Future exit() async { + _mwebdPolling?.cancel(); + _mwebdPolling = null; + await super.exit(); + } } diff --git a/pubspec.lock b/pubspec.lock index 563118121..4db79d477 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -884,7 +884,7 @@ packages: source: git version: "8.3.1" fixnum: - dependency: transitive + dependency: "direct main" description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be @@ -1566,10 +1566,10 @@ packages: dependency: "direct main" description: name: mweb_client - sha256: "8c9498adaaa1166a49ee114b03498268aff176778eeb311ed049fd22657feacb" + sha256: "263ba560dab7e63a1d03875d455a19cc4a1ab9720786cd9d6ffcc42127d06732" url: "https://pub.dev" source: hosted - version: "0.1.0" + version: "0.2.0" namecoin: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 3fa0f3077..de8d4dadc 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -222,7 +222,8 @@ dependencies: cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 flutter_mwebd: ^0.0.1-pre.1 - mweb_client: ^0.1.0 + mweb_client: ^0.2.0 + fixnum: ^1.1.1 dev_dependencies: flutter_test: From 77522108417e877012498884b1ea7ad130901d82 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 13 Jun 2025 11:29:25 -0600 Subject: [PATCH 131/206] WIP: mweb recovery --- .../models/blockchain_data/transaction.dart | 22 +- .../wallet_view/desktop_wallet_view.dart | 30 +- .../mweb_desktop_wallet_summary.dart | 206 ++++++++++++++ .../electrumx_interface.dart | 2 + .../mweb_interface.dart | 264 +++++++++++++++--- 5 files changed, 464 insertions(+), 60 deletions(-) create mode 100644 lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart diff --git a/lib/models/isar/models/blockchain_data/transaction.dart b/lib/models/isar/models/blockchain_data/transaction.dart index d5b3572fe..417856079 100644 --- a/lib/models/isar/models/blockchain_data/transaction.dart +++ b/lib/models/isar/models/blockchain_data/transaction.dart @@ -151,7 +151,8 @@ class Transaction { } @override - toString() => "{ " + toString() => + "{ " "id: $id, " "walletId: $walletId, " "txid: $txid, " @@ -217,12 +218,14 @@ class Transaction { slateId: json["slateId"] as String?, otherData: json["otherData"] as String?, nonce: json["nonce"] as int?, - inputs: List.from(json["inputs"] as List) - .map((e) => Input.fromJsonString(e)) - .toList(), - outputs: List.from(json["outputs"] as List) - .map((e) => Output.fromJsonString(e)) - .toList(), + inputs: + List.from( + json["inputs"] as List, + ).map((e) => Input.fromJsonString(e)).toList(), + outputs: + List.from( + json["outputs"] as List, + ).map((e) => Output.fromJsonString(e)).toList(), numberOfMessages: json["numberOfMessages"] as int, ); if (json["address"] == null) { @@ -241,7 +244,7 @@ enum TransactionType { outgoing, incoming, sentToSelf, // should we keep this? - unknown; + unknown, } // Used in Isar db and stored there as int indexes so adding/removing values @@ -256,5 +259,6 @@ enum TransactionSubType { cashFusion, sparkMint, // firo specific sparkSpend, // firo specific - ordinal; + ordinal, + mweb, } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index e35e6ed34..96363f1e2 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -28,7 +28,6 @@ import '../../../pages/wallet_view/sub_widgets/transactions_list.dart'; import '../../../pages/wallet_view/transaction_views/all_transactions_view.dart'; import '../../../pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart'; import '../../../pages/wallet_view/transaction_views/tx_v2/transaction_v2_list.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/active_wallet_provider.dart'; import '../../../providers/global/auto_swb_service_provider.dart'; import '../../../providers/providers.dart'; @@ -46,6 +45,7 @@ import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../wallets/wallet/impl/banano_wallet.dart'; import '../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../wallets/wallet/wallet.dart'; +import '../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_buttons/blue_text_button.dart'; @@ -57,6 +57,7 @@ import '../../coin_control/desktop_coin_control_use_dialog.dart'; import 'sub_widgets/desktop_wallet_features.dart'; import 'sub_widgets/desktop_wallet_summary.dart'; import 'sub_widgets/firo_desktop_wallet_summary.dart'; +import 'sub_widgets/mweb_desktop_wallet_summary.dart'; import 'sub_widgets/my_wallet.dart'; import 'sub_widgets/network_info_button.dart'; import 'sub_widgets/wallet_keys_button.dart'; @@ -448,13 +449,26 @@ class DesktopWalletHeaderRow extends ConsumerWidget { ), if (wallet is! FiroWallet) - DesktopWalletSummary( - walletId: wallet.walletId, - initialSyncStatus: - wallet.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, - ), + wallet is MwebInterface && + ref.watch( + pWalletInfo( + wallet.walletId, + ).select((s) => s.isMwebEnabled), + ) + ? MwebDesktopWalletSummary( + walletId: wallet.walletId, + initialSyncStatus: + wallet.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, + ) + : DesktopWalletSummary( + walletId: wallet.walletId, + initialSyncStatus: + wallet.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, + ), Expanded(child: DesktopWalletFeatures(walletId: wallet.walletId)), ], ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart new file mode 100644 index 000000000..942d08fa1 --- /dev/null +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart @@ -0,0 +1,206 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2025 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2025-06-13 + * + */ + +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../pages/wallet_view/sub_widgets/wallet_refresh_button.dart'; +import '../../../../providers/providers.dart'; +import '../../../../providers/wallet/wallet_balance_toggle_state_provider.dart'; +import '../../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import '../../../../themes/stack_colors.dart'; +import '../../../../utilities/amount/amount.dart'; +import '../../../../utilities/amount/amount_formatter.dart'; +import '../../../../utilities/enums/wallet_balance_toggle_state.dart'; +import '../../../../utilities/text_styles.dart'; +import '../../../../wallets/crypto_currency/crypto_currency.dart'; +import '../../../../wallets/isar/providers/wallet_info_provider.dart'; +import 'desktop_balance_toggle_button.dart'; + +class MwebDesktopWalletSummary extends ConsumerStatefulWidget { + const MwebDesktopWalletSummary({ + super.key, + required this.walletId, + required this.initialSyncStatus, + }); + + final String walletId; + final WalletSyncStatus initialSyncStatus; + + @override + ConsumerState createState() => + _WMwebDesktopWalletSummaryState(); +} + +class _WMwebDesktopWalletSummaryState + extends ConsumerState { + late final String walletId; + + late final CryptoCurrency coin; + late final bool isMweb; + + @override + void initState() { + super.initState(); + walletId = widget.walletId; + coin = ref.read(pWalletCoin(widget.walletId)); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + Decimal? price; + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.externalCalls), + )) { + price = + ref + .watch( + priceAnd24hChangeNotifierProvider.select( + (value) => value.getPrice(coin), + ), + ) + ?.value; + } + + final _showAvailable = + ref.watch(walletBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available; + + final balance0 = ref.watch(pWalletBalanceSecondary(walletId)); + final balanceToShowSpark = + _showAvailable ? balance0.spendable : balance0.total; + + final balance2 = ref.watch(pWalletBalance(walletId)); + final balanceToShowPublic = + _showAvailable ? balance2.spendable : balance2.total; + + return Consumer( + builder: (context, ref, __) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + columnWidths: { + 0: const IntrinsicColumnWidth(), + 1: const IntrinsicColumnWidth(), + if (price != null) 2: const IntrinsicColumnWidth(), + }, + children: [ + TableRow( + children: [ + const _Prefix(isMweb: true), + _Balance(coin: coin, amount: balanceToShowSpark), + if (price != null) + _Price( + coin: coin, + amount: balanceToShowSpark, + price: price, + ), + ], + ), + + TableRow( + children: [ + const _Prefix(isMweb: false), + _Balance(coin: coin, amount: balanceToShowPublic), + if (price != null) + _Price( + coin: coin, + amount: balanceToShowPublic, + price: price, + ), + ], + ), + ], + ), + + const SizedBox(width: 8), + WalletRefreshButton( + walletId: walletId, + initialSyncStatus: widget.initialSyncStatus, + ), + const SizedBox(width: 8), + const DesktopBalanceToggleButton(), + ], + ); + }, + ); + } +} + +class _Prefix extends StatelessWidget { + const _Prefix({super.key, required this.isMweb}); + + final bool isMweb; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SelectableText( + isMweb ? "MWEB" : "", + style: STextStyles.w500_24(context), + ), + ], + ), + ); + } +} + +class _Balance extends ConsumerWidget { + const _Balance({super.key, required this.coin, required this.amount}); + + final CryptoCurrency coin; + final Amount amount; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return SelectableText( + ref.watch(pAmountFormatter(coin)).format(amount, ethContract: null), + style: STextStyles.desktopH3(context), + textAlign: TextAlign.end, + ); + } +} + +class _Price extends ConsumerWidget { + const _Price({ + super.key, + required this.coin, + required this.amount, + required this.price, + }); + + final CryptoCurrency coin; + final Amount amount; + final Decimal price; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Padding( + padding: const EdgeInsets.only(left: 16), + child: SelectableText( + "${Amount.fromDecimal(price * amount.decimal, fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} " + "${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context).extension()!.textSubtitle1, + ), + + textAlign: TextAlign.end, + ), + ); + } +} diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 8fe157a61..dda6b2876 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; import 'package:isar/isar.dart'; +import 'package:meta/meta.dart'; import '../../../electrumx_rpc/cached_electrumx_client.dart'; import '../../../electrumx_rpc/client_manager.dart'; @@ -1788,6 +1789,7 @@ mixin ElectrumXInterface } } + @mustCallSuper @override Future init() async { try { diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index b30fc1a30..f812faba8 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -1,13 +1,17 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:math' as math; import 'package:drift/drift.dart'; import 'package:fixnum/fixnum.dart'; import 'package:isar/isar.dart'; +import 'package:meta/meta.dart'; import 'package:mweb_client/mweb_client.dart'; import '../../../db/drift/database.dart'; import '../../../models/balance.dart'; +import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; @@ -67,7 +71,9 @@ mixin MwebInterface cryptoCurrency.network, ); - Logging.instance.i("_polling mwebd status: $status"); + Logging.instance.t( + "$walletId ${info.name} _polling mwebd status: $status", + ); if (status == null) { throw Exception( @@ -115,22 +121,6 @@ mixin MwebInterface syncStatus = WalletSyncStatus.syncing; } else { - final walletMwebScanHeight = - info.otherData[WalletInfoKeys.mwebScanHeight] as int? ?? - info.restoreHeight; - - if (status.mwebUtxosHeight > walletMwebScanHeight) { - // TODO: check utxos and transactions? - - // then - await info.updateOtherData( - newEntries: { - WalletInfoKeys.mwebScanHeight: status.mwebUtxosHeight, - }, - isar: mainDB.isar, - ); - } - syncStatus = WalletSyncStatus.synced; } @@ -152,21 +142,29 @@ mixin MwebInterface }); } + Future _stopUpdateMwebUtxos() async => + await _mwebUtxoSubscription?.cancel(); Future _startUpdateMwebUtxos() async { + await _stopUpdateMwebUtxos(); + final client = await _client; Logging.instance.i("info.restoreHeight: ${info.restoreHeight}"); - final fromHeight = info.restoreHeight; + Logging.instance.i( + "info.otherData[WalletInfoKeys.mwebScanHeight]: ${info.otherData[WalletInfoKeys.mwebScanHeight]}", + ); + final fromHeight = + info.otherData[WalletInfoKeys.mwebScanHeight] as int? ?? + info.restoreHeight; final request = UtxosRequest( fromHeight: fromHeight, scanSecret: await _scanSecret, ); - await _mwebUtxoSubscription?.cancel(); final db = Drift.get(walletId); _mwebUtxoSubscription = (await client.utxos(request)).listen((utxo) async { - Logging.instance.i( + Logging.instance.t( "Found UTXO in stream: Utxo(" "height: ${utxo.height}, " "value: ${utxo.value}, " @@ -198,6 +196,50 @@ mixin MwebInterface ), ); }); + + // TODO get real txid one day + final fakeTxid = "mweb_outputId_${utxo.outputId}"; + + final tx = TransactionV2( + walletId: walletId, + blockHash: null, // ?? + hash: "", + txid: fakeTxid, + timestamp: utxo.blockTime, + height: utxo.height, + inputs: [], + outputs: [ + OutputV2.isarCantDoRequiredInDefaultConstructor( + scriptPubKeyHex: "", + valueStringSats: utxo.value.toString(), + addresses: [utxo.address], + walletOwns: true, + ), + ], + version: 2, // probably + type: TransactionType.incoming, + subType: TransactionSubType.mweb, + otherData: jsonEncode({ + TxV2OdKeys.overrideFee: + Amount( + rawValue: + BigInt + .zero, // TODO fill in correctly when we have a real txid + fractionDigits: cryptoCurrency.fractionDigits, + ).toJsonString(), + }), + ); + + await mainDB.updateOrPutTransactionV2s([tx]); + + await updateBalance(mwebOnly: true); + + if (utxo.height > fromHeight) { + await info.updateOtherData( + newEntries: {WalletInfoKeys.mwebScanHeight: utxo.height}, + isar: mainDB.isar, + ); + } } catch (e, s) { Logging.instance.f( "Failed to insert/update mweb utxo", @@ -337,19 +379,6 @@ mixin MwebInterface } } - /// Should only be called within the standard wallet [recover] function due to - /// mutex locking. Otherwise behaviour MAY be undefined. - Future recoverMweb() async { - if (!info.isMwebEnabled) { - Logging.instance.e( - "Tried calling recoverMweb with mweb disabled for $walletId ${info.name}", - ); - return; - } - - throw UnimplementedError(); - } - Future anonymizeAllMweb() async { if (!info.isMwebEnabled) { Logging.instance.e( @@ -404,6 +433,7 @@ mixin MwebInterface // =========================================================================== + @mustCallSuper @override Future init() async { if (info.isMwebEnabled) { @@ -426,18 +456,16 @@ mixin MwebInterface } } - // await info.updateReceivingAddress( - // newAddress: address.value, - // isar: mainDB.isar, - // ); - await super.init(); } @override - Future updateBalance() async { - // call to super to update transparent balance - final normalBalanceFuture = super.updateBalance(); + Future updateBalance({bool mwebOnly = false}) async { + Future? normalBalanceFuture; + if (!mwebOnly) { + // call to super to update transparent balance + normalBalanceFuture = super.updateBalance(); + } if (info.isMwebEnabled) { final start = DateTime.now(); @@ -513,8 +541,10 @@ mixin MwebInterface } } - // wait for normalBalanceFuture to complete before returning - await normalBalanceFuture; + if (!mwebOnly) { + // wait for normalBalanceFuture to complete before returning + await normalBalanceFuture; + } } @override @@ -563,6 +593,154 @@ mixin MwebInterface // } } + @override + Future recover({required bool isRescan}) async { + if (isViewOnly) { + await recoverViewOnly(isRescan: isRescan); + return; + } + + final start = DateTime.now(); + final root = await getRootHDNode(); + + final List addresses})>> receiveFutures = + []; + final List addresses})>> changeFutures = + []; + + const receiveChain = 0; + const changeChain = 1; + + const txCountBatchSize = 12; + + try { + await refreshMutex.protect(() async { + if (isRescan) { + // clear cache + await electrumXCachedClient.clearSharedTransactionCache( + cryptoCurrency: info.coin, + ); + // clear blockchain info + await mainDB.deleteWalletBlockchainData(walletId); + + // reset scan/listen height + await info.updateOtherData( + newEntries: {WalletInfoKeys.mwebScanHeight: info.restoreHeight}, + isar: mainDB.isar, + ); + + // reset balance to 0 + await info.updateBalanceSecondary( + newBalance: Balance.zeroFor(currency: cryptoCurrency), + isar: mainDB.isar, + ); + + // clear all mweb utxos + final db = Drift.get(walletId); + await db.transaction(() async => await db.delete(db.mwebUtxos).go()); + + await _stopUpdateMwebUtxos(); + if (info.isMwebEnabled) { + // only restart scanning if mweb enabled + unawaited(_startUpdateMwebUtxos()); + } + } + + // receiving addresses + Logging.instance.i("checking receiving addresses..."); + + final canBatch = await serverCanBatch; + + for (final type in cryptoCurrency.supportedDerivationPathTypes) { + receiveFutures.add( + canBatch + ? checkGapsBatched(txCountBatchSize, root, type, receiveChain) + : checkGapsLinearly(root, type, receiveChain), + ); + } + + // change addresses + Logging.instance.d("checking change addresses..."); + for (final type in cryptoCurrency.supportedDerivationPathTypes) { + changeFutures.add( + canBatch + ? checkGapsBatched(txCountBatchSize, root, type, changeChain) + : checkGapsLinearly(root, type, changeChain), + ); + } + + // io limitations may require running these linearly instead + final futuresResult = await Future.wait([ + Future.wait(receiveFutures), + Future.wait(changeFutures), + ]); + + final receiveResults = futuresResult[0]; + final changeResults = futuresResult[1]; + + final List
      addressesToStore = []; + + int highestReceivingIndexWithHistory = 0; + + for (final tuple in receiveResults) { + if (tuple.addresses.isEmpty) { + if (info.otherData[WalletInfoKeys.reuseAddress] != true) { + await checkReceivingAddressForTransactions(); + } + } else { + highestReceivingIndexWithHistory = math.max( + tuple.index, + highestReceivingIndexWithHistory, + ); + addressesToStore.addAll(tuple.addresses); + } + } + + int highestChangeIndexWithHistory = 0; + // If restoring a wallet that never sent any funds with change, then set changeArray + // manually. If we didn't do this, it'd store an empty array. + for (final tuple in changeResults) { + if (tuple.addresses.isEmpty) { + await checkChangeAddressForTransactions(); + } else { + highestChangeIndexWithHistory = math.max( + tuple.index, + highestChangeIndexWithHistory, + ); + addressesToStore.addAll(tuple.addresses); + } + } + + // remove extra addresses to help minimize risk of creating a large gap + addressesToStore.removeWhere( + (e) => + e.subType == AddressSubType.change && + e.derivationIndex > highestChangeIndexWithHistory, + ); + addressesToStore.removeWhere( + (e) => + e.subType == AddressSubType.receiving && + e.derivationIndex > highestReceivingIndexWithHistory, + ); + + await mainDB.updateOrPutAddresses(addressesToStore); + }); + + unawaited(refresh()); + Logging.instance.i( + "Mweb recover for " + "${info.name}: ${DateTime.now().difference(start)}", + ); + } catch (e, s) { + Logging.instance.e( + "Exception rethrown from mweb_interface recover(): ", + error: e, + stackTrace: s, + ); + rethrow; + } + } + @override Future exit() async { _mwebdPolling?.cancel(); From 7e1743610199f6ee81256bfb03492f7adc7b2059 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 19 Jun 2025 08:48:32 -0600 Subject: [PATCH 132/206] mwebd service clean up --- .../more_features/more_features_dialog.dart | 17 ++++++--- .../global/mweb_service_provider.dart | 7 ++++ lib/providers/providers.dart | 1 + .../global/mweb_status_changed_event.dart | 24 ------------- lib/services/mwebd_service.dart | 35 ++++++------------- 5 files changed, 30 insertions(+), 54 deletions(-) create mode 100644 lib/providers/global/mweb_service_provider.dart delete mode 100644 lib/services/event_bus/events/global/mweb_status_changed_event.dart diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 80f55b664..3df3c9504 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -16,8 +16,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import '../../../../../db/sqlite/firo_cache.dart'; -import '../../../../../providers/db/main_db_provider.dart'; -import '../../../../../providers/global/wallets_provider.dart'; +import '../../../../../providers/providers.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../themes/theme_providers.dart'; import '../../../../../utilities/assets.dart'; @@ -267,16 +266,24 @@ class _MoreFeaturesDialogState extends ConsumerState { } } - Future _updateMwebToggle(bool shouldReuse) async { + Future _updateMwebToggle(bool value) async { + if (value) { + unawaited( + ref + .read(pMwebService) + .init(ref.read(pWalletCoin(widget.walletId)).network), + ); + } + await ref .read(pWalletInfo(widget.walletId)) .updateOtherData( - newEntries: {WalletInfoKeys.mwebEnabled: shouldReuse}, + newEntries: {WalletInfoKeys.mwebEnabled: value}, isar: ref.read(mainDBProvider).isar, ); if (_switchControllerMwebToggle.isOn != null) { - if (_switchControllerMwebToggle.isOn!.call() != shouldReuse) { + if (_switchControllerMwebToggle.isOn!.call() != value) { _switchControllerMwebToggle.activate?.call(); } } diff --git a/lib/providers/global/mweb_service_provider.dart b/lib/providers/global/mweb_service_provider.dart new file mode 100644 index 000000000..1cddcb407 --- /dev/null +++ b/lib/providers/global/mweb_service_provider.dart @@ -0,0 +1,7 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../services/mwebd_service.dart'; + +final pMwebService = StateProvider( + (ref) => MwebdService.instance, +); diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart index 3db18af2f..d86e4de3b 100644 --- a/lib/providers/providers.dart +++ b/lib/providers/providers.dart @@ -23,6 +23,7 @@ export './global/barcode_scanner_provider.dart'; export './global/clipboard_provider.dart'; export './global/duress_provider.dart'; export './global/locale_provider.dart'; +export './global/mweb_service_provider.dart'; export './global/node_service_provider.dart'; export './global/notifications_provider.dart'; export './global/prefs_provider.dart'; diff --git a/lib/services/event_bus/events/global/mweb_status_changed_event.dart b/lib/services/event_bus/events/global/mweb_status_changed_event.dart deleted file mode 100644 index 70dd4f3d6..000000000 --- a/lib/services/event_bus/events/global/mweb_status_changed_event.dart +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import '../../../../utilities/logger.dart'; - -enum MwebStatus { enabled, disabled } - -class MwebPreferenceChangedEvent { - String? message; - MwebStatus status; - - MwebPreferenceChangedEvent({required this.status, this.message}) { - Logging.instance.w( - "MwebPreferenceChangedEvent changed to \"$status\" with message: $message", - ); - } -} diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index 00ace0d24..d912f8ff0 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -10,13 +10,19 @@ import '../utilities/logger.dart'; import '../utilities/prefs.dart'; import '../utilities/stack_file_system.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; -import 'event_bus/events/global/mweb_status_changed_event.dart'; import 'event_bus/events/global/tor_connection_status_changed_event.dart'; import 'event_bus/events/global/tor_status_changed_event.dart'; import 'event_bus/global_event_bus.dart'; import 'tor_service.dart'; final class MwebdService { + static String defaultPeer(CryptoCurrencyNetwork net) => switch (net) { + CryptoCurrencyNetwork.main => "litecoin.stackwallet.com:9333", + CryptoCurrencyNetwork.test => "litecoin.stackwallet.com:19335", + CryptoCurrencyNetwork.stage => throw UnimplementedError(), + CryptoCurrencyNetwork.test4 => throw UnimplementedError(), + }; + final Map _map = {}; @@ -24,8 +30,6 @@ final class MwebdService { _torStatusListener; late final StreamSubscription _torPreferenceListener; - late final StreamSubscription - _mwebPreferenceListener; final Mutex _torConnectingLock = Mutex(); @@ -67,27 +71,6 @@ final class MwebdService { return await _update(null); } }); - - // Listen for mweb preference changes. - _mwebPreferenceListener = bus.on().listen(( - event, - ) async { - switch (event.status) { - case MwebStatus.enabled: - // as we don't know which network(s) to use here - // we will rely on status checks and init as required within wallets - break; - - case MwebStatus.disabled: - final nets = _map.keys; - for (final net in nets) { - final old = _map.remove(net)!; - await old.client.cleanup(); - await old.server.stopServer(); - } - break; - } - }); } // locked while mweb servers and clients are updating @@ -133,6 +116,8 @@ final class MwebdService { } Future init(CryptoCurrencyNetwork net) async { + if (net == CryptoCurrencyNetwork.test) return; + Logging.instance.i("MwebdService init($net) called..."); await _updateLock.protect(() async { if (_map[net] != null) { @@ -166,7 +151,7 @@ final class MwebdService { final newServer = MwebdServer( chain: chain, dataDir: dir.path, - peer: "", + peer: defaultPeer(net), proxy: proxy, serverPort: port, ); From 6824774921391edd3a73901ae1ec0660fc30162a Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 19 Jun 2025 08:54:04 -0600 Subject: [PATCH 133/206] refactor firo balance type to general pub/priv balance type for use with mweb as well as firo --- .../send_view/confirm_transaction_view.dart | 8 +-- .../send_view/frost_ms/frost_send_view.dart | 2 +- lib/pages/send_view/send_view.dart | 45 +++++++------- ...dart => dual_balance_selection_sheet.dart} | 24 +++---- .../transaction_fee_selection_sheet.dart | 12 ++-- .../wallet_balance_toggle_sheet.dart | 62 ++++++++++--------- .../sub_widgets/wallet_summary_info.dart | 8 +-- .../desktop_balance_toggle_button.dart | 6 +- .../wallet_view/sub_widgets/desktop_send.dart | 54 +++++++++------- .../sub_widgets/desktop_send_fee_form.dart | 6 +- .../sub_widgets/desktop_wallet_summary.dart | 4 +- .../firo_desktop_wallet_summary.dart | 10 +-- .../ui/preview_tx_button_state_provider.dart | 4 +- ...public_private_balance_state_provider.dart | 6 +- lib/widgets/desktop/desktop_fee_dialog.dart | 12 ++-- 15 files changed, 137 insertions(+), 126 deletions(-) rename lib/pages/send_view/sub_widgets/{firo_balance_selection_sheet.dart => dual_balance_selection_sheet.dart} (92%) diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index d34306cf4..220d0e04f 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -140,7 +140,7 @@ class _ConfirmTransactionViewState } else { if (wallet is FiroWallet) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: if (widget.txData.sparkMints == null) { txDataFuture = wallet.confirmSend(txData: widget.txData); } else { @@ -150,7 +150,7 @@ class _ConfirmTransactionViewState } break; - case FiroType.spark: + case BalanceType.private: txDataFuture = wallet.confirmSendSpark(txData: widget.txData); break; } @@ -346,7 +346,7 @@ class _ConfirmTransactionViewState if (wallet is FiroWallet) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: if (widget.txData.sparkMints != null) { fee = widget.txData.sparkMints! .map((e) => e.fee!) @@ -360,7 +360,7 @@ class _ConfirmTransactionViewState } break; - case FiroType.spark: + case BalanceType.private: fee = widget.txData.fee; amountWithoutChange = (widget.txData.amountWithoutChange ?? diff --git a/lib/pages/send_view/frost_ms/frost_send_view.dart b/lib/pages/send_view/frost_ms/frost_send_view.dart index 22c290036..729bf7c69 100644 --- a/lib/pages/send_view/frost_ms/frost_send_view.dart +++ b/lib/pages/send_view/frost_ms/frost_send_view.dart @@ -230,7 +230,7 @@ class _FrostSendViewState extends ConsumerState { ), ) && (coin is Firo - ? ref.watch(publicPrivateBalanceStateProvider) == FiroType.public + ? ref.watch(publicPrivateBalanceStateProvider) == BalanceType.public : true); return ConditionalParent( diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 3fca255c7..be21c99d6 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -73,7 +73,7 @@ import '../address_book_views/address_book_view.dart'; import '../coin_control/coin_control_view.dart'; import 'confirm_transaction_view.dart'; import 'sub_widgets/building_transaction_dialog.dart'; -import 'sub_widgets/firo_balance_selection_sheet.dart'; +import 'sub_widgets/dual_balance_selection_sheet.dart'; import 'sub_widgets/transaction_fee_selection_sheet.dart'; class SendView extends ConsumerStatefulWidget { @@ -479,7 +479,8 @@ class _SendViewState extends ConsumerState { ref.read(pIsExchangeAddress.state).state = (coin as Firo) .isExchangeAddress(address ?? ""); - if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && + if (ref.read(publicPrivateBalanceStateProvider) == + BalanceType.private && ref.read(pIsExchangeAddress) && !_isFiroExWarningDisplayed) { _isFiroExWarningDisplayed = true; @@ -508,12 +509,12 @@ class _SendViewState extends ConsumerState { if (isFiro) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: if (cachedFiroPublicFees[amount] != null) { return cachedFiroPublicFees[amount]!; } break; - case FiroType.spark: + case BalanceType.private: if (cachedFiroSparkFees[amount] != null) { return cachedFiroSparkFees[amount]!; } @@ -572,14 +573,14 @@ class _SendViewState extends ConsumerState { final firoWallet = wallet as FiroWallet; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: fee = await firoWallet.estimateFeeFor(amount, feeRate); cachedFiroPublicFees[amount] = ref .read(pAmountFormatter(coin)) .format(fee, withUnitName: true, indicatePrecisionLoss: false); return cachedFiroPublicFees[amount]!; - case FiroType.spark: + case BalanceType.private: fee = await firoWallet.estimateFeeForSpark(amount); cachedFiroSparkFees[amount] = ref .read(pAmountFormatter(coin)) @@ -606,10 +607,10 @@ class _SendViewState extends ConsumerState { final Amount availableBalance; if (isFiro) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: availableBalance = wallet.info.cachedBalance.spendable; break; - case FiroType.spark: + case BalanceType.private: availableBalance = wallet.info.cachedBalanceTertiary.spendable; break; } @@ -691,7 +692,7 @@ class _SendViewState extends ConsumerState { isSpark: wallet is FiroWallet && ref.read(publicPrivateBalanceStateProvider.state).state == - FiroType.spark, + BalanceType.private, onCancel: () { wasCancelled = true; @@ -731,7 +732,7 @@ class _SendViewState extends ConsumerState { ); } else if (wallet is FiroWallet) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: if (ref.read(pValidSparkSendToAddress)) { txDataFuture = wallet.prepareSparkMintTransaction( txData: TxData( @@ -768,7 +769,7 @@ class _SendViewState extends ConsumerState { } break; - case FiroType.spark: + case BalanceType.private: txDataFuture = wallet.prepareSendSpark( txData: TxData( recipients: @@ -925,11 +926,11 @@ class _SendViewState extends ConsumerState { amount = _selectedUtxosAmount(selectedUTXOs); } else if (isFiro) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: amount = ref.read(pWalletBalance(walletId)).spendable; break; - case FiroType.spark: + case BalanceType.private: amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; break; } @@ -1159,7 +1160,7 @@ class _SendViewState extends ConsumerState { ), ) && (coin is Firo - ? ref.watch(publicPrivateBalanceStateProvider) == FiroType.public + ? ref.watch(publicPrivateBalanceStateProvider) == BalanceType.public : true); if (isFiro) { @@ -1181,7 +1182,7 @@ class _SendViewState extends ConsumerState { } if (previous != next && - next == FiroType.spark && + next == BalanceType.private && isExchangeAddress && !_isFiroExWarningDisplayed) { _isFiroExWarningDisplayed = true; @@ -1321,7 +1322,7 @@ class _SendViewState extends ConsumerState { .state, ) .state) { - case FiroType.public: + case BalanceType.public: amount = ref .read( @@ -1332,7 +1333,7 @@ class _SendViewState extends ConsumerState { .spendable; break; - case FiroType.spark: + case BalanceType.private: amount = ref .read( @@ -1761,7 +1762,7 @@ class _SendViewState extends ConsumerState { ), ), builder: - (_) => FiroBalanceSelectionSheet( + (_) => DualBalanceSelectionSheet( walletId: walletId, ), ); @@ -1789,7 +1790,7 @@ class _SendViewState extends ConsumerState { .state, ) .state) { - case FiroType.public: + case BalanceType.public: amount = ref .watch( @@ -1799,7 +1800,7 @@ class _SendViewState extends ConsumerState { ) .spendable; break; - case FiroType.spark: + case BalanceType.private: amount = ref .watch( @@ -2229,7 +2230,7 @@ class _SendViewState extends ConsumerState { .state, ) .state != - FiroType.public + BalanceType.public ? null : _onFeeSelectPressed, child: @@ -2240,7 +2241,7 @@ class _SendViewState extends ConsumerState { .state, ) .state != - FiroType.public) + BalanceType.public) ? Row( children: [ FutureBuilder( diff --git a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart b/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart similarity index 92% rename from lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart rename to lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart index 87c6da542..c8006b713 100644 --- a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart @@ -19,18 +19,18 @@ import '../../../utilities/constants.dart'; import '../../../utilities/text_styles.dart'; import '../../../wallets/wallet/impl/firo_wallet.dart'; -class FiroBalanceSelectionSheet extends ConsumerStatefulWidget { - const FiroBalanceSelectionSheet({super.key, required this.walletId}); +class DualBalanceSelectionSheet extends ConsumerStatefulWidget { + const DualBalanceSelectionSheet({super.key, required this.walletId}); final String walletId; @override - ConsumerState createState() => + ConsumerState createState() => _FiroBalanceSelectionSheetState(); } class _FiroBalanceSelectionSheetState - extends ConsumerState { + extends ConsumerState { late final String walletId; @override @@ -90,9 +90,9 @@ class _FiroBalanceSelectionSheetState onTap: () { final state = ref.read(publicPrivateBalanceStateProvider.state).state; - if (state != FiroType.spark) { + if (state != BalanceType.private) { ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; } Navigator.of(context).pop(); }, @@ -112,7 +112,7 @@ class _FiroBalanceSelectionSheetState Theme.of(context) .extension()! .radioButtonIconEnabled, - value: FiroType.spark, + value: BalanceType.private, groupValue: ref .watch( @@ -125,7 +125,7 @@ class _FiroBalanceSelectionSheetState .read( publicPrivateBalanceStateProvider.state, ) - .state = FiroType.spark; + .state = BalanceType.private; Navigator.of(context).pop(); }, @@ -173,9 +173,9 @@ class _FiroBalanceSelectionSheetState onTap: () { final state = ref.read(publicPrivateBalanceStateProvider.state).state; - if (state != FiroType.public) { + if (state != BalanceType.public) { ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; } Navigator.of(context).pop(); }, @@ -194,7 +194,7 @@ class _FiroBalanceSelectionSheetState Theme.of(context) .extension()! .radioButtonIconEnabled, - value: FiroType.public, + value: BalanceType.public, groupValue: ref .watch( @@ -207,7 +207,7 @@ class _FiroBalanceSelectionSheetState .read( publicPrivateBalanceStateProvider.state, ) - .state = FiroType.public; + .state = BalanceType.public; Navigator.of(context).pop(); }, ), diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index 2257af491..3ec7048a3 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -97,11 +97,11 @@ class _TransactionFeeSelectionSheetState } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, @@ -134,11 +134,11 @@ class _TransactionFeeSelectionSheetState } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, @@ -170,11 +170,11 @@ class _TransactionFeeSelectionSheetState } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, diff --git a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart index bbe90033e..120b99b25 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart @@ -23,7 +23,7 @@ import '../../../utilities/text_styles.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; -enum _BalanceType { available, full, sparkAvailable, sparkFull } +enum _BalanceType { available, full, privateAvailable, privateFull } class WalletBalanceToggleSheet extends ConsumerWidget { const WalletBalanceToggleSheet({super.key, required this.walletId}); @@ -35,7 +35,10 @@ class WalletBalanceToggleSheet extends ConsumerWidget { final maxHeight = MediaQuery.of(context).size.height * 0.90; final coin = ref.watch(pWalletCoin(walletId)); - final isFiro = coin is Firo; + final isMweb = ref.watch( + pWalletInfo(walletId).select((s) => s.isMwebEnabled), + ); + final hasPrivate = isMweb || coin is Firo; final balance = ref.watch(pWalletBalance(walletId)); @@ -45,16 +48,19 @@ class WalletBalanceToggleSheet extends ConsumerWidget { ? _BalanceType.available : _BalanceType.full; - Balance? balanceTertiary; - if (isFiro) { - balanceTertiary = ref.watch(pWalletBalanceTertiary(walletId)); + Balance? balancePrivate; + if (hasPrivate) { + balancePrivate = + isMweb + ? ref.watch(pWalletBalanceSecondary(walletId)) + : ref.watch(pWalletBalanceTertiary(walletId)); if (ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.spark) { + BalanceType.private) { _bal = _bal == _BalanceType.available - ? _BalanceType.sparkAvailable - : _BalanceType.sparkFull; + ? _BalanceType.privateAvailable + : _BalanceType.privateFull; } } @@ -102,21 +108,21 @@ class WalletBalanceToggleSheet extends ConsumerWidget { ), const SizedBox(height: 24), BalanceSelector( - title: "Available${isFiro ? " public" : ""} balance", + title: "Available${hasPrivate ? " public" : ""} balance", coin: coin, balance: balance.spendable, onPressed: () { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.available; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; Navigator.of(context).pop(); }, onChanged: (_) { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.available; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; Navigator.of(context).pop(); }, value: _BalanceType.available, @@ -124,70 +130,70 @@ class WalletBalanceToggleSheet extends ConsumerWidget { ), const SizedBox(height: 12), BalanceSelector( - title: "Full${isFiro ? " public" : ""} balance", + title: "Full${hasPrivate ? " public" : ""} balance", coin: coin, balance: balance.total, onPressed: () { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.full; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; Navigator.of(context).pop(); }, onChanged: (_) { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.full; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; Navigator.of(context).pop(); }, value: _BalanceType.full, groupValue: _bal, ), - if (balanceTertiary != null) const SizedBox(height: 12), - if (balanceTertiary != null) + if (balancePrivate != null) const SizedBox(height: 12), + if (balancePrivate != null) BalanceSelector( - title: "Available Spark balance", + title: "Available Private balance", coin: coin, - balance: balanceTertiary.spendable, + balance: balancePrivate.spendable, onPressed: () { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.available; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; Navigator.of(context).pop(); }, onChanged: (_) { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.available; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; Navigator.of(context).pop(); }, - value: _BalanceType.sparkAvailable, + value: _BalanceType.privateAvailable, groupValue: _bal, ), - if (balanceTertiary != null) const SizedBox(height: 12), - if (balanceTertiary != null) + if (balancePrivate != null) const SizedBox(height: 12), + if (balancePrivate != null) BalanceSelector( - title: "Full Spark balance", + title: "Full Private balance", coin: coin, - balance: balanceTertiary.total, + balance: balancePrivate.total, onPressed: () { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.full; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; Navigator.of(context).pop(); }, onChanged: (_) { ref.read(walletBalanceToggleStateProvider.state).state = WalletBalanceToggleState.full; ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; Navigator.of(context).pop(); }, - value: _BalanceType.sparkFull, + value: _BalanceType.privateFull, groupValue: _bal, ), const SizedBox(height: 40), diff --git a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart index 7661bffdd..3b8e255e8 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart @@ -85,10 +85,6 @@ class WalletSummaryInfo extends ConsumerWidget { ); } - final priceTuple = ref.watch( - priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin)), - ); - final _showAvailable = ref.watch(walletBalanceToggleStateProvider) == WalletBalanceToggleState.available; @@ -104,12 +100,12 @@ class WalletSummaryInfo extends ConsumerWidget { title = "${_showAvailable ? "Available" : "Full"} ${type.name.capitalize()} balance"; switch (type) { - case FiroType.spark: + case BalanceType.private: final balance = ref.watch(pWalletBalanceTertiary(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; break; - case FiroType.public: + case BalanceType.public: final balance = ref.watch(pWalletBalance(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; break; diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart index 73a6bd742..f2c5429db 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart @@ -89,12 +89,12 @@ class DesktopPrivateBalanceToggleButton extends ConsumerWidget { color: Theme.of(context).extension()!.buttonBackSecondary, splashColor: Theme.of(context).extension()!.highlight, onPressed: () { - if (currentType != FiroType.spark) { + if (currentType != BalanceType.private) { ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.spark; + BalanceType.private; } else { ref.read(publicPrivateBalanceStateProvider.state).state = - FiroType.public; + BalanceType.public; } onPressed?.call(); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 206e7ce6d..bf07ef580 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -165,11 +165,14 @@ class _DesktopSendState extends ConsumerState { final Amount availableBalance; if ((coin is Firo)) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: availableBalance = wallet.info.cachedBalance.spendable; break; - case FiroType.spark: - availableBalance = wallet.info.cachedBalanceTertiary.spendable; + case BalanceType.private: + availableBalance = + coin is Firo + ? wallet.info.cachedBalanceTertiary.spendable + : wallet.info.cachedBalanceSecondary.spendable; break; } } else { @@ -280,7 +283,7 @@ class _DesktopSendState extends ConsumerState { ref .read(publicPrivateBalanceStateProvider.state) .state == - FiroType.spark, + BalanceType.private, onCancel: () { wasCancelled = true; @@ -325,7 +328,7 @@ class _DesktopSendState extends ConsumerState { ); } else if (wallet is FiroWallet) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: if (ref.read(pValidSparkSendToAddress)) { txDataFuture = wallet.prepareSparkMintTransaction( txData: TxData( @@ -364,7 +367,7 @@ class _DesktopSendState extends ConsumerState { } break; - case FiroType.spark: + case BalanceType.private: txDataFuture = wallet.prepareSendSpark( txData: TxData( recipients: @@ -624,7 +627,8 @@ class _DesktopSendState extends ConsumerState { ref.read(pIsExchangeAddress.state).state = (coin as Firo) .isExchangeAddress(address ?? ""); - if (ref.read(publicPrivateBalanceStateProvider) == FiroType.spark && + if (ref.read(publicPrivateBalanceStateProvider) == + BalanceType.private && ref.read(pIsExchangeAddress) && !_isFiroExWarningDisplayed) { _isFiroExWarningDisplayed = true; @@ -833,10 +837,10 @@ class _DesktopSendState extends ConsumerState { amount = _selectedUtxosAmount(ref.read(desktopUseUTXOs)); } else if (coin is Firo) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.public: + case BalanceType.public: amount = ref.read(pWalletBalance(walletId)).spendable; break; - case FiroType.spark: + case BalanceType.private: amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; break; } @@ -969,12 +973,12 @@ class _DesktopSendState extends ConsumerState { }); } - final firoType = ref.watch(publicPrivateBalanceStateProvider); + final balType = ref.watch(publicPrivateBalanceStateProvider); final isExchangeAddress = ref.watch(pIsExchangeAddress); ref.listen(publicPrivateBalanceStateProvider, (previous, next) { if (previous != next && - next == FiroType.spark && + next == BalanceType.private && isExchangeAddress && !_isFiroExWarningDisplayed) { _isFiroExWarningDisplayed = true; @@ -994,13 +998,13 @@ class _DesktopSendState extends ConsumerState { ), ) && ref.watch(pWallets).getWallet(walletId) is CoinControlInterface && - (coin is Firo ? firoType == FiroType.public : true); + (coin is Firo ? balType == BalanceType.public : true); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), - if (coin is Firo) + if (showPrivateBalance) Text( "Send from", style: STextStyles.desktopTextExtraSmall(context).copyWith( @@ -1011,19 +1015,19 @@ class _DesktopSendState extends ConsumerState { ), textAlign: TextAlign.left, ), - if (coin is Firo) const SizedBox(height: 10), - if (coin is Firo) + if (showPrivateBalance) const SizedBox(height: 10), + if (showPrivateBalance) DropdownButtonHideUnderline( child: DropdownButton2( isExpanded: true, - value: firoType, + value: balType, items: [ DropdownMenuItem( - value: FiroType.spark, + value: BalanceType.private, child: Row( children: [ Text( - "Spark balance", + "Private balance", style: STextStyles.itemSubtitle12(context), ), const SizedBox(width: 10), @@ -1032,7 +1036,11 @@ class _DesktopSendState extends ConsumerState { .watch(pAmountFormatter(coin)) .format( ref - .watch(pWalletBalanceTertiary(walletId)) + .watch( + isMwebEnabled + ? pWalletBalanceSecondary(walletId) + : pWalletBalanceTertiary(walletId), + ) .spendable, ), style: STextStyles.itemSubtitle(context), @@ -1041,7 +1049,7 @@ class _DesktopSendState extends ConsumerState { ), ), DropdownMenuItem( - value: FiroType.public, + value: BalanceType.public, child: Row( children: [ Text( @@ -1062,8 +1070,8 @@ class _DesktopSendState extends ConsumerState { ), ], onChanged: (value) { - if (value is FiroType) { - if (value != FiroType.public) { + if (value is BalanceType) { + if (value != BalanceType.public) { ref.read(desktopUseUTXOs.state).state = {}; } setState(() { @@ -1098,7 +1106,7 @@ class _DesktopSendState extends ConsumerState { ), ), ), - if (coin is Firo) const SizedBox(height: 20), + if (showPrivateBalance) const SizedBox(height: 20), if (isPaynymSend) Text( "Send to PayNym address", diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 1eb046484..6b08923ab 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -71,7 +71,7 @@ class _DesktopSendFeeFormState extends ConsumerState { (cryptoCurrency is ElectrumXCurrencyInterface && !(((cryptoCurrency is Firo) && (ref.watch(publicPrivateBalanceStateProvider.state).state == - FiroType.spark)))); + BalanceType.private)))); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -183,7 +183,7 @@ class _DesktopSendFeeFormState extends ConsumerState { .state, ) .state != - FiroType.public) { + BalanceType.public) { final firoWallet = wallet as FiroWallet; if (ref @@ -192,7 +192,7 @@ class _DesktopSendFeeFormState extends ConsumerState { .state, ) .state == - FiroType.spark) { + BalanceType.private) { ref .read(feeSheetSessionCacheProvider) .average[amount] = await firoWallet diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart index 84c52c870..c6ad2694d 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart @@ -104,12 +104,12 @@ class _WDesktopWalletSummaryState extends ConsumerState { final Amount balanceToShow; if (isFiro) { switch (ref.watch(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: final balance = ref.watch(pWalletBalanceTertiary(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; break; - case FiroType.public: + case BalanceType.public: final balance = ref.watch(pWalletBalance(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; break; diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart index 2de6daf39..650f67f68 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/firo_desktop_wallet_summary.dart @@ -104,7 +104,7 @@ class _WFiroDesktopWalletSummaryState children: [ TableRow( children: [ - const _Prefix(type: FiroType.spark), + const _Prefix(type: BalanceType.private), _Balance(coin: coin, amount: balanceToShowSpark), if (price != null) _Price( @@ -117,7 +117,7 @@ class _WFiroDesktopWalletSummaryState TableRow( children: [ - const _Prefix(type: FiroType.public), + const _Prefix(type: BalanceType.public), _Balance(coin: coin, amount: balanceToShowPublic), if (price != null) _Price( @@ -147,13 +147,13 @@ class _WFiroDesktopWalletSummaryState class _Prefix extends StatelessWidget { const _Prefix({super.key, required this.type}); - final FiroType type; + final BalanceType type; String get asset { switch (type) { - case FiroType.public: + case BalanceType.public: return Assets.png.glasses; - case FiroType.spark: + case BalanceType.private: return Assets.svg.spark; } } diff --git a/lib/providers/ui/preview_tx_button_state_provider.dart b/lib/providers/ui/preview_tx_button_state_provider.dart index 35daf888f..9ff71aca7 100644 --- a/lib/providers/ui/preview_tx_button_state_provider.dart +++ b/lib/providers/ui/preview_tx_button_state_provider.dart @@ -27,13 +27,13 @@ final pPreviewTxButtonEnabled = Provider.autoDispose if (coin is Firo) { final firoType = ref.watch(publicPrivateBalanceStateProvider); switch (firoType) { - case FiroType.spark: + case BalanceType.private: return (ref.watch(pValidSendToAddress) || ref.watch(pValidSparkSendToAddress)) && !ref.watch(pIsExchangeAddress) && amount > Amount.zero; - case FiroType.public: + case BalanceType.public: return ref.watch(pValidSendToAddress) && amount > Amount.zero; } } else { diff --git a/lib/providers/wallet/public_private_balance_state_provider.dart b/lib/providers/wallet/public_private_balance_state_provider.dart index 7484db9f0..39ce0ae88 100644 --- a/lib/providers/wallet/public_private_balance_state_provider.dart +++ b/lib/providers/wallet/public_private_balance_state_provider.dart @@ -10,8 +10,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -enum FiroType { public, spark } +enum BalanceType { public, private } -final publicPrivateBalanceStateProvider = StateProvider( - (_) => FiroType.spark, +final publicPrivateBalanceStateProvider = StateProvider( + (_) => BalanceType.private, ); diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart index 3252be98e..82cc82e0b 100644 --- a/lib/widgets/desktop/desktop_fee_dialog.dart +++ b/lib/widgets/desktop/desktop_fee_dialog.dart @@ -69,11 +69,11 @@ class _DesktopFeeDialogState extends ConsumerState { } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, @@ -119,11 +119,11 @@ class _DesktopFeeDialogState extends ConsumerState { } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, @@ -169,11 +169,11 @@ class _DesktopFeeDialogState extends ConsumerState { } else if (coin is Firo) { final Amount fee; switch (ref.read(publicPrivateBalanceStateProvider.state).state) { - case FiroType.spark: + case BalanceType.private: fee = await (wallet as FiroWallet).estimateFeeForSpark( amount, ); - case FiroType.public: + case BalanceType.public: fee = await (wallet as FiroWallet).estimateFeeFor( amount, feeRate, From a8fc2f90e3fd8528318417f41be4efbdc51369a8 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 19 Jun 2025 09:41:52 -0600 Subject: [PATCH 134/206] refactor signing data --- lib/models/signing_data.dart | 49 ++++++++++--- lib/wallets/wallet/impl/namecoin_wallet.dart | 15 ++-- lib/wallets/wallet/impl/particl_wallet.dart | 8 +-- .../bcash_interface.dart | 33 +++++---- .../electrumx_interface.dart | 70 +++++++++++-------- .../paynym_interface.dart | 27 +++---- .../spark_interface.dart | 20 +++--- 7 files changed, 135 insertions(+), 87 deletions(-) diff --git a/lib/models/signing_data.dart b/lib/models/signing_data.dart index 265a021db..a6e8036a3 100644 --- a/lib/models/signing_data.dart +++ b/lib/models/signing_data.dart @@ -9,26 +9,53 @@ */ import 'package:coinlib_flutter/coinlib_flutter.dart'; -import 'isar/models/isar_models.dart'; + +import '../db/drift/database.dart'; import '../utilities/enums/derive_path_type_enum.dart'; +import 'isar/models/isar_models.dart'; + +abstract class BaseInput { + BaseInput(this._utxo, {this.key}); + + final Object _utxo; + HDKey? key; + + @override + String toString() { + return "BaseInput{\n" + " _utxo: $_utxo,\n" + " key: $key,\n" + "}"; + } +} -class SigningData { - SigningData({ - required this.derivePathType, - required this.utxo, - this.keyPair, - }); +class StandardInput extends BaseInput { + StandardInput(UTXO super.utxo, {required this.derivePathType, super.key}); final DerivePathType derivePathType; - final UTXO utxo; - HDPrivateKey? keyPair; + + UTXO get utxo => _utxo as UTXO; @override String toString() { - return "SigningData{\n" + return "StandardInput{\n" " derivePathType: $derivePathType,\n" " utxo: $utxo,\n" - " keyPair: $keyPair,\n" + " key: $key,\n" + "}"; + } +} + +class MwebInput extends BaseInput { + MwebInput(MwebUtxo super.utxo); + + MwebUtxo get utxo => _utxo as MwebUtxo; + + @override + String toString() { + return "MwebInput{\n" + " utxo: $utxo,\n" + " key: $key,\n" "}"; } } diff --git a/lib/wallets/wallet/impl/namecoin_wallet.dart b/lib/wallets/wallet/impl/namecoin_wallet.dart index bb3f020f3..a1970b974 100644 --- a/lib/wallets/wallet/impl/namecoin_wallet.dart +++ b/lib/wallets/wallet/impl/namecoin_wallet.dart @@ -627,7 +627,7 @@ class NamecoinWallet /// Builds and signs a transaction Future _createNameTx({ required TxData txData, - required List utxoSigningData, + required List utxoSigningData, required bool isForFeeCalcPurposesOnly, }) async { Logging.instance.d("Starting _createNameTx ----------"); @@ -692,7 +692,7 @@ class NamecoinWallet case DerivePathType.bip44: input = coinlib.P2PKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: utxoSigningData[i].key!.publicKey, sequence: sequence, ); @@ -710,7 +710,7 @@ class NamecoinWallet case DerivePathType.bip84: input = coinlib.P2WPKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: utxoSigningData[i].key!.publicKey, sequence: sequence, ); @@ -810,11 +810,11 @@ class NamecoinWallet // Sign the transaction accordingly for (int i = 0; i < utxoSigningData.length; i++) { final value = BigInt.from(utxoSigningData[i].utxo.value); - final key = utxoSigningData[i].keyPair!.privateKey; + final key = utxoSigningData[i].key!.privateKey!; if (clTx.inputs[i] is coinlib.TaprootKeyInput) { final taproot = coinlib.Taproot( - internalKey: utxoSigningData[i].keyPair!.publicKey, + internalKey: utxoSigningData[i].key!.publicKey, ); clTx = clTx.signTaproot( @@ -1115,7 +1115,10 @@ class NamecoinWallet final List recipientsAmtArray = [satoshiAmountToSend]; // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + final utxoSigningData = + (await fetchBuildTxData( + utxoObjectsToUse, + )).whereType().toList(); final int vSizeForOneOutput; try { diff --git a/lib/wallets/wallet/impl/particl_wallet.dart b/lib/wallets/wallet/impl/particl_wallet.dart index 1188625cb..19a9a9e20 100644 --- a/lib/wallets/wallet/impl/particl_wallet.dart +++ b/lib/wallets/wallet/impl/particl_wallet.dart @@ -352,7 +352,7 @@ class ParticlWallet @override Future buildTransaction({ required TxData txData, - required List utxoSigningData, + required covariant List utxoSigningData, }) async { Logging.instance.d("Starting Particl buildTransaction ----------"); @@ -374,7 +374,7 @@ class ParticlWallet for (int i = 0; i < utxoSigningData.length; i++) { final sd = utxoSigningData[i]; - final pubKey = sd.keyPair!.publicKey.data; + final pubKey = sd.key!.publicKey.data; final bitcoindart.PaymentData? data; Uint8List? redeem, output; @@ -512,9 +512,9 @@ class ParticlWallet txb.sign( vin: i, keyPair: bitcoindart.ECPair.fromPrivateKey( - utxoSigningData[i].keyPair!.privateKey.data, + utxoSigningData[i].key!.privateKey!.data, network: convertedNetwork, - compressed: utxoSigningData[i].keyPair!.privateKey.compressed, + compressed: utxoSigningData[i].key!.privateKey!.compressed, ), witnessValue: utxoSigningData[i].utxo.value, redeemScript: extraData[i].redeem, diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart index 371236180..492f727b0 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart @@ -18,7 +18,7 @@ mixin BCashInterface @override Future buildTransaction({ required TxData txData, - required List utxoSigningData, + required covariant List utxoSigningData, }) async { Logging.instance.d("Starting buildTransaction ----------"); @@ -50,9 +50,10 @@ mixin BCashInterface txid: utxoSigningData[i].utxo.txid, vout: utxoSigningData[i].utxo.vout, ), - addresses: utxoSigningData[i].utxo.address == null - ? [] - : [utxoSigningData[i].utxo.address!], + addresses: + utxoSigningData[i].utxo.address == null + ? [] + : [utxoSigningData[i].utxo.address!], valueStringSats: utxoSigningData[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, @@ -73,10 +74,9 @@ mixin BCashInterface OutputV2.isarCantDoRequiredInDefaultConstructor( scriptPubKeyHex: "000000", valueStringSats: txData.recipients![i].amount.raw.toString(), - addresses: [ - txData.recipients![i].address.toString(), - ], - walletOwns: (await mainDB.isar.addresses + addresses: [txData.recipients![i].address.toString()], + walletOwns: + (await mainDB.isar.addresses .where() .walletIdEqualTo(walletId) .filter() @@ -94,7 +94,7 @@ mixin BCashInterface // Sign the transaction accordingly for (int i = 0; i < utxoSigningData.length; i++) { final bitboxEC = bitbox.ECPair.fromPrivateKey( - utxoSigningData[i].keyPair!.privateKey.data, + utxoSigningData[i].key!.privateKey!.data, network: bitbox_utils.Network( cryptoCurrency.networkParams.privHDPrefix, cryptoCurrency.networkParams.pubHDPrefix, @@ -103,18 +103,17 @@ mixin BCashInterface cryptoCurrency.networkParams.wifPrefix, cryptoCurrency.networkParams.p2pkhPrefix, ), - compressed: utxoSigningData[i].keyPair!.privateKey.compressed, + compressed: utxoSigningData[i].key!.privateKey!.compressed, ); - builder.sign( - i, - bitboxEC, - utxoSigningData[i].utxo.value, - ); + builder.sign(i, bitboxEC, utxoSigningData[i].utxo.value); } } catch (e, s) { - Logging.instance.e("Caught exception while signing transaction: ", - error: e, stackTrace: s); + Logging.instance.e( + "Caught exception while signing transaction: ", + error: e, + stackTrace: s, + ); rethrow; } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index dda6b2876..6a505c60c 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -325,7 +325,11 @@ mixin ElectrumXInterface rawValue: feeForOneOutput, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: utxoSigningData.map((e) => e.utxo).toList(), + usedUTXOs: + utxoSigningData + .whereType() + .map((e) => e.utxo) + .toList(), ); } @@ -418,7 +422,11 @@ mixin ElectrumXInterface rawValue: feeBeingPaid, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: utxoSigningData.map((e) => e.utxo).toList(), + usedUTXOs: + utxoSigningData + .whereType() + .map((e) => e.utxo) + .toList(), ); } else { // Something went wrong here. It either overshot or undershot the estimated fee amount or the changeOutputSize @@ -438,7 +446,7 @@ mixin ElectrumXInterface required String recipientAddress, required BigInt satoshiAmountToSend, required BigInt satoshisBeingUsed, - required List utxoSigningData, + required List utxoSigningData, required int? satsPerVByte, required BigInt feeRatePerKB, }) async { @@ -491,13 +499,17 @@ mixin ElectrumXInterface rawValue: feeForOneOutput, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: utxoSigningData.map((e) => e.utxo).toList(), + usedUTXOs: + utxoSigningData + .whereType() + .map((e) => e.utxo) + .toList(), ); } - Future> fetchBuildTxData(List utxosToUse) async { + Future> fetchBuildTxData(List utxosToUse) async { // return data - final List signingData = []; + final List signingData = []; try { // Populating the addresses to check @@ -507,7 +519,7 @@ mixin ElectrumXInterface ); signingData.add( - SigningData(derivePathType: derivePathType, utxo: utxosToUse[i]), + StandardInput(utxosToUse[i], derivePathType: derivePathType), ); } @@ -552,7 +564,7 @@ mixin ElectrumXInterface ); } - sd.keyPair = keys; + sd.key = keys; } return signingData; @@ -565,7 +577,7 @@ mixin ElectrumXInterface /// Builds and signs a transaction Future buildTransaction({ required TxData txData, - required List utxoSigningData, + required List utxoSigningData, }) async { Logging.instance.d("Starting buildTransaction ----------"); @@ -587,20 +599,22 @@ mixin ElectrumXInterface ? 0xffffffff - 10 : 0xffffffff - 1; + final standardInputs = utxoSigningData.whereType().toList(); + // Add transaction inputs - for (var i = 0; i < utxoSigningData.length; i++) { - final txid = utxoSigningData[i].utxo.txid; + for (var i = 0; i < standardInputs.length; i++) { + final txid = standardInputs[i].utxo.txid; final hash = Uint8List.fromList( txid.toUint8ListFromHex.reversed.toList(), ); - final prevOutpoint = coinlib.OutPoint(hash, utxoSigningData[i].utxo.vout); + final prevOutpoint = coinlib.OutPoint(hash, standardInputs[i].utxo.vout); final prevOutput = coinlib.Output.fromAddress( - BigInt.from(utxoSigningData[i].utxo.value), + BigInt.from(standardInputs[i].utxo.value), coinlib.Address.fromString( - utxoSigningData[i].utxo.address!, + standardInputs[i].utxo.address!, cryptoCurrency.networkParams, ), ); @@ -609,12 +623,12 @@ mixin ElectrumXInterface final coinlib.Input input; - switch (utxoSigningData[i].derivePathType) { + switch (standardInputs[i].derivePathType) { case DerivePathType.bip44: case DerivePathType.bch44: input = coinlib.P2PKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: standardInputs[i].key!.publicKey, sequence: sequence, ); @@ -624,7 +638,7 @@ mixin ElectrumXInterface // input = coinlib.P2SHMultisigInput( // prevOut: prevOutpoint, // program: coinlib.MultisigProgram.decompile( - // utxoSigningData[i].redeemScript!, + // standardInputs[i].redeemScript!, // ), // sequence: sequence, // ); @@ -632,7 +646,7 @@ mixin ElectrumXInterface case DerivePathType.bip84: input = coinlib.P2WPKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: standardInputs[i].key!.publicKey, sequence: sequence, ); @@ -641,7 +655,7 @@ mixin ElectrumXInterface default: throw UnsupportedError( - "Unknown derivation path type found: ${utxoSigningData[i].derivePathType}", + "Unknown derivation path type found: ${standardInputs[i].derivePathType}", ); } @@ -653,14 +667,14 @@ mixin ElectrumXInterface scriptSigAsm: null, sequence: sequence, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: utxoSigningData[i].utxo.txid, - vout: utxoSigningData[i].utxo.vout, + txid: standardInputs[i].utxo.txid, + vout: standardInputs[i].utxo.vout, ), addresses: - utxoSigningData[i].utxo.address == null + standardInputs[i].utxo.address == null ? [] - : [utxoSigningData[i].utxo.address!], - valueStringSats: utxoSigningData[i].utxo.value.toString(), + : [standardInputs[i].utxo.address!], + valueStringSats: standardInputs[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -715,13 +729,13 @@ mixin ElectrumXInterface try { // Sign the transaction accordingly - for (var i = 0; i < utxoSigningData.length; i++) { - final value = BigInt.from(utxoSigningData[i].utxo.value); - final key = utxoSigningData[i].keyPair!.privateKey; + for (var i = 0; i < standardInputs.length; i++) { + final value = BigInt.from(standardInputs[i].utxo.value); + final key = standardInputs[i].key!.privateKey!; if (clTx.inputs[i] is coinlib.TaprootKeyInput) { final taproot = coinlib.Taproot( - internalKey: utxoSigningData[i].keyPair!.publicKey, + internalKey: standardInputs[i].key!.publicKey, ); clTx = clTx.signTaproot( diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart index 1bfb3a2a3..5d38c3d87 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart @@ -526,7 +526,10 @@ mixin PaynymInterface } // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + final utxoSigningData = + (await fetchBuildTxData( + utxoObjectsToUse, + )).whereType().toList(); final vSizeForNoChange = BigInt.from( (await _createNotificationTx( @@ -706,7 +709,7 @@ mixin PaynymInterface // equal to its vSize Future> _createNotificationTx({ required String targetPaymentCodeString, - required List utxoSigningData, + required List utxoSigningData, required BigInt change, BigInt? overrideAmountForTesting, }) async { @@ -726,10 +729,10 @@ mixin PaynymInterface final buffer = rev.buffer.asByteData(); buffer.setUint32(txPoint.length, txPointIndex, Endian.little); - final myKeyPair = utxoSigningData.first.keyPair!; + final myKeyPair = utxoSigningData.first.key!; final S = SecretPoint( - myKeyPair.privateKey.data, + myKeyPair.privateKey!.data, targetPaymentCode.notificationPublicKey(), ); @@ -785,7 +788,7 @@ mixin PaynymInterface case DerivePathType.bch44: input = coinlib.P2PKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: utxoSigningData[i].key!.publicKey, sequence: 0xffffffff - 1, ); @@ -803,7 +806,7 @@ mixin PaynymInterface case DerivePathType.bip84: input = coinlib.P2WPKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].keyPair!.publicKey, + publicKey: utxoSigningData[i].key!.publicKey, sequence: 0xffffffff - 1, ); @@ -860,21 +863,21 @@ mixin PaynymInterface clTx = clTx.signTaproot( inputN: 0, - key: taproot.tweakPrivateKey(myKeyPair.privateKey), + key: taproot.tweakPrivateKey(myKeyPair.privateKey!), prevOuts: prevOuts, ); } else if (clTx.inputs[0] is coinlib.LegacyWitnessInput) { clTx = clTx.signLegacyWitness( inputN: 0, - key: myKeyPair.privateKey, + key: myKeyPair.privateKey!, value: BigInt.from(utxo.value), ); } else if (clTx.inputs[0] is coinlib.LegacyInput) { - clTx = clTx.signLegacy(inputN: 0, key: myKeyPair.privateKey); + clTx = clTx.signLegacy(inputN: 0, key: myKeyPair.privateKey!); } else if (clTx.inputs[0] is coinlib.TaprootSingleScriptSigInput) { clTx = clTx.signTaprootSingleScriptSig( inputN: 0, - key: myKeyPair.privateKey, + key: myKeyPair.privateKey!, prevOuts: prevOuts, ); } else { @@ -886,11 +889,11 @@ mixin PaynymInterface // sign rest of possible inputs for (int i = 1; i < utxoSigningData.length; i++) { final value = BigInt.from(utxoSigningData[i].utxo.value); - final key = utxoSigningData[i].keyPair!.privateKey; + final key = utxoSigningData[i].key!.privateKey!; if (clTx.inputs[i] is coinlib.TaprootKeyInput) { final taproot = coinlib.Taproot( - internalKey: utxoSigningData[i].keyPair!.publicKey, + internalKey: utxoSigningData[i].key!.publicKey, ); clTx = clTx.signTaproot( diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 21bd7a74a..02a257ea8 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -1413,7 +1413,7 @@ mixin SparkInterface ? max(0, currentHeight - random.nextInt(100)) : currentHeight; const txVersion = 1; - final List vin = []; + final List vin = []; final List<(dynamic, int, String?)> vout = []; BigInt nFeeRet = BigInt.zero; @@ -1426,7 +1426,7 @@ mixin SparkInterface } BigInt nValueToSelect, mintedValue; - final List setCoins = []; + final List setCoins = []; bool skipCoin = false; // Start with no fee and loop until there is enough fee @@ -1555,7 +1555,9 @@ mixin SparkInterface BigInt nValueIn = BigInt.zero; for (final utxo in itr) { if (nValueToSelect > nValueIn) { - setCoins.add((await fetchBuildTxData([utxo])).first); + setCoins.add( + (await fetchBuildTxData([utxo])).whereType().first, + ); nValueIn += BigInt.from(utxo.value); } } @@ -1595,7 +1597,7 @@ mixin SparkInterface for (final sd in setCoins) { vin.add(sd); - final pubKey = sd.keyPair!.publicKey.data; + final pubKey = sd.key!.publicKey.data; final btc.PaymentData? data; switch (sd.derivePathType) { @@ -1659,9 +1661,9 @@ mixin SparkInterface dummyTxb.sign( vin: i, keyPair: btc.ECPair.fromPrivateKey( - setCoins[i].keyPair!.privateKey.data, + setCoins[i].key!.privateKey!.data, network: _bitcoinDartNetwork, - compressed: setCoins[i].keyPair!.privateKey.compressed, + compressed: setCoins[i].key!.privateKey!.compressed, ), witnessValue: setCoins[i].utxo.value, @@ -1756,7 +1758,7 @@ mixin SparkInterface txb.setVersion(txVersion); txb.setLockTime(lockTime); for (final input in vin) { - final pubKey = input.keyPair!.publicKey.data; + final pubKey = input.key!.publicKey.data; final btc.PaymentData? data; switch (input.derivePathType) { @@ -1867,9 +1869,9 @@ mixin SparkInterface txb.sign( vin: i, keyPair: btc.ECPair.fromPrivateKey( - vin[i].keyPair!.privateKey.data, + vin[i].key!.privateKey!.data, network: _bitcoinDartNetwork, - compressed: vin[i].keyPair!.privateKey.compressed, + compressed: vin[i].key!.privateKey!.compressed, ), witnessValue: vin[i].utxo.value, From 1054b5a996b07cdabfa137194fbac68e37ebbd9b Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 20 Jun 2025 11:50:40 -0600 Subject: [PATCH 135/206] WIP broken mweb transactions --- lib/models/signing_data.dart | 56 +- .../exchange_step_views/step_4_view.dart | 8 +- lib/pages/exchange_view/send_from_view.dart | 12 +- lib/pages/namecoin_names/buy_domain_view.dart | 320 ++++++----- .../sub_widgets/transfer_option_widget.dart | 2 +- .../sub_widgets/update_option_widget.dart | 2 +- .../addresses/address_details_view.dart | 474 ++++++++-------- .../send_view/frost_ms/frost_send_view.dart | 8 +- .../send_steps/frost_send_step_1b.dart | 83 +-- .../send_steps/frost_send_step_3.dart | 97 ++-- lib/pages/send_view/send_view.dart | 60 ++- lib/pages/send_view/token_send_view.dart | 4 +- .../desktop_coin_control_use_dialog.dart | 505 +++++++++--------- .../wallet_view/sub_widgets/desktop_send.dart | 63 ++- .../sub_widgets/desktop_token_send.dart | 4 +- .../sub_widgets/desktop_wallet_features.dart | 15 +- .../more_features/more_features_dialog.dart | 2 +- lib/services/frost.dart | 217 ++++---- lib/services/mwebd_service.dart | 217 +++++++- .../crypto_currency/coins/litecoin.dart | 2 + lib/wallets/models/tx_data.dart | 13 +- lib/wallets/models/tx_recipient.dart | 5 + .../wallet/impl/bitcoin_frost_wallet.dart | 12 +- lib/wallets/wallet/impl/cardano_wallet.dart | 2 +- lib/wallets/wallet/impl/epiccash_wallet.dart | 5 +- lib/wallets/wallet/impl/litecoin_wallet.dart | 4 +- lib/wallets/wallet/impl/namecoin_wallet.dart | 10 +- lib/wallets/wallet/impl/tezos_wallet.dart | 2 +- lib/wallets/wallet/impl/wownero_wallet.dart | 2 +- lib/wallets/wallet/impl/xelis_wallet.dart | 12 +- .../intermediate/lib_monero_wallet.dart | 36 +- .../intermediate/lib_salvium_wallet.dart | 38 +- lib/wallets/wallet/wallet.dart | 95 ++-- .../electrumx_interface.dart | 411 ++++++++------ .../mweb_interface.dart | 325 +++++++---- .../paynym_interface.dart | 16 +- .../rbf_interface.dart | 91 ++-- .../spark_interface.dart | 32 +- pubspec.lock | 32 +- 39 files changed, 1929 insertions(+), 1365 deletions(-) diff --git a/lib/models/signing_data.dart b/lib/models/signing_data.dart index a6e8036a3..2fcfde38d 100644 --- a/lib/models/signing_data.dart +++ b/lib/models/signing_data.dart @@ -20,6 +20,14 @@ abstract class BaseInput { final Object _utxo; HDKey? key; + String get id; + + String? get address; + + BigInt get value; + + int? get blockTime; + @override String toString() { return "BaseInput{\n" @@ -30,12 +38,24 @@ abstract class BaseInput { } class StandardInput extends BaseInput { - StandardInput(UTXO super.utxo, {required this.derivePathType, super.key}); + StandardInput(UTXO super.utxo, {this.derivePathType, super.key}); - final DerivePathType derivePathType; + final DerivePathType? derivePathType; UTXO get utxo => _utxo as UTXO; + @override + String get id => utxo.txid; + + @override + String? get address => utxo.address; + + @override + BigInt get value => BigInt.from(utxo.value); + + @override + int? get blockTime => utxo.blockTime; + @override String toString() { return "StandardInput{\n" @@ -44,6 +64,18 @@ class StandardInput extends BaseInput { " key: $key,\n" "}"; } + + @override + bool operator ==(Object other) { + return other is StandardInput && + other.utxo.walletId == utxo.walletId && + other.utxo.txid == utxo.txid && + other.utxo.vout == utxo.vout && + other.derivePathType == derivePathType; + } + + @override + int get hashCode => Object.hashAll([utxo.walletId, utxo.txid, utxo.vout]); } class MwebInput extends BaseInput { @@ -51,6 +83,18 @@ class MwebInput extends BaseInput { MwebUtxo get utxo => _utxo as MwebUtxo; + @override + String get id => utxo.outputId; + + @override + String get address => utxo.address; + + @override + BigInt get value => BigInt.from(utxo.value); + + @override + int? get blockTime => utxo.blockTime < 1 ? null : utxo.blockTime; + @override String toString() { return "MwebInput{\n" @@ -58,4 +102,12 @@ class MwebInput extends BaseInput { " key: $key,\n" "}"; } + + @override + bool operator ==(Object other) { + return other is MwebInput && other.utxo == utxo; + } + + @override + int get hashCode => Object.hashAll([utxo.hashCode]); } diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index 72d2ff241..11bc9fe82 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -233,7 +233,9 @@ class _Step4ViewState extends ConsumerState { if (wallet is FiroWallet && !firoPublicSend) { txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: [(address: address, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: address, amount: amount, isChange: false), + ], note: "${model.trade!.payInCurrency.toUpperCase()}/" "${model.trade!.payOutCurrency.toUpperCase()} exchange", @@ -248,7 +250,9 @@ class _Step4ViewState extends ConsumerState { : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [(address: address, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: address, amount: amount, isChange: false), + ], memo: memo, feeRateType: FeeRateType.average, note: diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 8f397e79e..dd98dce23 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -293,7 +293,9 @@ class _SendFromCardState extends ConsumerState { : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [(address: address, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: address, amount: amount, isChange: false), + ], memo: memo, feeRateType: FeeRateType.average, ), @@ -304,14 +306,18 @@ class _SendFromCardState extends ConsumerState { if (shouldSendPublicFiroFunds) { txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [(address: address, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: address, amount: amount, isChange: false), + ], feeRateType: FeeRateType.average, ), ); } else { txDataFuture = firoWallet.prepareSendSpark( txData: TxData( - recipients: [(address: address, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: address, amount: amount, isChange: false), + ], // feeRateType: FeeRateType.average, ), ); diff --git a/lib/pages/namecoin_names/buy_domain_view.dart b/lib/pages/namecoin_names/buy_domain_view.dart index d0dddda3e..6b2695ef5 100644 --- a/lib/pages/namecoin_names/buy_domain_view.dart +++ b/lib/pages/namecoin_names/buy_domain_view.dart @@ -103,7 +103,7 @@ class _BuyDomainWidgetState extends ConsumerState { note: "Reserve ${widget.domainName.substring(2)}.bit", feeRateType: kNameTxDefaultFeeRate, // TODO: make configurable? recipients: [ - ( + TxRecipient( address: myAddress.value, isChange: false, amount: Amount( @@ -123,28 +123,30 @@ class _BuyDomainWidgetState extends ConsumerState { if (_preRegLock) return; _preRegLock = true; try { - final txData = (await showLoading( - whileFuture: _preRegFuture(), - context: context, - message: "Preparing transaction...", - onException: (e) { - throw e; - }, - ))!; + final txData = + (await showLoading( + whileFuture: _preRegFuture(), + context: context, + message: "Preparing transaction...", + onException: (e) { + throw e; + }, + ))!; if (mounted) { if (Util.isDesktop) { await showDialog( context: context, - builder: (context) => SDialog( - child: SizedBox( - width: 580, - child: ConfirmNameTransactionView( - txData: txData, - walletId: widget.walletId, + builder: + (context) => SDialog( + child: SizedBox( + width: 580, + child: ConfirmNameTransactionView( + txData: txData, + walletId: widget.walletId, + ), + ), ), - ), - ), ); } else { await Navigator.of(context).pushNamed( @@ -164,12 +166,13 @@ class _BuyDomainWidgetState extends ConsumerState { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Error", - message: err, - desktopPopRootNavigator: Util.isDesktop, - maxWidth: Util.isDesktop ? 600 : null, - ), + builder: + (_) => StackOkDialog( + title: "Error", + message: err, + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), ); } } finally { @@ -192,50 +195,48 @@ class _BuyDomainWidgetState extends ConsumerState { builder: (context) { return Util.isDesktop ? SDialog( - child: SizedBox( - width: 580, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Add DNS record", - style: STextStyles.desktopH3(context), - ), - ), - DesktopDialogCloseButton( - onPressedOverride: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(); - }, + child: SizedBox( + width: 580, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Add DNS record", + style: STextStyles.desktopH3(context), ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, ), - child: AddDnsStep1( - name: _getNameFormattedForInternal(), + DesktopDialogCloseButton( + onPressedOverride: () { + Navigator.of( + context, + rootNavigator: true, + ).pop(); + }, ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + ), + child: AddDnsStep1( + name: _getNameFormattedForInternal(), ), - ], - ), + ), + ], ), - ) + ), + ) : StackDialogBase( - child: AddDnsStep1( - name: _getNameFormattedForInternal(), - ), - ); + child: AddDnsStep1( + name: _getNameFormattedForInternal(), + ), + ); }, ); }, @@ -254,11 +255,12 @@ class _BuyDomainWidgetState extends ConsumerState { if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Add DNS record failed", - desktopPopRootNavigator: Util.isDesktop, - maxWidth: Util.isDesktop ? 600 : null, - ), + builder: + (_) => StackOkDialog( + title: "Add DNS record failed", + desktopPopRootNavigator: Util.isDesktop, + maxWidth: Util.isDesktop ? 600 : null, + ), ); } } finally { @@ -289,8 +291,9 @@ class _BuyDomainWidgetState extends ConsumerState { builder: (ctx, constraints) { return SingleChildScrollView( child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), child: IntrinsicHeight( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -306,114 +309,120 @@ class _BuyDomainWidgetState extends ConsumerState { ); }, child: Column( - crossAxisAlignment: Util.isDesktop - ? CrossAxisAlignment.start - : CrossAxisAlignment.stretch, + crossAxisAlignment: + Util.isDesktop + ? CrossAxisAlignment.start + : CrossAxisAlignment.stretch, children: [ if (!Util.isDesktop) Text( "Buy domain", - style: Util.isDesktop - ? STextStyles.desktopH3(context) - : STextStyles.pageTitleH2(context), + style: + Util.isDesktop + ? STextStyles.desktopH3(context) + : STextStyles.pageTitleH2(context), ), - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), Row( - mainAxisAlignment: Util.isDesktop - ? MainAxisAlignment.center - : MainAxisAlignment.start, + mainAxisAlignment: + Util.isDesktop + ? MainAxisAlignment.center + : MainAxisAlignment.start, children: [ Text( "Name registration will take approximately 2 to 4 hours.", - style: Util.isDesktop - ? STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ) - : STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), ), ], ), - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Domain name", - style: Util.isDesktop - ? STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ) - : STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ), + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), ), Text( "${widget.domainName.substring(2)}.bit", - style: Util.isDesktop - ? STextStyles.w500_14(context) - : STextStyles.w500_12(context), + style: + Util.isDesktop + ? STextStyles.w500_14(context) + : STextStyles.w500_12(context), ), ], ), ), - SizedBox( - height: Util.isDesktop ? 16 : 8, - ), + SizedBox(height: Util.isDesktop ? 16 : 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Amount", - style: Util.isDesktop - ? STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ) - : STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ), + style: + Util.isDesktop + ? STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ) + : STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), ), Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( Amount( rawValue: BigInt.from(kNameNewAmountSats), fractionDigits: coin.fractionDigits, ), ), - style: Util.isDesktop - ? STextStyles.w500_14(context) - : STextStyles.w500_12(context), + style: + Util.isDesktop + ? STextStyles.w500_14(context) + : STextStyles.w500_12(context), ), ], ), ), - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Row( - children: [child], - ), + builder: (child) => Row(children: [child]), child: CustomTextButton( text: _settingsHidden ? "More settings" : "Hide settings", onTap: () { @@ -423,10 +432,7 @@ class _BuyDomainWidgetState extends ConsumerState { }, ), ), - if (!_settingsHidden) - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + if (!_settingsHidden) SizedBox(height: Util.isDesktop ? 24 : 16), if (!_settingsHidden) if (_dnsRecords.isEmpty) RoundedWhiteContainer( @@ -436,9 +442,10 @@ class _BuyDomainWidgetState extends ConsumerState { Text( "Add DNS records to your domain name", style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ], @@ -455,27 +462,25 @@ class _BuyDomainWidgetState extends ConsumerState { (e) => DNSRecordCard( key: ValueKey(e), record: e, - onRemoveTapped: () => setState(() { - _dnsRecords.remove(e); - }), + onRemoveTapped: + () => setState(() { + _dnsRecords.remove(e); + }), ), ), - SizedBox( - height: Util.isDesktop ? 16 : 8, - ), + SizedBox(height: Util.isDesktop ? 16 : 8), SecondaryButton( - label: _dnsRecords.isEmpty - ? "Add DNS record" - : "Add another DNS record", + label: + _dnsRecords.isEmpty + ? "Add DNS record" + : "Add another DNS record", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: _addRecord, ), ], ), ), - SizedBox( - height: Util.isDesktop ? 24 : 16, - ), + SizedBox(height: Util.isDesktop ? 24 : 16), if (!Util.isDesktop && _settingsHidden) const Spacer(), PrimaryButton( label: "Buy", @@ -483,9 +488,7 @@ class _BuyDomainWidgetState extends ConsumerState { buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: _preRegister, ), - SizedBox( - height: Util.isDesktop ? 32 : 16, - ), + SizedBox(height: Util.isDesktop ? 32 : 16), ], ), ); @@ -524,13 +527,8 @@ class DNSRecordCard extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "${record.type.name}$_extraInfo", - ), - CustomTextButton( - text: "Remove", - onTap: onRemoveTapped, - ), + Text("${record.type.name}$_extraInfo"), + CustomTextButton(text: "Remove", onTap: onRemoveTapped), ], ), Text(record.getValueString()), diff --git a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart index 6aaad59c0..db869b5f3 100644 --- a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart @@ -133,7 +133,7 @@ class _TransferOptionWidgetState extends ConsumerState { txData: TxData( feeRateType: kNameTxDefaultFeeRate, // TODO: make configurable? recipients: [ - ( + TxRecipient( address: _address!, isChange: false, amount: Amount( diff --git a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart index e438e420c..ac9f665d6 100644 --- a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart @@ -147,7 +147,7 @@ class _BuyDomainWidgetState extends ConsumerState { txData: TxData( feeRateType: kNameTxDefaultFeeRate, // TODO: make configurable? recipients: [ - ( + TxRecipient( address: _address!.value, isChange: false, amount: Amount( diff --git a/lib/pages/receive_view/addresses/address_details_view.dart b/lib/pages/receive_view/addresses/address_details_view.dart index 25e18becb..96c2e66a6 100644 --- a/lib/pages/receive_view/addresses/address_details_view.dart +++ b/lib/pages/receive_view/addresses/address_details_view.dart @@ -70,60 +70,60 @@ class _AddressDetailsViewState extends ConsumerState { void _showDesktopAddressQrCode() { showDialog( context: context, - builder: (context) => DesktopDialog( - maxWidth: 480, - maxHeight: 400, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (context) => DesktopDialog( + maxWidth: 480, + maxHeight: 400, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "Address QR code", - style: STextStyles.desktopH3(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Address QR code", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Center( - child: RepaintBoundary( - key: _qrKey, - child: QR( - data: AddressUtils.buildUriString( - ref.watch(pWalletCoin(widget.walletId)).uriScheme, - address.value, - {}, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: RepaintBoundary( + key: _qrKey, + child: QR( + data: AddressUtils.buildUriString( + ref.watch(pWalletCoin(widget.walletId)).uriScheme, + address.value, + {}, + ), + size: 220, + ), ), - size: 220, ), - ), + ], ), - ], - ), - ), - const SizedBox( - height: 32, + ), + const SizedBox(height: 32), + ], ), - ], - ), - ), + ), ); } @override void initState() { - address = MainDB.instance.isar.addresses - .where() - .idEqualTo(widget.addressId) - .findFirstSync()!; + address = + MainDB.instance.isar.addresses + .where() + .idEqualTo(widget.addressId) + .findFirstSync()!; label = MainDB.instance.getAddressLabelSync(widget.walletId, address.value); Id? id = label?.id; @@ -132,9 +132,10 @@ class _AddressDetailsViewState extends ConsumerState { walletId: widget.walletId, addressString: address.value, value: "", - tags: address.subType == AddressSubType.receiving - ? ["receiving"] - : address.subType == AddressSubType.change + tags: + address.subType == AddressSubType.receiving + ? ["receiving"] + : address.subType == AddressSubType.change ? ["change"] : null, ); @@ -151,43 +152,46 @@ class _AddressDetailsViewState extends ConsumerState { final wallet = ref.watch(pWallets).getWallet(widget.walletId); return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.backgroundAppBar, - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - titleSpacing: 0, - title: Text( - "Address details", - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: child, - ), - ), - ); - }, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "Address details", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ); + }, + ), + ), ), ), - ), - ), child: StreamBuilder( stream: stream, builder: (context, snapshot) { @@ -200,9 +204,7 @@ class _AddressDetailsViewState extends ConsumerState { builder: (child) { return Column( children: [ - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), RoundedWhiteContainer( padding: const EdgeInsets.all(24), child: Column( @@ -215,9 +217,10 @@ class _AddressDetailsViewState extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), CustomTextButton( @@ -226,19 +229,16 @@ class _AddressDetailsViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), RoundedWhiteContainer( padding: EdgeInsets.zero, - borderColor: Theme.of(context) - .extension()! - .backgroundAppBar, + borderColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, child: child, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -247,34 +247,35 @@ class _AddressDetailsViewState extends ConsumerState { style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: EdgeInsets.zero, - borderColor: Theme.of(context) - .extension()! - .backgroundAppBar, - child: ref - .watch(pWallets) - .getWallet(widget.walletId) - .isarTransactionVersion == - 2 - ? _AddressDetailsTxV2List( - walletId: widget.walletId, - address: address, - ) - : _AddressDetailsTxList( - walletId: widget.walletId, - address: address, - ), + borderColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, + child: + ref + .watch(pWallets) + .getWallet(widget.walletId) + .isarTransactionVersion == + 2 + ? _AddressDetailsTxV2List( + walletId: widget.walletId, + address: address, + ) + : _AddressDetailsTxList( + walletId: widget.walletId, + address: address, + ), ), ], ), @@ -299,24 +300,16 @@ class _AddressDetailsViewState extends ConsumerState { ), ), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), DetailItem( title: "Address", detail: address.value, - button: isDesktop - ? IconCopyButton( - data: address.value, - ) - : SimpleCopyButton( - data: address.value, - ), - ), - const _Div( - height: 12, + button: + isDesktop + ? IconCopyButton(data: address.value) + : SimpleCopyButton(data: address.value), ), + const _Div(height: 12), DetailItem( title: "Label", detail: label!.value, @@ -325,59 +318,47 @@ class _AddressDetailsViewState extends ConsumerState { editLabel: 'label', onValueChanged: (value) { MainDB.instance.putAddressLabel( - label!.copyWith( - label: value, - ), + label!.copyWith(label: value), ); }, ), ), - const _Div( - height: 12, - ), - _Tags( - tags: label!.tags, - ), - if (address.derivationPath != null) - const _Div( - height: 12, - ), + const _Div(height: 12), + _Tags(tags: label!.tags), + if (address.derivationPath != null) const _Div(height: 12), if (address.derivationPath != null) DetailItem( title: "Derivation path", detail: address.derivationPath!.value, button: Container(), ), - if (address.type == AddressType.spark) - const _Div( - height: 12, - ), + if (address.type == AddressType.spark) const _Div(height: 12), if (address.type == AddressType.spark) DetailItem( title: "Diversifier", detail: address.derivationIndex.toString(), button: Container(), ), - const _Div( - height: 12, - ), + if (address.type == AddressType.mweb) const _Div(height: 12), + if (address.type == AddressType.mweb) + DetailItem( + title: "Index", + detail: address.derivationIndex.toString(), + button: Container(), + ), + const _Div(height: 12), DetailItem( title: "Type", detail: address.type.readableName, button: Container(), ), - const _Div( - height: 12, - ), + const _Div(height: 12), DetailItem( title: "Sub type", detail: address.subType.prettyName, button: Container(), ), - if (kDebugMode) - const _Div( - height: 12, - ), + if (kDebugMode) const _Div(height: 12), if (kDebugMode) DetailItem( title: "frost secure (kDebugMode)", @@ -385,18 +366,13 @@ class _AddressDetailsViewState extends ConsumerState { button: Container(), ), if (wallet is Bip39HDWallet && !wallet.isViewOnly) - const _Div( - height: 12, - ), + const _Div(height: 12), if (wallet is Bip39HDWallet && !wallet.isViewOnly) AddressPrivateKey( walletId: widget.walletId, address: address, ), - if (!isDesktop) - const SizedBox( - height: 20, - ), + if (!isDesktop) const SizedBox(height: 20), if (!isDesktop) Text( "Transactions", @@ -406,10 +382,7 @@ class _AddressDetailsViewState extends ConsumerState { Theme.of(context).extension()!.textDark3, ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), if (!isDesktop) ref .watch(pWallets) @@ -417,13 +390,13 @@ class _AddressDetailsViewState extends ConsumerState { .isarTransactionVersion == 2 ? _AddressDetailsTxV2List( - walletId: widget.walletId, - address: address, - ) + walletId: widget.walletId, + address: address, + ) : _AddressDetailsTxList( - walletId: widget.walletId, - address: address, - ), + walletId: widget.walletId, + address: address, + ), ], ), ); @@ -458,10 +431,9 @@ class _AddressDetailsTxList extends StatelessWidget { return ListView.separated( shrinkWrap: true, primary: false, - itemBuilder: (_, index) => TransactionCard( - transaction: txns[index], - walletId: walletId, - ), + itemBuilder: + (_, index) => + TransactionCard(transaction: txns[index], walletId: walletId), separatorBuilder: (_, __) => const _Div(height: 1), itemCount: count, ); @@ -470,15 +442,14 @@ class _AddressDetailsTxList extends StatelessWidget { padding: EdgeInsets.zero, child: Column( mainAxisSize: MainAxisSize.min, - children: query - .findAllSync() - .map( - (e) => TransactionCard( - transaction: e, - walletId: walletId, - ), - ) - .toList(), + children: + query + .findAllSync() + .map( + (e) => + TransactionCard(transaction: e, walletId: walletId), + ) + .toList(), ), ); } @@ -503,40 +474,35 @@ class _AddressDetailsTxV2List extends ConsumerWidget { final walletTxFilter = ref.watch(pWallets).getWallet(walletId).transactionFilterOperation; - final query = - ref.watch(mainDBProvider).isar.transactionV2s.buildQuery( - whereClauses: [ - IndexWhereClause.equalTo( - indexName: 'walletId', - value: [walletId], + final query = ref + .watch(mainDBProvider) + .isar + .transactionV2s + .buildQuery( + whereClauses: [ + IndexWhereClause.equalTo(indexName: 'walletId', value: [walletId]), + ], + filter: FilterGroup.and([ + if (walletTxFilter != null) walletTxFilter, + FilterGroup.or([ + ObjectFilter( + property: 'inputs', + filter: FilterCondition.contains( + property: "addresses", + value: address.value, ), - ], - filter: FilterGroup.and([ - if (walletTxFilter != null) walletTxFilter, - FilterGroup.or([ - ObjectFilter( - property: 'inputs', - filter: FilterCondition.contains( - property: "addresses", - value: address.value, - ), - ), - ObjectFilter( - property: 'outputs', - filter: FilterCondition.contains( - property: "addresses", - value: address.value, - ), - ), - ]), - ]), - sortBy: [ - const SortProperty( - property: "timestamp", - sort: Sort.desc, + ), + ObjectFilter( + property: 'outputs', + filter: FilterCondition.contains( + property: "addresses", + value: address.value, ), - ], - ); + ), + ]), + ]), + sortBy: [const SortProperty(property: "timestamp", sort: Sort.desc)], + ); final count = query.countSync(); @@ -546,9 +512,8 @@ class _AddressDetailsTxV2List extends ConsumerWidget { return ListView.separated( shrinkWrap: true, primary: false, - itemBuilder: (_, index) => TransactionCardV2( - transaction: txns[index], - ), + itemBuilder: + (_, index) => TransactionCardV2(transaction: txns[index]), separatorBuilder: (_, __) => const _Div(height: 1), itemCount: count, ); @@ -557,14 +522,11 @@ class _AddressDetailsTxV2List extends ConsumerWidget { padding: EdgeInsets.zero, child: Column( mainAxisSize: MainAxisSize.min, - children: query - .findAllSync() - .map( - (e) => TransactionCardV2( - transaction: e, - ), - ) - .toList(), + children: + query + .findAllSync() + .map((e) => TransactionCardV2(transaction: e)) + .toList(), ), ); } @@ -575,10 +537,7 @@ class _AddressDetailsTxV2List extends ConsumerWidget { } class _Div extends StatelessWidget { - const _Div({ - super.key, - required this.height, - }); + const _Div({super.key, required this.height}); final double height; @@ -591,18 +550,13 @@ class _Div extends StatelessWidget { width: double.infinity, ); } else { - return SizedBox( - height: height, - ); + return SizedBox(height: height); } } } class _Tags extends StatelessWidget { - const _Tags({ - super.key, - required this.tags, - }); + const _Tags({super.key, required this.tags}); final List? tags; @@ -615,10 +569,7 @@ class _Tags extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Tags", - style: STextStyles.itemSubtitle(context), - ), + Text("Tags", style: STextStyles.itemSubtitle(context)), Container(), // SimpleEditButton( // onPressedOverride: () { @@ -627,29 +578,20 @@ class _Tags extends StatelessWidget { // ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), tags != null && tags!.isNotEmpty ? Wrap( - spacing: 10, - runSpacing: 10, - children: tags! - .map( - (e) => AddressTag( - tag: e, - ), - ) - .toList(), - ) + spacing: 10, + runSpacing: 10, + children: tags!.map((e) => AddressTag(tag: e)).toList(), + ) : Text( - "Tags will appear here", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle3, - ), + "Tags will appear here", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of(context).extension()!.textSubtitle3, ), + ), ], ), ); diff --git a/lib/pages/send_view/frost_ms/frost_send_view.dart b/lib/pages/send_view/frost_ms/frost_send_view.dart index 729bf7c69..70f9f964b 100644 --- a/lib/pages/send_view/frost_ms/frost_send_view.dart +++ b/lib/pages/send_view/frost_ms/frost_send_view.dart @@ -83,7 +83,13 @@ class _FrostSendViewState extends ConsumerState { final recipients = recipientWidgetIndexes .map((i) => ref.read(pRecipient(i).state).state) - .map((e) => (address: e!.address, amount: e!.amount!, isChange: false)) + .map( + (e) => TxRecipient( + address: e!.address, + amount: e.amount!, + isChange: false, + ), + ) .toList(growable: false); final txData = await wallet.frostCreateSignConfig( diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart index ade993b22..21d85fe9c 100644 --- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart +++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart @@ -4,6 +4,7 @@ import 'package:isar/isar.dart'; import '../../../../frost_route_generator.dart'; import '../../../../models/isar/models/isar_models.dart'; +import '../../../../models/signing_data.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/frost_wallet/frost_wallet_providers.dart'; import '../../../../providers/global/wallets_provider.dart'; @@ -60,9 +61,9 @@ class _FrostSendStep1bState extends ConsumerState { } final config = configFieldController.text; - final wallet = ref.read(pWallets).getWallet( - ref.read(pFrostScaffoldArgs)!.walletId!, - ) as BitcoinFrostWallet; + final wallet = + ref.read(pWallets).getWallet(ref.read(pFrostScaffoldArgs)!.walletId!) + as BitcoinFrostWallet; final data = Frost.extractDataFromSignConfig( signConfig: config, @@ -70,28 +71,36 @@ class _FrostSendStep1bState extends ConsumerState { serializedKeys: (await wallet.getSerializedKeys())!, ); - final utxos = await ref - .read(mainDBProvider) - .getUTXOs(wallet.walletId) - .filter() - .anyOf( - data.inputs, - (q, e) => q - .txidEqualTo(Format.uint8listToString(e.hash)) - .and() - .valueEqualTo(e.value) - .and() - .voutEqualTo(e.vout), - ) - .findAll(); + final utxos = + await ref + .read(mainDBProvider) + .getUTXOs(wallet.walletId) + .filter() + .anyOf( + data.inputs, + (q, e) => q + .txidEqualTo(Format.uint8listToString(e.hash)) + .and() + .valueEqualTo(e.value) + .and() + .voutEqualTo(e.vout), + ) + .findAll(); // TODO add more data from 'data' and display to user ? ref.read(pFrostTxData.notifier).state = TxData( frostMSConfig: config, - recipients: data.recipients - .map((e) => (address: e.address, amount: e.amount, isChange: false)) - .toList(), - utxos: utxos.toSet(), + recipients: + data.recipients + .map( + (e) => TxRecipient( + address: e.address, + amount: e.amount, + isChange: false, + ), + ) + .toList(), + utxos: utxos.map((e) => StandardInput(e)).toSet(), ); final attemptSignRes = await wallet.frostAttemptSignConfig( @@ -112,11 +121,12 @@ class _FrostSendStep1bState extends ConsumerState { if (mounted) { await showDialog( context: context, - builder: (_) => StackOkDialog( - title: "Import and attempt sign config failed", - message: e.toString(), - desktopPopRootNavigator: Util.isDesktop, - ), + builder: + (_) => StackOkDialog( + title: "Import and attempt sign config failed", + message: e.toString(), + desktopPopRootNavigator: Util.isDesktop, + ), ); } } finally { @@ -128,9 +138,9 @@ class _FrostSendStep1bState extends ConsumerState { void initState() { configFieldController = TextEditingController(); configFocusNode = FocusNode(); - final wallet = ref.read(pWallets).getWallet( - ref.read(pFrostScaffoldArgs)!.walletId!, - ) as BitcoinFrostWallet; + final wallet = + ref.read(pWallets).getWallet(ref.read(pFrostScaffoldArgs)!.walletId!) + as BitcoinFrostWallet; WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(pFrostMyName.state).state = wallet.frostInfo.myName; }); @@ -152,9 +162,7 @@ class _FrostSendStep1bState extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const FrostStepUserSteps( - userSteps: info, - ), + const FrostStepUserSteps(userSteps: info), const SizedBox(height: 20), FrostStepField( controller: configFieldController, @@ -169,11 +177,10 @@ class _FrostSendStep1bState extends ConsumerState { }, ), if (!Util.isDesktop) const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), CheckboxTextButton( - label: "I have verified that everyone has imported he config and" + label: + "I have verified that everyone has imported he config and" " is ready to sign", onChanged: (value) { setState(() { @@ -181,9 +188,7 @@ class _FrostSendStep1bState extends ConsumerState { }); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), PrimaryButton( label: "Start signing", enabled: !_configEmpty && _userVerifyContinue, diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart index 6ce475a0b..f3ddc90cc 100644 --- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart +++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart @@ -51,9 +51,9 @@ class _FrostSendStep3State extends ConsumerState { @override void initState() { - final wallet = ref.read(pWallets).getWallet( - ref.read(pFrostScaffoldArgs)!.walletId!, - ) as BitcoinFrostWallet; + final wallet = + ref.read(pWallets).getWallet(ref.read(pFrostScaffoldArgs)!.walletId!) + as BitcoinFrostWallet; final frostInfo = wallet.frostInfo; @@ -62,12 +62,13 @@ class _FrostSendStep3State extends ConsumerState { myIndex = frostInfo.participants.indexOf(frostInfo.myName); myShare = ref.read(pFrostContinueSignData.state).state!.share; - participantsWithoutMe = frostInfo.participants - .toSet() - .intersection( - ref.read(pFrostSelectParticipantsUnordered.state).state!.toSet(), - ) - .toList(); + participantsWithoutMe = + frostInfo.participants + .toSet() + .intersection( + ref.read(pFrostSelectParticipantsUnordered.state).state!.toSet(), + ) + .toList(); participantsWithoutMe.remove(myName); @@ -98,46 +99,28 @@ class _FrostSendStep3State extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const FrostStepUserSteps( - userSteps: info, - ), - const SizedBox( - height: 12, - ), + const FrostStepUserSteps(userSteps: info), + const SizedBox(height: 12), DetailItem( title: "My name", detail: myName, - button: Util.isDesktop - ? IconCopyButton( - data: myName, - ) - : SimpleCopyButton( - data: myName, - ), - ), - const SizedBox( - height: 12, + button: + Util.isDesktop + ? IconCopyButton(data: myName) + : SimpleCopyButton(data: myName), ), + const SizedBox(height: 12), DetailItem( title: "My share", detail: myShare, - button: Util.isDesktop - ? IconCopyButton( - data: myShare, - ) - : SimpleCopyButton( - data: myShare, - ), - ), - const SizedBox( - height: 12, - ), - FrostQrDialogPopupButton( - data: myShare, - ), - const SizedBox( - height: 12, + button: + Util.isDesktop + ? IconCopyButton(data: myShare) + : SimpleCopyButton(data: myShare), ), + const SizedBox(height: 12), + FrostQrDialogPopupButton(data: myShare), + const SizedBox(height: 12), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -158,9 +141,7 @@ class _FrostSendStep3State extends ConsumerState { ], ), if (!Util.isDesktop) const Spacer(), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), CheckboxTextButton( label: "I have verified that everyone has my share", onChanged: (value) { @@ -169,12 +150,11 @@ class _FrostSendStep3State extends ConsumerState { }); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), PrimaryButton( label: "Generate transaction", - enabled: _userVerifyContinue && + enabled: + _userVerifyContinue && !fieldIsEmptyFlags.fold(false, (v, e) => v |= e), onPressed: () async { // collect Share strings @@ -206,23 +186,21 @@ class _FrostSendStep3State extends ConsumerState { final inputTotal = Amount( rawValue: txData.utxos! - .map((e) => BigInt.from(e.value)) + .map((e) => e.value) .reduce((v, e) => v += e), fractionDigits: fractionDigits, ); final outputTotal = Amount( - rawValue: - tx.outputs.map((e) => e.value).reduce((v, e) => v += e), + rawValue: tx.outputs + .map((e) => e.value) + .reduce((v, e) => v += e), fractionDigits: fractionDigits, ); ref.read(pFrostTxData.state).state = txData.copyWith( raw: rawTx, fee: inputTotal - outputTotal, - frostSigners: [ - myName, - ...participantsWithoutMe, - ], + frostSigners: [myName, ...participantsWithoutMe], ); ref.read(pFrostCreateCurrentStep.state).state = 4; @@ -233,14 +211,15 @@ class _FrostSendStep3State extends ConsumerState { .routeName, ); } catch (e, s) { - Logging.instance.f("$e\n$s", error: e, stackTrace: s,); + Logging.instance.f("$e\n$s", error: e, stackTrace: s); if (context.mounted) { return await showDialog( context: context, - builder: (_) => const FrostErrorDialog( - title: "Failed to complete signing process", - ), + builder: + (_) => const FrostErrorDialog( + title: "Failed to complete signing process", + ), ); } } diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index be21c99d6..63df318e8 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -22,6 +22,7 @@ import 'package:tuple/tuple.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; import '../../models/send_view_auto_fill_data.dart'; +import '../../models/signing_data.dart'; import '../../providers/providers.dart'; import '../../providers/ui/fee_rate_type_state_provider.dart'; import '../../providers/ui/preview_tx_button_state_provider.dart'; @@ -52,6 +53,7 @@ import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/models/tx_data.dart'; import '../../wallets/wallet/impl/firo_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../widgets/animated_text.dart'; @@ -141,7 +143,7 @@ class _SendViewState extends ConsumerState { bool _cryptoAmountChangeLock = false; late VoidCallback onCryptoAmountChanged; - Set selectedUTXOs = {}; + Set selectedUTXOs = {}; void _applyUri(PaymentUriData paymentData) { try { @@ -714,7 +716,7 @@ class _SendViewState extends ConsumerState { txData: TxData( paynymAccountLite: widget.accountLite!, recipients: [ - ( + TxRecipient( address: widget.accountLite!.code, amount: amount, isChange: false, @@ -756,7 +758,11 @@ class _SendViewState extends ConsumerState { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - (address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + ), ], feeRateType: ref.read(feeRateTypeMobileStateProvider), satsPerVByte: isCustomFee.value ? customFeeRate : null, @@ -776,7 +782,11 @@ class _SendViewState extends ConsumerState { ref.read(pValidSparkSendToAddress) ? null : [ - (address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + ), ], sparkRecipients: ref.read(pValidSparkSendToAddress) @@ -793,11 +803,31 @@ class _SendViewState extends ConsumerState { ); break; } + } else if (wallet is MwebInterface && + ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { + txDataFuture = wallet.prepareSend( + txData: TxData( + isMweb: true, + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], + feeRateType: ref.read(feeRateTypeDesktopStateProvider), + satsPerVByte: isCustomFee.value ? customFeeRate : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + selectedUTXOs.isNotEmpty) + ? selectedUTXOs + : null, + ), + ); } else { final memo = coin is Stellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [(address: _address!, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], memo: memo, feeRateType: ref.read(feeRateTypeMobileStateProvider), satsPerVByte: isCustomFee.value ? customFeeRate : null, @@ -906,7 +936,10 @@ class _SendViewState extends ConsumerState { } } - String _getSendAllTitle(bool showCoinControl, Set selectedUTXOs) { + String _getSendAllTitle( + bool showCoinControl, + Set selectedUTXOs, + ) { if (showCoinControl && selectedUTXOs.isNotEmpty) { return "Send all selected"; } @@ -914,8 +947,8 @@ class _SendViewState extends ConsumerState { return "Send all ${coin.ticker}"; } - Amount _selectedUtxosAmount(Set utxos) => Amount( - rawValue: utxos.map((e) => BigInt.from(e.value)).reduce((v, e) => v += e), + Amount _selectedUtxosAmount(Set utxos) => Amount( + rawValue: utxos.map((e) => e.value).reduce((v, e) => v += e), fractionDigits: ref.read(pWalletCoin(walletId)).fractionDigits, ); @@ -2065,13 +2098,20 @@ class _SendViewState extends ConsumerState { walletId, CoinControlViewType.use, amount, - selectedUTXOs, + selectedUTXOs + .map((e) => e.utxo) + .toSet(), ), ); if (result is Set) { setState(() { - selectedUTXOs = result; + selectedUTXOs = + result + .map( + (e) => StandardInput(e), + ) + .toSet(); }); } } diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index fe7f4bb46..70f076c01 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -491,7 +491,9 @@ class _TokenSendViewState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( - recipients: [(address: _address!, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], feeRateType: ref.read(feeRateTypeMobileStateProvider), note: noteController.text, ethEIP1559Fee: ethFee, diff --git a/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart index c66fb387d..4f8e8576f 100644 --- a/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart +++ b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart @@ -17,6 +17,7 @@ import 'package:isar/isar.dart'; import '../../db/isar/main_db.dart'; import '../../models/isar/models/blockchain_data/utxo.dart'; +import '../../models/signing_data.dart'; import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount.dart'; @@ -41,6 +42,9 @@ import '../../widgets/toggle.dart'; import 'utxo_row.dart'; final desktopUseUTXOs = StateProvider((ref) => {}); +final pDesktopUseUTXOs = Provider( + (ref) => ref.watch(desktopUseUTXOs).map((e) => StandardInput(e)).toSet(), +); class DesktopCoinControlUseDialog extends ConsumerStatefulWidget { const DesktopCoinControlUseDialog({ @@ -124,21 +128,22 @@ class _DesktopCoinControlUseDialogState ); } - final Amount selectedSum = _selectedUTXOs.map((e) => e.value).fold( - Amount( - rawValue: BigInt.zero, - fractionDigits: coin.fractionDigits, - ), - (value, element) => value += Amount( - rawValue: BigInt.from(element), - fractionDigits: coin.fractionDigits, - ), + final Amount selectedSum = _selectedUTXOs + .map((e) => e.value) + .fold( + Amount(rawValue: BigInt.zero, fractionDigits: coin.fractionDigits), + (value, element) => + value += Amount( + rawValue: BigInt.from(element), + fractionDigits: coin.fractionDigits, + ), ); - final enableApply = widget.amountToSend == null - ? selectedChanged(_selectedUTXOs) - : selectedChanged(_selectedUTXOs) && - widget.amountToSend! <= selectedSum; + final enableApply = + widget.amountToSend == null + ? selectedChanged(_selectedUTXOs) + : selectedChanged(_selectedUTXOs) && + widget.amountToSend! <= selectedSum; return DesktopDialog( maxWidth: 700, @@ -147,14 +152,8 @@ class _DesktopCoinControlUseDialogState children: [ Row( children: [ - const AppBarBackButton( - size: 40, - iconSize: 24, - ), - Text( - "Coin control", - style: STextStyles.desktopH3(context), - ), + const AppBarBackButton(size: 40, iconSize: 24), + Text("Coin control", style: STextStyles.desktopH3(context)), ], ), Expanded( @@ -164,24 +163,24 @@ class _DesktopCoinControlUseDialogState children: [ RoundedContainer( color: Colors.transparent, - borderColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + borderColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "This option allows you to control, freeze, and utilize " "outputs at your discretion.", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -199,11 +198,13 @@ class _DesktopCoinControlUseDialogState _searchString = value; }); }, - style: STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, height: 1.8, ), decoration: standardInputDecoration( @@ -223,44 +224,47 @@ class _DesktopCoinControlUseDialogState height: 20, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SizedBox( height: 56, width: 240, child: Toggle( isOn: _filter == CCFilter.frozen, - onColor: Theme.of(context) - .extension()! - .rateTypeToggleDesktopColorOn, - offColor: Theme.of(context) - .extension()! - .rateTypeToggleDesktopColorOff, + onColor: + Theme.of(context) + .extension()! + .rateTypeToggleDesktopColorOn, + offColor: + Theme.of(context) + .extension()! + .rateTypeToggleDesktopColorOff, onIcon: Assets.svg.coinControl.unBlocked, onText: "Available", offIcon: Assets.svg.coinControl.blocked, @@ -281,9 +285,7 @@ class _DesktopCoinControlUseDialogState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), JDropdownIconButton( redrawOnScreenSizeChanged: true, groupValue: _sort, @@ -299,164 +301,169 @@ class _DesktopCoinControlUseDialogState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Expanded( - child: _list != null - ? ListView.separated( - shrinkWrap: true, - primary: false, - itemCount: _list!.length, - separatorBuilder: (context, _) => const SizedBox( - height: 10, - ), - itemBuilder: (context, index) { - final utxo = MainDB.instance.isar.utxos - .where() - .idEqualTo(_list![index]) - .findFirstSync()!; - final data = UtxoRowData(utxo.id, false); - data.selected = _selectedUTXOsData.contains(data); + child: + _list != null + ? ListView.separated( + shrinkWrap: true, + primary: false, + itemCount: _list!.length, + separatorBuilder: + (context, _) => const SizedBox(height: 10), + itemBuilder: (context, index) { + final utxo = + MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; + final data = UtxoRowData(utxo.id, false); + data.selected = _selectedUTXOsData.contains( + data, + ); - return UtxoRow( - key: Key( - "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}", - ), - data: data, - compact: true, - walletId: widget.walletId, - onSelectionChanged: (value) { - setState(() { - if (data.selected) { - _selectedUTXOsData.add(value); - _selectedUTXOs.add(utxo); + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}", + ), + data: data, + compact: true, + walletId: widget.walletId, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOsData.add(value); + _selectedUTXOs.add(utxo); + } else { + _selectedUTXOsData.remove(value); + _selectedUTXOs.remove(utxo); + } + }); + }, + ); + }, + ) + : ListView.separated( + itemCount: _map!.entries.length, + separatorBuilder: + (context, _) => const SizedBox(height: 10), + itemBuilder: (context, index) { + final entry = _map!.entries.elementAt(index); + final _controller = RotateIconController(); + + return Expandable2( + border: + Theme.of(context) + .extension()! + .backgroundAppBar, + background: + Theme.of( + context, + ).extension()!.popupBG, + animationDurationMultiplier: + 0.2 * entry.value.length, + onExpandWillChange: (state) { + if (state == Expandable2State.expanded) { + _controller.forward?.call(); } else { - _selectedUTXOsData.remove(value); - _selectedUTXOs.remove(utxo); + _controller.reverse?.call(); } - }); - }, - ); - }, - ) - : ListView.separated( - itemCount: _map!.entries.length, - separatorBuilder: (context, _) => const SizedBox( - height: 10, - ), - itemBuilder: (context, index) { - final entry = _map!.entries.elementAt(index); - final _controller = RotateIconController(); - - return Expandable2( - border: Theme.of(context) - .extension()! - .backgroundAppBar, - background: Theme.of(context) - .extension()! - .popupBG, - animationDurationMultiplier: - 0.2 * entry.value.length, - onExpandWillChange: (state) { - if (state == Expandable2State.expanded) { - _controller.forward?.call(); - } else { - _controller.reverse?.call(); - } - }, - header: RoundedContainer( - padding: const EdgeInsets.all(20), - color: Colors.transparent, - child: Row( - children: [ - SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), + }, + header: RoundedContainer( + padding: const EdgeInsets.all(20), + color: Colors.transparent, + child: Row( + children: [ + SvgPicture.file( + File( + ref.watch(coinIconProvider(coin)), + ), + width: 24, + height: 24, ), - width: 24, - height: 24, - ), - const SizedBox( - width: 12, - ), - Expanded( - flex: 3, - child: Text( - entry.key, - style: STextStyles.w600_14(context), + const SizedBox(width: 12), + Expanded( + flex: 3, + child: Text( + entry.key, + style: STextStyles.w600_14(context), + ), ), - ), - Expanded( - child: Text( - "${entry.value.length} " - "output${entry.value.length > 1 ? "s" : ""}", - style: STextStyles - .desktopTextExtraExtraSmall( - context, + Expanded( + child: Text( + "${entry.value.length} " + "output${entry.value.length > 1 ? "s" : ""}", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ), - ), - RotateIcon( - animationDurationMultiplier: - 0.2 * entry.value.length, - icon: SvgPicture.asset( - Assets.svg.chevronDown, - width: 14, - color: Theme.of(context) - .extension()! - .textSubtitle1, + RotateIcon( + animationDurationMultiplier: + 0.2 * entry.value.length, + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 14, + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + curve: Curves.easeInOut, + controller: _controller, ), - curve: Curves.easeInOut, - controller: _controller, - ), - ], + ], + ), ), - ), - children: entry.value.map( - (id) { - final utxo = MainDB.instance.isar.utxos - .where() - .idEqualTo(id) - .findFirstSync()!; - final data = UtxoRowData(utxo.id, false); - data.selected = - _selectedUTXOsData.contains(data); + children: + entry.value.map((id) { + final utxo = + MainDB.instance.isar.utxos + .where() + .idEqualTo(id) + .findFirstSync()!; + final data = UtxoRowData( + utxo.id, + false, + ); + data.selected = _selectedUTXOsData + .contains(data); - return UtxoRow( - key: Key( - "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}", - ), - data: data, - compact: true, - compactWithBorder: false, - raiseOnSelected: false, - walletId: widget.walletId, - onSelectionChanged: (value) { - setState(() { - if (data.selected) { - _selectedUTXOsData.add(value); - _selectedUTXOs.add(utxo); - } else { - _selectedUTXOsData.remove(value); - _selectedUTXOs.remove(utxo); - } - }); - }, - ); - }, - ).toList(), - ); - }, - ), - ), - const SizedBox( - height: 16, + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}", + ), + data: data, + compact: true, + compactWithBorder: false, + raiseOnSelected: false, + walletId: widget.walletId, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOsData.add(value); + _selectedUTXOs.add(utxo); + } else { + _selectedUTXOsData.remove( + value, + ); + _selectedUTXOs.remove(utxo); + } + }); + }, + ); + }).toList(), + ); + }, + ), ), + const SizedBox(height: 16), RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, padding: EdgeInsets.zero, child: ConditionalParent( condition: widget.amountToSend != null, @@ -467,9 +474,10 @@ class _DesktopCoinControlUseDialogState child, Container( height: 1.2, - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, ), Padding( padding: const EdgeInsets.all(16), @@ -481,26 +489,26 @@ class _DesktopCoinControlUseDialogState "Amount to send", style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ), ), SelectableText( - "${widget.amountToSend!.decimal.toStringAsFixed( - coin.fractionDigits, - )}" + "${widget.amountToSend!.decimal.toStringAsFixed(coin.fractionDigits)}" " ${coin.ticker}", style: STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ), ), ], ), @@ -518,23 +526,23 @@ class _DesktopCoinControlUseDialogState style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), SelectableText( - "${selectedSum.decimal.toStringAsFixed( - coin.fractionDigits, - )} ${coin.ticker}", + "${selectedSum.decimal.toStringAsFixed(coin.fractionDigits)} ${coin.ticker}", style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: widget.amountToSend == null - ? Theme.of(context) - .extension()! - .textDark - : selectedSum < widget.amountToSend! + color: + widget.amountToSend == null + ? Theme.of( + context, + ).extension()!.textDark + : selectedSum < widget.amountToSend! ? Theme.of(context) .extension()! .accentColorRed @@ -548,18 +556,17 @@ class _DesktopCoinControlUseDialogState ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( child: SecondaryButton( enabled: _selectedUTXOsData.isNotEmpty, buttonHeight: ButtonHeight.l, - label: _selectedUTXOsData.isEmpty - ? "Clear selection" - : "Clear selection (${_selectedUTXOsData.length})", + label: + _selectedUTXOsData.isEmpty + ? "Clear selection" + : "Clear selection (${_selectedUTXOsData.length})", onPressed: () { setState(() { _selectedUTXOsData.clear(); @@ -568,9 +575,7 @@ class _DesktopCoinControlUseDialogState }, ), ), - const SizedBox( - width: 20, - ), + const SizedBox(width: 20), Expanded( child: PrimaryButton( enabled: enableApply, @@ -586,9 +591,7 @@ class _DesktopCoinControlUseDialogState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index bf07ef580..b5cb4e7c9 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -49,6 +49,7 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/models/tx_data.dart'; import '../../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../widgets/custom_buttons/blue_text_button.dart'; @@ -163,7 +164,7 @@ class _DesktopSendState extends ConsumerState { final Amount amount = ref.read(pSendAmount)!; final Amount availableBalance; - if ((coin is Firo)) { + if (coin is Firo || ref.read(pWalletInfo(walletId)).isMwebEnabled) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case BalanceType.public: availableBalance = wallet.info.cachedBalance.spendable; @@ -310,7 +311,7 @@ class _DesktopSendState extends ConsumerState { txData: TxData( paynymAccountLite: widget.accountLite!, recipients: [ - ( + TxRecipient( address: widget.accountLite!.code, amount: amount, isChange: false, @@ -321,8 +322,8 @@ class _DesktopSendState extends ConsumerState { utxos: (wallet is CoinControlInterface && coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) + ref.read(pDesktopUseUTXOs).isNotEmpty) + ? ref.read(pDesktopUseUTXOs) : null, ), ); @@ -344,8 +345,8 @@ class _DesktopSendState extends ConsumerState { satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) + ref.read(pDesktopUseUTXOs).isNotEmpty) + ? ref.read(pDesktopUseUTXOs) : null, ), ); @@ -353,14 +354,18 @@ class _DesktopSendState extends ConsumerState { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - (address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + ), ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, utxos: (coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) + ref.read(pDesktopUseUTXOs).isNotEmpty) + ? ref.read(pDesktopUseUTXOs) : null, ), ); @@ -374,7 +379,11 @@ class _DesktopSendState extends ConsumerState { ref.read(pValidSparkSendToAddress) ? null : [ - (address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + ), ], sparkRecipients: ref.read(pValidSparkSendToAddress) @@ -391,11 +400,31 @@ class _DesktopSendState extends ConsumerState { ); break; } + } else if (wallet is MwebInterface && + ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { + txDataFuture = wallet.prepareSend( + txData: TxData( + isMweb: true, + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], + feeRateType: ref.read(feeRateTypeDesktopStateProvider), + satsPerVByte: isCustomFee ? customFeeRate : null, + utxos: + (wallet is CoinControlInterface && + coinControlEnabled && + ref.read(pDesktopUseUTXOs).isNotEmpty) + ? ref.read(pDesktopUseUTXOs) + : null, + ), + ); } else { final memo = isStellar ? memoController.text : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [(address: _address!, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], memo: memo, feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, @@ -406,8 +435,8 @@ class _DesktopSendState extends ConsumerState { utxos: (wallet is CoinControlInterface && coinControlEnabled && - ref.read(desktopUseUTXOs).isNotEmpty) - ? ref.read(desktopUseUTXOs) + ref.read(pDesktopUseUTXOs).isNotEmpty) + ? ref.read(pDesktopUseUTXOs) : null, ethEIP1559Fee: ethFee, ), @@ -835,7 +864,7 @@ class _DesktopSendState extends ConsumerState { if (showCoinControl && ref.read(desktopUseUTXOs).isNotEmpty) { amount = _selectedUtxosAmount(ref.read(desktopUseUTXOs)); - } else if (coin is Firo) { + } else if (coin is Firo || ref.read(pWalletInfo(walletId)).isMwebEnabled) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case BalanceType.public: amount = ref.read(pWalletBalance(walletId)).spendable; @@ -975,6 +1004,10 @@ class _DesktopSendState extends ConsumerState { final balType = ref.watch(publicPrivateBalanceStateProvider); + final isMwebEnabled = ref.watch( + pWalletInfo(walletId).select((s) => s.isMwebEnabled), + ); + final showPrivateBalance = coin is Firo || isMwebEnabled; final isExchangeAddress = ref.watch(pIsExchangeAddress); ref.listen(publicPrivateBalanceStateProvider, (previous, next) { if (previous != next && @@ -998,7 +1031,7 @@ class _DesktopSendState extends ConsumerState { ), ) && ref.watch(pWallets).getWallet(walletId) is CoinControlInterface && - (coin is Firo ? balType == BalanceType.public : true); + balType == BalanceType.public; return Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index aac8ec01d..581b5a824 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -232,7 +232,9 @@ class _DesktopTokenSendState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( - recipients: [(address: _address!, amount: amount, isChange: false)], + recipients: [ + TxRecipient(address: _address!, amount: amount, isChange: false), + ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), nonce: int.tryParse(nonceController.text), ethEIP1559Fee: ethFee, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index d06d84400..17c055614 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -213,10 +213,9 @@ class _DesktopWalletFeaturesState extends ConsumerState { ), ), ); - final firoWallet = - ref.read(pWallets).getWallet(widget.walletId) as FiroWallet; - final publicBalance = firoWallet.info.cachedBalance.spendable; + final wallet = ref.read(pWallets).getWallet(widget.walletId); + final publicBalance = wallet.info.cachedBalance.spendable; if (publicBalance <= Amount.zero) { shouldPop = true; if (context.mounted) { @@ -236,7 +235,11 @@ class _DesktopWalletFeaturesState extends ConsumerState { } try { - await firoWallet.anonymizeAllSpark(); + if (wallet is MwebInterface && wallet.info.isMwebEnabled) { + await wallet.anonymizeAllMweb(); + } else { + await (wallet as FiroWallet).anonymizeAllSpark(); + } shouldPop = true; if (mounted) { Navigator.of(context, rootNavigator: true).pop(); @@ -391,7 +394,9 @@ class _DesktopWalletFeaturesState extends ConsumerState { final isViewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly; return [ - if (!isViewOnly && coin is Firo) + if (!isViewOnly && + (coin is Firo || + (wallet is MwebInterface && wallet.info.isMwebEnabled))) ( WalletFeature.anonymizeFunds, Assets.svg.recycle, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 3df3c9504..b3510022c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -271,7 +271,7 @@ class _MoreFeaturesDialogState extends ConsumerState { unawaited( ref .read(pMwebService) - .init(ref.read(pWalletCoin(widget.walletId)).network), + .initService(ref.read(pWalletCoin(widget.walletId)).network), ); } diff --git a/lib/services/frost.dart b/lib/services/frost.dart index 76c0b5db9..33066de92 100644 --- a/lib/services/frost.dart +++ b/lib/services/frost.dart @@ -12,12 +12,11 @@ import '../utilities/amount/amount.dart'; import '../utilities/extensions/extensions.dart'; import '../utilities/logger.dart'; import '../wallets/crypto_currency/crypto_currency.dart'; +import '../wallets/models/tx_recipient.dart'; abstract class Frost { //==================== utility =============================================== - static List getParticipants({ - required String multisigConfig, - }) { + static List getParticipants({required String multisigConfig}) { try { final numberOfParticipants = multisigParticipants( multisigConfig: multisigConfig, @@ -26,10 +25,7 @@ abstract class Frost { final List participants = []; for (int i = 0; i < numberOfParticipants; i++) { participants.add( - multisigParticipant( - multisigConfig: multisigConfig, - index: i, - ), + multisigParticipant(multisigConfig: multisigConfig, index: i), ); } @@ -45,18 +41,18 @@ abstract class Frost { decodeMultisigConfig(multisigConfig: encodedConfig); return true; } catch (e, s) { - Logging.instance.f("validateEncodedMultisigConfig failed: ", error: e, stackTrace: s); + Logging.instance.f( + "validateEncodedMultisigConfig failed: ", + error: e, + stackTrace: s, + ); return false; } } - static int getThreshold({ - required String multisigConfig, - }) { + static int getThreshold({required String multisigConfig}) { try { - final threshold = multisigThreshold( - multisigConfig: multisigConfig, - ); + final threshold = multisigThreshold(multisigConfig: multisigConfig); return threshold; } catch (e, s) { @@ -70,7 +66,8 @@ abstract class Frost { String changeAddress, int feePerWeight, List inputs, - }) extractDataFromSignConfig({ + }) + extractDataFromSignConfig({ required String serializedKeys, required String signConfig, required CryptoCurrency coin, @@ -85,8 +82,9 @@ abstract class Frost { ); // get various data from config - final feePerWeight = - signFeePerWeight(signConfigPointer: signConfigPointer); + final feePerWeight = signFeePerWeight( + signConfigPointer: signConfigPointer, + ); final changeAddress = signChange(signConfigPointer: signConfigPointer); final recipientsCount = signPayments( signConfigPointer: signConfigPointer, @@ -103,15 +101,13 @@ abstract class Frost { signConfigPointer: signConfigPointer, index: i, ); - recipients.add( - ( - address: address, - amount: Amount( - rawValue: BigInt.from(amount), - fractionDigits: coin.fractionDigits, - ), + recipients.add(( + address: address, + amount: Amount( + rawValue: BigInt.from(amount), + fractionDigits: coin.fractionDigits, ), - ); + )); } // get utxos @@ -135,7 +131,11 @@ abstract class Frost { inputs: outputs, ); } catch (e, s) { - Logging.instance.f("extractDataFromSignConfig failed: ", error: e, stackTrace: s); + Logging.instance.f( + "extractDataFromSignConfig failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -156,7 +156,11 @@ abstract class Frost { return config; } catch (e, s) { - Logging.instance.f("createMultisigConfig failed: ", error: e, stackTrace: s); + Logging.instance.f( + "createMultisigConfig failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -166,10 +170,8 @@ abstract class Frost { String commitments, Pointer multisigConfigWithNamePtr, Pointer secretShareMachineWrapperPtr, - }) startKeyGeneration({ - required String multisigConfig, - required String myName, - }) { + }) + startKeyGeneration({required String multisigConfig, required String myName}) { try { final startKeyGenResPtr = startKeyGen( multisigConfig: multisigConfig, @@ -189,15 +191,17 @@ abstract class Frost { secretShareMachineWrapperPtr: machinePtr, ); } catch (e, s) { - Logging.instance.f("startKeyGeneration failed: ", error: e, stackTrace: s); + Logging.instance.f( + "startKeyGeneration failed: ", + error: e, + stackTrace: s, + ); rethrow; } } - static ({ - String share, - Pointer secretSharesResPtr, - }) generateSecretShares({ + static ({String share, Pointer secretSharesResPtr}) + generateSecretShares({ required Pointer multisigConfigWithNamePtr, required String mySeed, required Pointer secretShareMachineWrapperPtr, @@ -216,16 +220,17 @@ abstract class Frost { return (share: share, secretSharesResPtr: secretSharesResPtr); } catch (e, s) { - Logging.instance.f("generateSecretShares failed: ", error: e, stackTrace: s); + Logging.instance.f( + "generateSecretShares failed: ", + error: e, + stackTrace: s, + ); rethrow; } } - static ({ - Uint8List multisigId, - String recoveryString, - String serializedKeys, - }) completeKeyGeneration({ + static ({Uint8List multisigId, String recoveryString, String serializedKeys}) + completeKeyGeneration({ required Pointer multisigConfigWithNamePtr, required Pointer secretSharesResPtr, required List shares, @@ -254,7 +259,11 @@ abstract class Frost { serializedKeys: serializedKeys, ); } catch (e, s) { - Logging.instance.f("completeKeyGeneration failed: ", error: e, stackTrace: s); + Logging.instance.f( + "completeKeyGeneration failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -265,13 +274,14 @@ abstract class Frost { required String serializedKeys, required int network, required List< - ({ - UTXO utxo, - Uint8List scriptPubKey, - AddressDerivationData addressDerivationData - })> - inputs, - required List<({String address, Amount amount, bool isChange})> outputs, + ({ + UTXO utxo, + Uint8List scriptPubKey, + AddressDerivationData addressDerivationData, + }) + > + inputs, + required List outputs, required String changeAddress, required int feePerWeight, }) { @@ -279,17 +289,18 @@ abstract class Frost { final signConfig = newSignConfig( thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys), network: network, - outputs: inputs - .map( - (e) => Output( - hash: e.utxo.txid.toUint8ListFromHex, - vout: e.utxo.vout, - value: e.utxo.value, - scriptPubKey: e.scriptPubKey, - addressDerivationData: e.addressDerivationData, - ), - ) - .toList(), + outputs: + inputs + .map( + (e) => Output( + hash: e.utxo.txid.toUint8ListFromHex, + vout: e.utxo.vout, + value: e.utxo.value, + scriptPubKey: e.scriptPubKey, + addressDerivationData: e.addressDerivationData, + ), + ) + .toList(), paymentAddresses: outputs.map((e) => e.address).toList(), paymentAmounts: outputs.map((e) => e.amount.raw.toInt()).toList(), change: changeAddress, @@ -306,7 +317,8 @@ abstract class Frost { static ({ Pointer machinePtr, String preprocess, - }) attemptSignConfig({ + }) + attemptSignConfig({ required int network, required String config, required String serializedKeys, @@ -333,7 +345,8 @@ abstract class Frost { static ({ Pointer machinePtr, String share, - }) continueSigning({ + }) + continueSigning({ required Pointer machinePtr, required List preprocesses, }) { @@ -358,10 +371,7 @@ abstract class Frost { required List shares, }) { try { - final rawTransaction = completeSign( - machine: machinePtr, - shares: shares, - ); + final rawTransaction = completeSign(machine: machinePtr, shares: shares); return rawTransaction; } catch (e, s) { @@ -404,28 +414,24 @@ abstract class Frost { return config; } catch (e, s) { - Logging.instance.f("createResharerConfig failed: ", error: e, stackTrace: s); + Logging.instance.f( + "createResharerConfig failed: ", + error: e, + stackTrace: s, + ); rethrow; } } - static ({ - String resharerStart, - Pointer machine, - }) beginResharer({ - required String serializedKeys, - required String config, - }) { + static ({String resharerStart, Pointer machine}) + beginResharer({required String serializedKeys, required String config}) { try { final result = startResharer( serializedKeys: serializedKeys, config: config, ); - return ( - resharerStart: result.encoded, - machine: result.machine, - ); + return (resharerStart: result.encoded, machine: result.machine); } catch (e, s) { Logging.instance.f("beginResharer failed: ", error: e, stackTrace: s); rethrow; @@ -433,10 +439,8 @@ abstract class Frost { } /// expects [resharerStarts] of length equal to resharers. - static ({ - String resharedStart, - Pointer prior, - }) beginReshared({ + static ({String resharedStart, Pointer prior}) + beginReshared({ required String myName, required String resharerConfig, required List resharerStarts, @@ -448,10 +452,7 @@ abstract class Frost { resharerConfig: resharerConfig, resharerStarts: resharerStarts, ); - return ( - resharedStart: result.encoded, - prior: result.machine, - ); + return (resharedStart: result.encoded, prior: result.machine); } catch (e, s) { Logging.instance.f("beginReshared failed: ", error: e, stackTrace: s); rethrow; @@ -476,11 +477,8 @@ abstract class Frost { } /// expects [resharerCompletes] of length equal to resharers - static ({ - String multisigConfig, - String serializedKeys, - String resharedId, - }) finishReshared({ + static ({String multisigConfig, String serializedKeys, String resharedId}) + finishReshared({ required StartResharedRes prior, required List resharerCompletes, }) { @@ -504,7 +502,11 @@ abstract class Frost { return config; } catch (e, s) { - Logging.instance.f("decodedResharerConfig failed: ", error: e, stackTrace: s); + Logging.instance.f( + "decodedResharerConfig failed: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -513,9 +515,8 @@ abstract class Frost { int newThreshold, Map resharers, List newParticipants, - }) extractResharerConfigData({ - required String rConfig, - }) { + }) + extractResharerConfigData({required String rConfig}) { final decoded = _decodeRConfigWithResharers(rConfig); final resharerConfig = decoded.config; @@ -564,8 +565,9 @@ abstract class Frost { for (final resharer in resharers) { resharersMap[decoded.resharers.entries - .firstWhere((e) => e.value == resharer) - .key] = resharer; + .firstWhere((e) => e.value == resharer) + .key] = + resharer; } return ( @@ -574,28 +576,25 @@ abstract class Frost { newParticipants: newParticipants, ); } catch (e, s) { - Logging.instance.f("extractResharerConfigData failed: ", error: e, stackTrace: s); + Logging.instance.f( + "extractResharerConfigData failed: ", + error: e, + stackTrace: s, + ); rethrow; } } - static String encodeRConfig( - String config, - Map resharers, - ) { + static String encodeRConfig(String config, Map resharers) { return base64Encode("$config@${jsonEncode(resharers)}".toUint8ListFromUtf8); } - static String decodeRConfig( - String rConfig, - ) { + static String decodeRConfig(String rConfig) { return base64Decode(rConfig).toUtf8String.split("@").first; } static ({Map resharers, String config}) - _decodeRConfigWithResharers( - String rConfig, - ) { + _decodeRConfigWithResharers(String rConfig) { final parts = base64Decode(rConfig).toUtf8String.split("@"); final config = parts[0]; diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index d912f8ff0..8f60a3d6f 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -115,9 +115,7 @@ final class MwebdService { }); } - Future init(CryptoCurrencyNetwork net) async { - if (net == CryptoCurrencyNetwork.test) return; - + Future initService(CryptoCurrencyNetwork net) async { Logging.instance.i("MwebdService init($net) called..."); await _updateLock.protect(() async { if (_map[net] != null) { @@ -125,6 +123,22 @@ final class MwebdService { return; } + if (_map.isNotEmpty) { + for (final old in _map.values) { + try { + await old.client.cleanup(); + await old.server.stopServer(); + } catch (e, s) { + Logging.instance.i( + "Switching mwebd chain. Error likely expected here.", + error: e, + stackTrace: s, + ); + } + } + _map.clear(); + } + final port = await _getRandomUnusedPort(); if (port == null) { @@ -211,3 +225,200 @@ Future _getRandomUnusedPort({Set excluded = const {}}) async { return null; } + +// final class MwebdService { +// static String defaultPeer(CryptoCurrencyNetwork net) => switch (net) { +// CryptoCurrencyNetwork.main => "litecoin.stackwallet.com:9333", +// CryptoCurrencyNetwork.test => "litecoin.stackwallet.com:19335", +// CryptoCurrencyNetwork.stage => throw UnimplementedError(), +// CryptoCurrencyNetwork.test4 => throw UnimplementedError(), +// }; +// +// final Map +// _map = {}; +// +// late final StreamSubscription +// _torStatusListener; +// late final StreamSubscription +// _torPreferenceListener; +// +// final Mutex _torConnectingLock = Mutex(); +// +// static final instance = MwebdService._(); +// +// MwebdService._() { +// final bus = GlobalEventBus.instance; +// +// // Listen for tor status changes. +// _torStatusListener = bus.on().listen(( +// event, +// ) async { +// switch (event.newStatus) { +// case TorConnectionStatus.connecting: +// if (!_torConnectingLock.isLocked) { +// await _torConnectingLock.acquire(); +// } +// break; +// +// case TorConnectionStatus.connected: +// case TorConnectionStatus.disconnected: +// if (_torConnectingLock.isLocked) { +// _torConnectingLock.release(); +// } +// break; +// } +// }); +// +// // Listen for tor preference changes. +// _torPreferenceListener = bus.on().listen(( +// event, +// ) async { +// if (Prefs.instance.useTor) { +// return await _torConnectingLock.protect(() async { +// final proxyInfo = TorService.sharedInstance.getProxyInfo(); +// return await _update(proxyInfo); +// }); +// } else { +// return await _update(null); +// } +// }); +// } +// +// // locked while mweb servers and clients are updating +// final _updateLock = Mutex(); +// +// // update function called when Tor pref changed +// Future _update(({InternetAddress host, int port})? proxyInfo) async { +// await _updateLock.protect(() async { +// final proxy = +// proxyInfo == null +// ? "" +// : "${proxyInfo.host.address}:${proxyInfo.port}"; +// final nets = _map.keys; +// for (final net in nets) { +// final old = _map.remove(net)!; +// +// await old.client.cleanup(); +// await old.server.stopServer(); +// +// final port = await _getRandomUnusedPort(); +// if (port == null) { +// throw Exception("Could not find an unused port for mwebd"); +// } +// +// final newServer = MwebdServer( +// chain: old.server.chain, +// dataDir: old.server.dataDir, +// peer: old.server.peer, +// proxy: proxy, +// serverPort: port, +// ); +// await newServer.createServer(); +// await newServer.startServer(); +// +// final newClient = MwebClient.fromHost( +// "127.0.0.1", +// newServer.serverPort, +// ); +// +// _map[net] = (server: newServer, client: newClient); +// } +// }); +// } +// +// Future init(CryptoCurrencyNetwork net) async { +// if (net == CryptoCurrencyNetwork.test) return; +// +// Logging.instance.i("MwebdService init($net) called..."); +// await _updateLock.protect(() async { +// if (_map[net] != null) { +// Logging.instance.i("MwebdService init($net) was already called."); +// return; +// } +// +// final port = await _getRandomUnusedPort(); +// +// if (port == null) { +// throw Exception("Could not find an unused port for mwebd"); +// } +// +// final chain = switch (net) { +// CryptoCurrencyNetwork.main => "mainnet", +// CryptoCurrencyNetwork.test => "testnet", +// CryptoCurrencyNetwork.stage => throw UnimplementedError(), +// CryptoCurrencyNetwork.test4 => throw UnimplementedError(), +// }; +// +// final dir = await StackFileSystem.applicationMwebdDirectory(chain); +// +// final String proxy; +// if (Prefs.instance.useTor) { +// final proxyInfo = TorService.sharedInstance.getProxyInfo(); +// proxy = "${proxyInfo.host.address}:${proxyInfo.port}"; +// } else { +// proxy = ""; +// } +// +// final newServer = MwebdServer( +// chain: chain, +// dataDir: dir.path, +// peer: defaultPeer(net), +// proxy: proxy, +// serverPort: port, +// ); +// await newServer.createServer(); +// await newServer.startServer(); +// +// final newClient = MwebClient.fromHost("127.0.0.1", newServer.serverPort); +// +// _map[net] = (server: newServer, client: newClient); +// +// Logging.instance.i("MwebdService init($net) completed!"); +// }); +// } +// +// /// Get server status. Returns null if no server was initialized. +// Future getServerStatus(CryptoCurrencyNetwork net) async { +// return await _updateLock.protect(() async { +// return await _map[net]?.server.getStatus(); +// }); +// } +// +// /// Get client for network. Returns null if no server was initialized. +// Future getClient(CryptoCurrencyNetwork net) async { +// return await _updateLock.protect(() async { +// return _map[net]?.client; +// }); +// } +// } +// +// // ============================================================================ +// Future _getRandomUnusedPort({Set excluded = const {}}) async { +// const int minPort = 1024; +// const int maxPort = 65535; +// const int maxAttempts = 1000; +// +// final random = Random.secure(); +// +// for (int i = 0; i < maxAttempts; i++) { +// final int potentialPort = minPort + random.nextInt(maxPort - minPort + 1); +// +// if (excluded.contains(potentialPort)) { +// continue; +// } +// +// try { +// final ServerSocket socket = await ServerSocket.bind( +// InternetAddress.anyIPv4, +// potentialPort, +// ); +// await socket.close(); +// return potentialPort; +// } catch (_) { +// excluded.add(potentialPort); +// continue; +// } +// } +// +// return null; +// } diff --git a/lib/wallets/crypto_currency/coins/litecoin.dart b/lib/wallets/crypto_currency/coins/litecoin.dart index 4ab8ec0c2..1b830c4f9 100644 --- a/lib/wallets/crypto_currency/coins/litecoin.dart +++ b/lib/wallets/crypto_currency/coins/litecoin.dart @@ -91,6 +91,7 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { privHDPrefix: 0x0488ade4, pubHDPrefix: 0x0488b21e, bech32Hrp: "ltc", + mwebBech32Hrp: "ltcmweb", messagePrefix: '\x19Litecoin Signed Message:\n', minFee: BigInt.from(1), // Not used in stack wallet currently minOutput: dustLimit.raw, // Not used in stack wallet currently @@ -104,6 +105,7 @@ class Litecoin extends Bip39HDCurrency with ElectrumXCurrencyInterface { privHDPrefix: 0x04358394, pubHDPrefix: 0x043587cf, bech32Hrp: "tltc", + mwebBech32Hrp: "tmweb", messagePrefix: "\x19Litecoin Signed Message:\n", minFee: BigInt.from(1), // Not used in stack wallet currently minOutput: dustLimit.raw, // Not used in stack wallet currently diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index 6353a330a..bb2eb2cd1 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -7,13 +7,15 @@ import '../../db/drift/database.dart'; import '../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; +import '../../models/signing_data.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/enums/fee_rate_type_enum.dart'; import '../../widgets/eth_fee_form.dart'; import '../isar/models/spark_coin.dart'; import 'name_op_state.dart'; +import 'tx_recipient.dart'; -typedef TxRecipient = ({String address, Amount amount, bool isChange}); +export 'tx_recipient.dart'; class TxData { final FeeRateType? feeRateType; @@ -34,7 +36,7 @@ class TxData { final String? memo; final List? recipients; - final Set? utxos; + final Set? utxos; final List? usedUTXOs; final String? changeAddress; @@ -85,7 +87,6 @@ class TxData { // MWEB final bool isMweb; - final Set? mwebUtxos; final List? usedMwebUtxos; TxData({ @@ -123,7 +124,6 @@ class TxData { this.opNameState, this.sparkNameInfo, this.isMweb = false, - this.mwebUtxos, this.usedMwebUtxos, }); @@ -238,7 +238,7 @@ class TxData { String? noteOnChain, String? memo, String? otherData, - Set? utxos, + Set? utxos, List? usedUTXOs, List? recipients, String? frostMSConfig, @@ -273,7 +273,6 @@ class TxData { })? sparkNameInfo, bool? isMweb, - Set? mwebUtxos, List? usedMwebUtxos, }) { return TxData( @@ -313,7 +312,6 @@ class TxData { opNameState: opNameState ?? this.opNameState, sparkNameInfo: sparkNameInfo ?? this.sparkNameInfo, isMweb: isMweb ?? this.isMweb, - mwebUtxos: mwebUtxos ?? this.mwebUtxos, usedMwebUtxos: usedMwebUtxos ?? this.usedMwebUtxos, ); } @@ -354,7 +352,6 @@ class TxData { 'opNameState: $opNameState, ' 'sparkNameInfo: $sparkNameInfo, ' 'isMweb: $isMweb, ' - 'mwebUtxos: $mwebUtxos, ' 'usedMwebUtxos: $usedMwebUtxos, ' '}'; } diff --git a/lib/wallets/models/tx_recipient.dart b/lib/wallets/models/tx_recipient.dart index 8c5e9a9d4..8dd0c3011 100644 --- a/lib/wallets/models/tx_recipient.dart +++ b/lib/wallets/models/tx_recipient.dart @@ -1,11 +1,16 @@ +import '../../models/isar/models/blockchain_data/address.dart'; import '../../utilities/amount/amount.dart'; class TxRecipient { final String address; final Amount amount; + final bool isChange; + final AddressType? addressType; TxRecipient({ required this.address, required this.amount, + required this.isChange, + this.addressType, }); } diff --git a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart index 3b0c36ac0..33b6d3a0d 100644 --- a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart @@ -18,6 +18,7 @@ import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/paymint/fee_object_model.dart'; +import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../services/event_bus/global_event_bus.dart'; import '../../../services/frost.dart'; @@ -235,7 +236,10 @@ class BitcoinFrostWallet extends Wallet } } - return txData.copyWith(frostMSConfig: config, utxos: utxosToUse); + return txData.copyWith( + frostMSConfig: config, + utxos: utxosToUse.map((e) => StandardInput(e)).toSet(), + ); } catch (_) { rethrow; } @@ -676,11 +680,13 @@ class BitcoinFrostWallet extends Wallet Logging.instance.d("Sent txHash: $txHash"); // mark utxos as used - final usedUTXOs = txData.utxos!.map((e) => e.copyWith(used: true)); + final usedUTXOs = txData.utxos!.whereType().map( + (e) => e.utxo.copyWith(used: true), + ); await mainDB.putUTXOs(usedUTXOs.toList()); txData = txData.copyWith( - utxos: usedUTXOs.toSet(), + utxos: usedUTXOs.map((e) => StandardInput(e)).toSet(), txHash: txHash, txid: txHash, ); diff --git a/lib/wallets/wallet/impl/cardano_wallet.dart b/lib/wallets/wallet/impl/cardano_wallet.dart index 2cad7c514..5f4fdc37c 100644 --- a/lib/wallets/wallet/impl/cardano_wallet.dart +++ b/lib/wallets/wallet/impl/cardano_wallet.dart @@ -235,7 +235,7 @@ class CardanoWallet extends Bip39Wallet { // Check if we are sending all balance, which means no change and only one output for recipient. if (totalBalance == txData.amount!.raw) { final List newRecipients = [ - ( + TxRecipient( address: txData.recipients!.first.address, amount: Amount( rawValue: txData.amount!.raw - fee, diff --git a/lib/wallets/wallet/impl/epiccash_wallet.dart b/lib/wallets/wallet/impl/epiccash_wallet.dart index 215f41917..9032a0c82 100644 --- a/lib/wallets/wallet/impl/epiccash_wallet.dart +++ b/lib/wallets/wallet/impl/epiccash_wallet.dart @@ -631,8 +631,7 @@ class EpiccashWallet extends Bip39Wallet { throw Exception("Epic cash prepare send requires a single recipient!"); } - ({String address, Amount amount, bool isChange}) recipient = - txData.recipients!.first; + TxRecipient recipient = txData.recipients!.first; final int realFee = await _nativeFee(recipient.amount.raw.toInt()); final feeAmount = Amount( @@ -647,7 +646,7 @@ class EpiccashWallet extends Bip39Wallet { } if (info.cachedBalance.spendable == recipient.amount) { - recipient = ( + recipient = TxRecipient( address: recipient.address, amount: recipient.amount - feeAmount, isChange: recipient.isChange, diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index db22a5b55..c8b2673f6 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -13,6 +13,7 @@ import '../../../utilities/logger.dart'; import '../../crypto_currency/crypto_currency.dart'; import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../intermediate/bip39_hd_wallet.dart'; +import '../intermediate/external_wallet.dart'; import '../wallet_mixin_interfaces/coin_control_interface.dart'; import '../wallet_mixin_interfaces/electrumx_interface.dart'; import '../wallet_mixin_interfaces/extended_keys_interface.dart'; @@ -28,7 +29,8 @@ class LitecoinWallet CoinControlInterface, RbfInterface, OrdinalsInterface, - MwebInterface { + MwebInterface + implements ExternalWallet { @override int get isarTransactionVersion => 2; diff --git a/lib/wallets/wallet/impl/namecoin_wallet.dart b/lib/wallets/wallet/impl/namecoin_wallet.dart index a1970b974..5cee5ce22 100644 --- a/lib/wallets/wallet/impl/namecoin_wallet.dart +++ b/lib/wallets/wallet/impl/namecoin_wallet.dart @@ -579,7 +579,7 @@ class NamecoinWallet } TxData txData = TxData( - utxos: {utxo}, + utxos: {StandardInput(utxo)}, opNameState: NameOpState( name: data.name, saltHex: data.salt, @@ -593,7 +593,7 @@ class NamecoinWallet note: "Purchase $noteName", feeRateType: kNameTxDefaultFeeRate, // TODO: make configurable? recipients: [ - ( + TxRecipient( address: (await getCurrentReceivingAddress())!.value, isChange: false, amount: Amount( @@ -902,7 +902,7 @@ class NamecoinWallet if (customSatsPerVByte != null) { final result = await coinSelectionName( txData: txData.copyWith(feeRateAmount: BigInt.from(-1)), - utxos: utxos?.toList(), + utxos: utxos?.whereType().map((e) => e.utxo).toList(), coinControl: coinControl, ); @@ -940,7 +940,7 @@ class NamecoinWallet final result = await coinSelectionName( txData: txData.copyWith(feeRateAmount: rate), - utxos: utxos?.toList(), + utxos: utxos?.whereType().map((e) => e.utxo).toList(), coinControl: coinControl, ); @@ -1117,7 +1117,7 @@ class NamecoinWallet // gather required signing data final utxoSigningData = (await fetchBuildTxData( - utxoObjectsToUse, + utxoObjectsToUse.map((e) => StandardInput(e)).toList(), )).whereType().toList(); final int vSizeForOneOutput; diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index 53afa8df9..d5028093b 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -252,7 +252,7 @@ class TezosWallet extends Bip39Wallet { return txData.copyWith( recipients: [ - ( + TxRecipient( amount: sendAmount, address: txData.recipients!.first.address, isChange: txData.recipients!.first.isChange, diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart index e1c09b693..b632943d0 100644 --- a/lib/wallets/wallet/impl/wownero_wallet.dart +++ b/lib/wallets/wallet/impl/wownero_wallet.dart @@ -54,7 +54,7 @@ class WowneroWallet extends LibMoneroWallet { txData: TxData( recipients: [ // This address is only used for getting an approximate fee, never for sending - ( + TxRecipient( address: "WW3iVcnoAY6K9zNdU4qmdvZELefx6xZz4PMpTwUifRkvMQckyadhSPYMVPJhBdYE8P9c27fg9RPmVaWNFx1cDaj61HnetqBiy", amount: amount, diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart index 2605d40ca..cc11b48f2 100644 --- a/lib/wallets/wallet/impl/xelis_wallet.dart +++ b/lib/wallets/wallet/impl/xelis_wallet.dart @@ -416,7 +416,10 @@ class XelisWallet extends LibXelisWallet { asset: xelis_sdk.xelisAsset, ); - fee = Amount(rawValue: BigInt.zero, fractionDigits: cryptoCurrency.fractionDigits); + fee = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); outputs.add( OutputV2.isarCantDoRequiredInDefaultConstructor( @@ -477,7 +480,10 @@ class XelisWallet extends LibXelisWallet { asset: transfer.asset, ); - fee = Amount(rawValue: BigInt.zero, fractionDigits: cryptoCurrency.fractionDigits); + fee = Amount( + rawValue: BigInt.zero, + fractionDigits: cryptoCurrency.fractionDigits, + ); outputs.add( OutputV2.isarCantDoRequiredInDefaultConstructor( @@ -719,7 +725,7 @@ class XelisWallet extends LibXelisWallet { recipients.isNotEmpty ? recipients : [ - ( + TxRecipient( address: 'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m', amount: amount, diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index 82f3bce3c..763162fd0 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -21,6 +21,7 @@ import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; +import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; @@ -502,9 +503,10 @@ abstract class LibMoneroWallet final host = node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; ({InternetAddress host, int port})? proxy; - proxy = prefs.useTor && !node.forceNoTor - ? TorService.sharedInstance.getProxyInfo() - : null; + proxy = + prefs.useTor && !node.forceNoTor + ? TorService.sharedInstance.getProxyInfo() + : null; _setSyncStatus(lib_monero_compat.ConnectingSyncStatus()); try { @@ -991,7 +993,8 @@ abstract class LibMoneroWallet bool _torNodeMismatchGuard(NodeModel node) { _canPing = true; // Reset. - final bool mismatch = (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || + final bool mismatch = + (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || (!prefs.useTor && !node.clearnetEnabled && node.torEnabled); if (mismatch) { @@ -1290,7 +1293,7 @@ abstract class LibMoneroWallet } else { final totalInputsValue = txData.utxos! .map((e) => e.value) - .fold(BigInt.zero, (p, e) => p + BigInt.from(e)); + .fold(BigInt.zero, (p, e) => p + e); sweep = txData.amount!.raw == totalInputsValue; } @@ -1317,22 +1320,23 @@ abstract class LibMoneroWallet final height = await chainHeight; final inputs = txData.utxos - ?.map( + ?.whereType() + .map( (e) => lib_monero.Output( address: e.address!, - hash: e.txid, - keyImage: e.keyImage!, - value: BigInt.from(e.value), - isFrozen: e.isBlocked, + hash: e.utxo.txid, + keyImage: e.utxo.keyImage!, + value: e.value, + isFrozen: e.utxo.isBlocked, isUnlocked: - e.blockHeight != null && - (height - (e.blockHeight ?? 0)) >= + e.utxo.blockHeight != null && + (height - (e.utxo.blockHeight ?? 0)) >= cryptoCurrency.minConfirms, - height: e.blockHeight ?? 0, - vout: e.vout, - spent: e.used ?? false, + height: e.utxo.blockHeight ?? 0, + vout: e.utxo.vout, + spent: e.utxo.used ?? false, spentHeight: null, // doesn't matter here - coinbase: e.isCoinbase, + coinbase: e.utxo.isCoinbase, ), ) .toList(); diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index 7f7eea6f0..2c47a843d 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -19,6 +19,7 @@ import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; +import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; @@ -480,9 +481,10 @@ abstract class LibSalviumWallet final host = node.host.endsWith(".onion") ? node.host : Uri.parse(node.host).host; ({InternetAddress host, int port})? proxy; - proxy = prefs.useTor && !node.forceNoTor - ? TorService.sharedInstance.getProxyInfo() - : null; + proxy = + prefs.useTor && !node.forceNoTor + ? TorService.sharedInstance.getProxyInfo() + : null; _setSyncStatus(ConnectingSyncStatus()); try { @@ -956,7 +958,8 @@ abstract class LibSalviumWallet bool _torNodeMismatchGuard(NodeModel node) { _canPing = true; // Reset. - final bool mismatch = (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || + final bool mismatch = + (prefs.useTor && node.clearnetEnabled && !node.torEnabled) || (!prefs.useTor && !node.clearnetEnabled && node.torEnabled); if (mismatch) { @@ -1255,7 +1258,7 @@ abstract class LibSalviumWallet } else { final totalInputsValue = txData.utxos! .map((e) => e.value) - .fold(BigInt.zero, (p, e) => p + BigInt.from(e)); + .fold(BigInt.zero, (p, e) => p + e); sweep = txData.amount!.raw == totalInputsValue; } @@ -1282,22 +1285,23 @@ abstract class LibSalviumWallet final height = await chainHeight; final inputs = txData.utxos - ?.map( + ?.whereType() + .map( (e) => lib_salvium.Output( - address: e.address!, - hash: e.txid, - keyImage: e.keyImage!, - value: BigInt.from(e.value), - isFrozen: e.isBlocked, + address: e.utxo.address!, + hash: e.utxo.txid, + keyImage: e.utxo.keyImage!, + value: e.value, + isFrozen: e.utxo.isBlocked, isUnlocked: - e.blockHeight != null && - (height - (e.blockHeight ?? 0)) >= + e.utxo.blockHeight != null && + (height - (e.utxo.blockHeight ?? 0)) >= cryptoCurrency.minConfirms, - height: e.blockHeight ?? 0, - vout: e.vout, - spent: e.used ?? false, + height: e.utxo.blockHeight ?? 0, + vout: e.utxo.vout, + spent: e.utxo.used ?? false, spentHeight: null, // doesn't matter here - coinbase: e.isCoinbase, + coinbase: e.utxo.isCoinbase, ), ) .toList(); diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index c2bfa5b41..554e04313 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -431,20 +431,24 @@ abstract class Wallet { hasNetwork ? NodeConnectionStatus.connected : NodeConnectionStatus.disconnected; - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent(status, walletId, cryptoCurrency), - ); + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + NodeConnectionStatusChangedEvent(status, walletId, cryptoCurrency), + ); + } _isConnected = hasNetwork; if (status == NodeConnectionStatus.disconnected) { - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - cryptoCurrency, - ), - ); + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + cryptoCurrency, + ), + ); + } } if (hasNetwork) { @@ -511,19 +515,22 @@ abstract class Wallet { return node; } + bool doNotFireRefreshEvents = false; + // Should fire events Future refresh() async { final refreshCompleter = Completer(); final future = refreshCompleter.future.then( (_) { - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.synced, - walletId, - cryptoCurrency, - ), - ); - + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.synced, + walletId, + cryptoCurrency, + ), + ); + } if (shouldAutoSync) { _periodicRefreshTimer ??= Timer.periodic(const Duration(seconds: 150), ( timer, @@ -541,20 +548,22 @@ abstract class Wallet { } }, onError: (Object e, StackTrace s) { - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - NodeConnectionStatus.disconnected, - walletId, - cryptoCurrency, - ), - ); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - cryptoCurrency, - ), - ); + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + NodeConnectionStatusChangedEvent( + NodeConnectionStatus.disconnected, + walletId, + cryptoCurrency, + ), + ); + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + cryptoCurrency, + ), + ); + } Logging.instance.e( "Caught exception in refreshWalletData()", error: e, @@ -572,7 +581,11 @@ abstract class Wallet { if (this is ElectrumXInterface) { (this as ElectrumXInterface?)?.refreshingPercent = percent; } - GlobalEventBus.instance.fire(RefreshPercentChangedEvent(percent, walletId)); + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + RefreshPercentChangedEvent(percent, walletId), + ); + } } // Should fire events @@ -593,13 +606,15 @@ abstract class Wallet { // Slight possibility of race but should be irrelevant await refreshMutex.acquire(); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.syncing, - walletId, - cryptoCurrency, - ), - ); + if (!doNotFireRefreshEvents) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.syncing, + walletId, + cryptoCurrency, + ), + ); + } // add some small buffer before making calls. // this can probably be removed in the future but was added as a diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 6a505c60c..877cb0783 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -6,6 +6,7 @@ import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; import 'package:isar/isar.dart'; import 'package:meta/meta.dart'; +import '../../../db/drift/database.dart'; import '../../../electrumx_rpc/cached_electrumx_client.dart'; import '../../../electrumx_rpc/client_manager.dart'; import '../../../electrumx_rpc/electrumx_client.dart'; @@ -32,6 +33,7 @@ import '../impl/firo_wallet.dart'; import '../impl/peercoin_wallet.dart'; import '../intermediate/bip39_hd_wallet.dart'; import 'cpfp_interface.dart'; +import 'mweb_interface.dart'; import 'paynym_interface.dart'; import 'rbf_interface.dart'; import 'view_only_option_interface.dart'; @@ -76,29 +78,33 @@ mixin ElectrumXInterface return false; } - Future> - helperRecipientsConvert(List addrs, List satValues) async { - final List<({String address, Amount amount, bool isChange})> results = []; + Future> helperRecipientsConvert( + List addrs, + List satValues, + ) async { + final List results = []; for (int i = 0; i < addrs.length; i++) { - results.add(( - address: addrs[i], - amount: Amount( - rawValue: satValues[i], - fractionDigits: cryptoCurrency.fractionDigits, + results.add( + TxRecipient( + address: addrs[i], + amount: Amount( + rawValue: satValues[i], + fractionDigits: cryptoCurrency.fractionDigits, + ), + isChange: + (await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .subTypeEqualTo(AddressSubType.change) + .and() + .valueEqualTo(addrs[i]) + .valueProperty() + .findFirst()) != + null, ), - isChange: - (await mainDB.isar.addresses - .where() - .walletIdEqualTo(walletId) - .filter() - .subTypeEqualTo(AddressSubType.change) - .and() - .valueEqualTo(addrs[i]) - .valueProperty() - .findFirst()) != - null, - )); + ); } return results; @@ -110,7 +116,7 @@ mixin ElectrumXInterface required bool isSendAll, required bool isSendAllCoinControlUtxos, int additionalOutputs = 0, - List? utxos, + List? utxos, }) async { Logging.instance.d("Starting coinSelection ----------"); @@ -126,29 +132,44 @@ mixin ElectrumXInterface final int? satsPerVByte = txData.satsPerVByte; final selectedTxFeeRate = txData.feeRateAmount!; - final List availableOutputs = - utxos ?? await mainDB.getUTXOs(walletId).findAll(); + final List availableOutputs = + utxos ?? + (await mainDB.getUTXOs(walletId).findAll()) + .map((e) => StandardInput(e)) + .toList(); + if (this is MwebInterface && utxos == null) { + final db = Drift.get(walletId); + final mwebUtxos = + await (db.select(db.mwebUtxos) + ..where((e) => e.used.equals(false))).get(); + + availableOutputs.addAll(mwebUtxos.map((e) => MwebInput(e))); + } + final currentChainHeight = await chainHeight; final canCPFP = this is CpfpInterface && coinControl; final spendableOutputs = - availableOutputs - .where( - (e) => - !e.isBlocked && - (e.used != true) && - (canCPFP || - e.isConfirmed( - currentChainHeight, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - )), - ) - .toList(); + availableOutputs.where((e) { + if (e is StandardInput) { + return !e.utxo.isBlocked && + (e.utxo.used != true) && + (canCPFP || + e.utxo.isConfirmed( + currentChainHeight, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + )); + } else if (e is MwebInput) { + return !e.utxo.blocked && !e.utxo.used; + } else { + return false; + } + }).toList(); final spendableSatoshiValue = spendableOutputs.fold( BigInt.zero, - (p, e) => p + BigInt.from(e.value), + (p, e) => p + e.value, ); if (spendableSatoshiValue < satoshiAmountToSend) { @@ -181,7 +202,7 @@ mixin ElectrumXInterface BigInt satoshisBeingUsed = BigInt.zero; int inputsBeingConsumed = 0; - final List utxoObjectsToUse = []; + final List utxoObjectsToUse = []; if (!coinControl) { for ( @@ -190,7 +211,7 @@ mixin ElectrumXInterface i++ ) { utxoObjectsToUse.add(spendableOutputs[i]); - satoshisBeingUsed += BigInt.from(spendableOutputs[i].value); + satoshisBeingUsed += spendableOutputs[i].value; inputsBeingConsumed += 1; } for ( @@ -199,9 +220,7 @@ mixin ElectrumXInterface i++ ) { utxoObjectsToUse.add(spendableOutputs[inputsBeingConsumed]); - satoshisBeingUsed += BigInt.from( - spendableOutputs[inputsBeingConsumed].value, - ); + satoshisBeingUsed += spendableOutputs[inputsBeingConsumed].value; inputsBeingConsumed += 1; } } else { @@ -507,25 +526,32 @@ mixin ElectrumXInterface ); } - Future> fetchBuildTxData(List utxosToUse) async { + Future> fetchBuildTxData(List utxosToUse) async { // return data - final List signingData = []; + final List signingData = []; try { // Populating the addresses to check for (var i = 0; i < utxosToUse.length; i++) { - final derivePathType = cryptoCurrency.addressType( - address: utxosToUse[i].address!, - ); + final input = utxosToUse[i]; + if (input is MwebInput) { + signingData.add(input); + } else if (input is StandardInput) { + final derivePathType = cryptoCurrency.addressType( + address: input.address!, + ); - signingData.add( - StandardInput(utxosToUse[i], derivePathType: derivePathType), - ); + signingData.add( + StandardInput(input.utxo, derivePathType: derivePathType), + ); + } else { + throw Exception("Unknown input type ${input.runtimeType}"); + } } final root = await getRootHDNode(); - for (final sd in signingData) { + for (final sd in signingData.whereType()) { coinlib.HDPrivateKey? keys; final address = await mainDB.getAddress(walletId, sd.utxo.address!); if (address?.derivationPath != null) { @@ -587,8 +613,16 @@ mixin ElectrumXInterface final List prevOuts = []; + final hasMwebInputs = utxoSigningData.whereType().isNotEmpty; + final hasMwebOutputs = + txData.recipients! + .where((e) => e.addressType == AddressType.mweb) + .isNotEmpty; + + final isMweb = hasMwebOutputs || hasMwebInputs; + coinlib.Transaction clTx = coinlib.Transaction( - version: cryptoCurrency.transactionVersion, + version: isMweb ? 2 : cryptoCurrency.transactionVersion, inputs: [], outputs: [], ); @@ -599,88 +633,125 @@ mixin ElectrumXInterface ? 0xffffffff - 10 : 0xffffffff - 1; - final standardInputs = utxoSigningData.whereType().toList(); - // Add transaction inputs - for (var i = 0; i < standardInputs.length; i++) { - final txid = standardInputs[i].utxo.txid; + for (var i = 0; i < utxoSigningData.length; i++) { + final data = utxoSigningData[i]; + if (data is MwebInput) { + final address = data.address; + + final addr = await mainDB.getAddress(walletId, address); + final index = addr!.derivationIndex; + + final input = coinlib.RawInput( + prevOut: coinlib.OutPoint( + Uint8List.fromList( + data.utxo.outputId.toUint8ListFromHex.reversed.toList(), + ), + index, + ), + scriptSig: Uint8List(0), + ); - final hash = Uint8List.fromList( - txid.toUint8ListFromHex.reversed.toList(), - ); + clTx = clTx.addInput(input); - final prevOutpoint = coinlib.OutPoint(hash, standardInputs[i].utxo.vout); + tempInputs.add( + InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: input.scriptSig.toHex, + scriptSigAsm: null, + sequence: sequence, + outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( + txid: data.utxo.outputId, + vout: index, + ), + addresses: [address], + valueStringSats: utxoSigningData[i].value.toString(), + witness: null, + innerRedeemScriptAsm: null, + coinbase: null, + walletOwns: true, + ), + ); + } else if (data is StandardInput) { + final txid = data.utxo.txid; - final prevOutput = coinlib.Output.fromAddress( - BigInt.from(standardInputs[i].utxo.value), - coinlib.Address.fromString( - standardInputs[i].utxo.address!, - cryptoCurrency.networkParams, - ), - ); + final hash = Uint8List.fromList( + txid.toUint8ListFromHex.reversed.toList(), + ); - prevOuts.add(prevOutput); + final prevOutpoint = coinlib.OutPoint(hash, data.utxo.vout); - final coinlib.Input input; + final prevOutput = coinlib.Output.fromAddress( + BigInt.from(data.utxo.value), + coinlib.Address.fromString( + data.utxo.address!, + cryptoCurrency.networkParams, + ), + ); - switch (standardInputs[i].derivePathType) { - case DerivePathType.bip44: - case DerivePathType.bch44: - input = coinlib.P2PKHInput( - prevOut: prevOutpoint, - publicKey: standardInputs[i].key!.publicKey, - sequence: sequence, - ); + prevOuts.add(prevOutput); - // TODO: fix this as it is (probably) wrong! - case DerivePathType.bip49: - throw Exception("TODO p2sh"); - // input = coinlib.P2SHMultisigInput( - // prevOut: prevOutpoint, - // program: coinlib.MultisigProgram.decompile( - // standardInputs[i].redeemScript!, - // ), - // sequence: sequence, - // ); - - case DerivePathType.bip84: - input = coinlib.P2WPKHInput( - prevOut: prevOutpoint, - publicKey: standardInputs[i].key!.publicKey, - sequence: sequence, - ); + final coinlib.Input input; - case DerivePathType.bip86: - input = coinlib.TaprootKeyInput(prevOut: prevOutpoint); + switch (data.derivePathType) { + case DerivePathType.bip44: + case DerivePathType.bch44: + input = coinlib.P2PKHInput( + prevOut: prevOutpoint, + publicKey: data.key!.publicKey, + sequence: sequence, + ); - default: - throw UnsupportedError( - "Unknown derivation path type found: ${standardInputs[i].derivePathType}", - ); - } + // TODO: fix this as it is (probably) wrong! + case DerivePathType.bip49: + throw Exception("TODO p2sh"); + // input = coinlib.P2SHMultisigInput( + // prevOut: prevOutpoint, + // program: coinlib.MultisigProgram.decompile( + // data.redeemScript!, + // ), + // sequence: sequence, + // ); + + case DerivePathType.bip84: + input = coinlib.P2WPKHInput( + prevOut: prevOutpoint, + publicKey: data.key!.publicKey, + sequence: sequence, + ); - clTx = clTx.addInput(input); + case DerivePathType.bip86: + input = coinlib.TaprootKeyInput(prevOut: prevOutpoint); - tempInputs.add( - InputV2.isarCantDoRequiredInDefaultConstructor( - scriptSigHex: input.scriptSig.toHex, - scriptSigAsm: null, - sequence: sequence, - outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: standardInputs[i].utxo.txid, - vout: standardInputs[i].utxo.vout, + default: + throw UnsupportedError( + "Unknown derivation path type found: ${data.derivePathType}", + ); + } + + clTx = clTx.addInput(input); + + tempInputs.add( + InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: input.scriptSig.toHex, + scriptSigAsm: null, + sequence: sequence, + outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( + txid: data.utxo.txid, + vout: data.utxo.vout, + ), + addresses: data.utxo.address == null ? [] : [data.utxo.address!], + valueStringSats: data.utxo.value.toString(), + witness: null, + innerRedeemScriptAsm: null, + coinbase: null, + walletOwns: true, ), - addresses: - standardInputs[i].utxo.address == null - ? [] - : [standardInputs[i].utxo.address!], - valueStringSats: standardInputs[i].utxo.value.toString(), - witness: null, - innerRedeemScriptAsm: null, - coinbase: null, - walletOwns: true, - ), - ); + ); + } else { + throw Exception( + "Unknown input type: ${utxoSigningData[i].runtimeType}", + ); + } } // Add transaction output @@ -702,10 +773,18 @@ mixin ElectrumXInterface rethrow; } } - final output = coinlib.Output.fromAddress( - txData.recipients![i].amount.raw, - address, - ); + final coinlib.Output output; + if (address is coinlib.MwebAddress) { + output = coinlib.Output.fromProgram( + txData.recipients![i].amount.raw, + address.program, + ); + } else { + output = coinlib.Output.fromAddress( + txData.recipients![i].amount.raw, + address, + ); + } clTx = clTx.addOutput(output); @@ -729,33 +808,40 @@ mixin ElectrumXInterface try { // Sign the transaction accordingly - for (var i = 0; i < standardInputs.length; i++) { - final value = BigInt.from(standardInputs[i].utxo.value); - final key = standardInputs[i].key!.privateKey!; - - if (clTx.inputs[i] is coinlib.TaprootKeyInput) { - final taproot = coinlib.Taproot( - internalKey: standardInputs[i].key!.publicKey, - ); - - clTx = clTx.signTaproot( - inputN: i, - key: taproot.tweakPrivateKey(key), - prevOuts: prevOuts, - ); - } else if (clTx.inputs[i] is coinlib.LegacyWitnessInput) { - clTx = clTx.signLegacyWitness(inputN: i, key: key, value: value); - } else if (clTx.inputs[i] is coinlib.LegacyInput) { - clTx = clTx.signLegacy(inputN: i, key: key); - } else if (clTx.inputs[i] is coinlib.TaprootSingleScriptSigInput) { - clTx = clTx.signTaprootSingleScriptSig( - inputN: i, - key: key, - prevOuts: prevOuts, - ); + for (var i = 0; i < utxoSigningData.length; i++) { + final data = utxoSigningData[i]; + + if (data is MwebInput) { + // do nothing + } else if (data is StandardInput) { + final value = BigInt.from(data.utxo.value); + final key = data.key!.privateKey!; + if (clTx.inputs[i] is coinlib.TaprootKeyInput) { + final taproot = coinlib.Taproot(internalKey: data.key!.publicKey); + + clTx = clTx.signTaproot( + inputN: i, + key: taproot.tweakPrivateKey(key), + prevOuts: prevOuts, + ); + } else if (clTx.inputs[i] is coinlib.LegacyWitnessInput) { + clTx = clTx.signLegacyWitness(inputN: i, key: key, value: value); + } else if (clTx.inputs[i] is coinlib.LegacyInput) { + clTx = clTx.signLegacy(inputN: i, key: key); + } else if (clTx.inputs[i] is coinlib.TaprootSingleScriptSigInput) { + clTx = clTx.signTaprootSingleScriptSig( + inputN: i, + key: key, + prevOuts: prevOuts, + ); + } else { + throw Exception( + "Unable to sign input of type ${clTx.inputs[i].runtimeType}", + ); + } } else { throw Exception( - "Unable to sign input of type ${clTx.inputs[i].runtimeType}", + "Unknown input type: ${utxoSigningData[i].runtimeType}", ); } } @@ -769,6 +855,7 @@ mixin ElectrumXInterface } return txData.copyWith( + isMweb: isMweb, raw: clTx.toHex(), // dirty shortcut for peercoin's weirdness vSize: this is PeercoinWallet ? clTx.size : clTx.vSize(), @@ -1707,9 +1794,7 @@ mixin ElectrumXInterface final isSendAllCoinControlUtxos = coinControl && txData.amount!.raw == - utxos - .map((e) => e.value) - .fold(BigInt.zero, (p, e) => p + BigInt.from(e)); + utxos.map((e) => e.value).fold(BigInt.zero, (p, e) => p + e); if (customSatsPerVByte != null) { // check for send all @@ -1789,6 +1874,26 @@ mixin ElectrumXInterface ); } + // mweb + if (result.isMweb) { + final mwebData = await coinSelection( + txData: result.copyWith( + recipients: + result.recipients! + .where( + (e) => + !(e.isChange && e.addressType == AddressType.mweb), + ) + .toList(), + ), + coinControl: coinControl, + isSendAll: isSendAll, + isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, + ); + + return await (this as MwebInterface).processMwebTransaction(mwebData); + } + return result; } else { throw ArgumentError("Invalid fee rate argument provided!"); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index f812faba8..61ac5f030 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -2,10 +2,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; +import 'package:coinlib_flutter/coinlib_flutter.dart' as cl; import 'package:drift/drift.dart'; import 'package:fixnum/fixnum.dart'; import 'package:isar/isar.dart'; -import 'package:meta/meta.dart'; import 'package:mweb_client/mweb_client.dart'; import '../../../db/drift/database.dart'; @@ -13,21 +13,25 @@ import '../../../models/balance.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; +import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../services/event_bus/global_event_bus.dart'; import '../../../services/mwebd_service.dart'; import '../../../utilities/amount/amount.dart'; +import '../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../utilities/extensions/extensions.dart'; import '../../../utilities/logger.dart'; import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../../isar/models/wallet_info.dart'; import '../../models/tx_data.dart'; +import '../intermediate/external_wallet.dart'; import 'electrumx_interface.dart'; mixin MwebInterface - on ElectrumXInterface { + on ElectrumXInterface + implements ExternalWallet { // TODO StreamSubscription? _mwebUtxoSubscription; @@ -45,10 +49,25 @@ mixin MwebInterface .walletIdEqualTo(walletId) .filter() .typeEqualTo(AddressType.mweb) + .and() + .subTypeEqualTo(AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst(); } + Future getMwebChangeAddress() async { + return await mainDB.isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.mweb) + .and() + .subTypeEqualTo(AddressSubType.change) + .and() + .derivationIndexEqualTo(0) + .findFirst(); + } + Future get _client async { final client = await MwebdService.instance.getClient( cryptoCurrency.network, @@ -59,7 +78,23 @@ mixin MwebInterface return client; } - WalletSyncStatus? _syncStatus; + WalletSyncStatus? _syncStatusMwebCache; + WalletSyncStatus? get _syncStatusMweb => _syncStatusMwebCache; + set _syncStatusMweb(WalletSyncStatus? newValue) { + switch (newValue) { + case null: + doNotFireRefreshEvents = true; + case WalletSyncStatus.unableToSync: + doNotFireRefreshEvents = true; + case WalletSyncStatus.synced: + doNotFireRefreshEvents = false; + case WalletSyncStatus.syncing: + doNotFireRefreshEvents = true; + } + + _syncStatusMwebCache = newValue; + } + Timer? _mwebdPolling; int currentKnownChainHeight = 0; double highestPercentCached = 0; @@ -124,7 +159,7 @@ mixin MwebInterface syncStatus = WalletSyncStatus.synced; } - _syncStatus = syncStatus; + _syncStatusMweb = syncStatus; GlobalEventBus.instance.fire( WalletSyncStatusChangedEvent(syncStatus, walletId, info.coin), ); @@ -134,9 +169,9 @@ mixin MwebInterface error: e, stackTrace: s, ); - _syncStatus = WalletSyncStatus.unableToSync; + _syncStatusMweb = WalletSyncStatus.unableToSync; GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent(_syncStatus!, walletId, info.coin), + WalletSyncStatusChangedEvent(_syncStatusMweb!, walletId, info.coin), ); } }); @@ -260,7 +295,7 @@ mixin MwebInterface cryptoCurrency.network, ); if (status == null) { - await MwebdService.instance.init(cryptoCurrency.network); + await MwebdService.instance.initService(cryptoCurrency.network); } _startPollingMwebd(); @@ -269,16 +304,23 @@ mixin MwebInterface } } - Future
      generateNextMwebAddress() async { + /// [isChange] will always return the change address at index 0 !!!!! + Future
      generateNextMwebAddress({bool isChange = false}) async { if (!info.isMwebEnabled) { throw Exception( "Tried calling generateNextMwebAddress with mweb disabled for $walletId ${info.name}", ); } - final highestStoredIndex = - (await getCurrentReceivingMwebAddress())?.derivationIndex ?? -1; - final nextIndex = highestStoredIndex + 1; + final int nextIndex; + if (isChange) { + nextIndex = 0; + } else { + final highestStoredIndex = + (await getCurrentReceivingMwebAddress())?.derivationIndex ?? 0; + + nextIndex = highestStoredIndex + 1; + } final client = await _client; @@ -295,31 +337,12 @@ mixin MwebInterface derivationIndex: nextIndex, derivationPath: null, type: AddressType.mweb, - subType: AddressSubType.receiving, + subType: isChange ? AddressSubType.change : AddressSubType.receiving, ); } - Future estimateFeeForMweb(Amount amount) async { - if (!info.isMwebEnabled) { - throw Exception( - "Tried calling estimateFeeForMweb with mweb disabled for $walletId ${info.name}", - ); - } - throw UnimplementedError(); - } - - Future prepareSendMweb({required TxData txData}) async { - if (!info.isMwebEnabled) { - throw Exception( - "Tried calling prepareSendMweb with mweb disabled for $walletId ${info.name}", - ); - } - if (!txData.isMweb) { - throw Exception("Invalid mweb flagged tx data"); - } - + Future processMwebTransaction(TxData txData) async { final client = await _client; - final response = await client.create( CreateRequest( rawTx: txData.raw!.toUint8ListFromHex, @@ -333,19 +356,23 @@ mixin MwebInterface return txData.copyWith(raw: Uint8List.fromList(response.rawTx).toHex); } - Future confirmSendMweb({required TxData txData}) async { + Future _confirmSendMweb({required TxData txData}) async { if (!info.isMwebEnabled) { throw Exception( - "Tried calling confirmSendMweb with mweb disabled for $walletId ${info.name}", + "Tried calling _confirmSendMweb with mweb disabled for $walletId ${info.name}", ); } try { - Logging.instance.d("confirmSend txData: $txData"); + Logging.instance.d("_confirmSendMweb txData: $txData"); - final txHash = await electrumXClient.broadcastTransaction( - rawTx: txData.raw!, + final client = await _client; + + final response = await client.broadcast( + BroadcastRequest(rawTx: txData.raw!.toUint8ListFromHex), ); + + final txHash = response.txid; Logging.instance.d("Sent txHash: $txHash"); txData = txData.copyWith(txHash: txHash, txid: txHash); @@ -371,7 +398,7 @@ mixin MwebInterface return await updateSentCachedTxData(txData: txData); } catch (e, s) { Logging.instance.e( - "Exception rethrown from confirmSendMweb(): ", + "Exception rethrown from _confirmSendMweb(): ", error: e, stackTrace: s, ); @@ -416,11 +443,34 @@ mixin MwebInterface } // TODO finish - final txData = await prepareSendMweb( - txData: TxData(utxos: spendableUtxos.toSet()), + final txData = await prepareSend( + txData: TxData( + isMweb: true, + feeRateType: FeeRateType.average, + utxos: spendableUtxos.map((e) => StandardInput(e)).toSet(), + recipients: [ + TxRecipient( + address: (await getCurrentReceivingMwebAddress())!.value, + amount: spendableUtxos.fold( + Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits), + (p, e) => + p + + Amount( + rawValue: BigInt.from(e.value), + fractionDigits: cryptoCurrency.fractionDigits, + ), + ), + + isChange: false, + addressType: AddressType.mweb, + ), + ], + ), ); - await confirmSendMweb(txData: txData); + final processed = await processMwebTransaction(txData); + + await _confirmSendMweb(txData: processed); } catch (e, s) { Logging.instance.w( "Exception caught in anonymizeAllMweb(): ", @@ -431,19 +481,71 @@ mixin MwebInterface } } + Future _checkSpentMwebUtxos() async { + try { + final db = Drift.get(walletId); + final mwebUtxos = + await (db.select(db.mwebUtxos) + ..where((e) => e.used.equals(false))).get(); + + final client = await _client; + + final spent = await client.spent( + SpentRequest(outputId: mwebUtxos.map((e) => e.outputId)), + ); + + final updated = mwebUtxos.where( + (e) => spent.outputId.contains(e.outputId), + ); + + await db.transaction(() async { + for (final utxo in updated) { + await db + .into(db.mwebUtxos) + .insertOnConflictUpdate( + utxo.toCompanion(false).copyWith(used: const Value(true)), + ); + } + }); + } catch (e, s) { + Logging.instance.e("_checkSpentMwebUtxos()", error: e, stackTrace: s); + } + } + + Future _checkAddresses() async { + // check change first as it is index 0 + Address? changeAddress = await getMwebChangeAddress(); + if (changeAddress == null) { + changeAddress = await generateNextMwebAddress(isChange: true); + await mainDB.putAddress(changeAddress); + } + + // check recieving + Address? address = await getCurrentReceivingMwebAddress(); + if (address == null) { + address = await generateNextMwebAddress(); + await mainDB.putAddress(address); + } + } + // =========================================================================== - @mustCallSuper @override - Future init() async { + Future confirmSend({required TxData txData}) async { + if (txData.isMweb) { + return await _confirmSendMweb(txData: txData); + } else { + return await super.confirmSend(txData: txData); + } + } + + @override + Future open() async { if (info.isMwebEnabled) { try { await _initMweb(); - Address? address = await getCurrentReceivingMwebAddress(); - if (address == null) { - address = await generateNextMwebAddress(); - await mainDB.putAddress(address); - } + + await _checkAddresses(); unawaited(_startUpdateMwebUtxos()); } catch (e, s) { @@ -455,8 +557,6 @@ mixin MwebInterface ); } } - - await super.init(); } @override @@ -470,6 +570,8 @@ mixin MwebInterface if (info.isMwebEnabled) { final start = DateTime.now(); try { + await _checkSpentMwebUtxos(); + final currentHeight = await chainHeight; final db = Drift.get(walletId); final mwebUtxos = @@ -547,52 +649,6 @@ mixin MwebInterface } } - @override - Future refresh() async { - if (isViewOnly || !info.isMwebEnabled) { - await super.refresh(); - return; - } - - // Awaiting this lock could be dangerous. - // Since refresh is periodic (generally) - if (refreshMutex.isLocked) { - return; - } - - // TODO - - // final node = getCurrentNode(); - // - // if (_torNodeMismatchGuard(node)) { - // throw Exception("TOR – clearnet mismatch"); - // } - // - // // this acquire should be almost instant due to above check. - // // Slight possibility of race but should be irrelevant - // await refreshMutex.acquire(); - // - // libMoneroWallet?.startSyncing(); - // _setSyncStatus(lib_monero_compat.StartingSyncStatus()); - // - // await updateTransactions(); - // await updateBalance(); - // - // if (info.otherData[WalletInfoKeys.reuseAddress] != true) { - // await checkReceivingAddressForTransactions(); - // } - // - // if (refreshMutex.isLocked) { - // refreshMutex.release(); - // } - // - // final synced = await libMoneroWallet?.isSynced(); - // - // if (synced == true) { - // _setSyncStatus(lib_monero_compat.SyncedSyncStatus()); - // } - } - @override Future recover({required bool isRescan}) async { if (isViewOnly) { @@ -616,6 +672,8 @@ mixin MwebInterface try { await refreshMutex.protect(() async { if (isRescan) { + await _stopUpdateMwebUtxos(); + // clear cache await electrumXCachedClient.clearSharedTransactionCache( cryptoCurrency: info.coin, @@ -639,8 +697,9 @@ mixin MwebInterface final db = Drift.get(walletId); await db.transaction(() async => await db.delete(db.mwebUtxos).go()); - await _stopUpdateMwebUtxos(); if (info.isMwebEnabled) { + await _checkAddresses(); + // only restart scanning if mweb enabled unawaited(_startUpdateMwebUtxos()); } @@ -747,4 +806,76 @@ mixin MwebInterface _mwebdPolling = null; await super.exit(); } + + bool isMwebAddress(String address) { + try { + cl.MwebAddress.fromString(address, network: cryptoCurrency.networkParams); + return true; + } catch (_) { + return false; + } + } + + // TODO: this is broken + Future mwebFee({required TxData txData}) async { + final client = await _client; + + final resp = await client.create( + CreateRequest( + rawTx: txData.raw!.toUint8ListFromHex, + scanSecret: await _scanSecret, + spendSecret: await _spendSecret, + feeRatePerKb: Int64(txData.feeRateAmount!.toInt()), + dryRun: false, + ), + ); + + final tx = cl.Transaction.fromBytes(Uint8List.fromList(resp.rawTx)); + + final used = [ + ...txData.usedUTXOs?.map((e) => StandardInput(e)) ?? [], + ...txData.usedMwebUtxos?.map((e) => MwebInput(e)) ?? [], + ]; + + final posUtxos = + used + .where( + (utxo) => tx.inputs.any( + (input) => + input.prevOut.hash.toHex == + Uint8List.fromList( + utxo.id.toUint8ListFromHex.reversed.toList(), + ).toHex, + ), + ) + .toList(); + + final preInSum = used.fold(BigInt.zero, (p, e) => p + e.value); + final posOutputSum = tx.outputs.fold( + BigInt.zero, + (acc, output) => acc + output.value, + ); + final mwebInputSum = + preInSum - posUtxos.fold(BigInt.zero, (p, e) => p + e.value); + + final preOutputSum = txData.recipients!.fold( + BigInt.zero, + (p, e) => p + e.amount.raw, + ); + + final difference = preOutputSum - mwebInputSum; + + final expectedPegin = difference > BigInt.zero ? difference : BigInt.zero; + + final fee = preInSum - preOutputSum; + + BigInt feeIncrease = posOutputSum - expectedPegin; + if (expectedPegin > BigInt.zero && fee == BigInt.zero) { + feeIncrease += txData.fee!.raw + txData.feeRateAmount! * BigInt.from(41); + } + return Amount( + rawValue: fee + feeIncrease, + fractionDigits: cryptoCurrency.fractionDigits, + ); + } } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart index 5d38c3d87..1a62c46ef 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart @@ -379,7 +379,7 @@ mixin PaynymInterface return prepareSend( txData: txData.copyWith( recipients: [ - ( + TxRecipient( address: sendToAddress.value, amount: txData.recipients!.first.amount, isChange: false, @@ -528,7 +528,7 @@ mixin PaynymInterface // gather required signing data final utxoSigningData = (await fetchBuildTxData( - utxoObjectsToUse, + utxoObjectsToUse.map((e) => StandardInput(e)).toList(), )).whereType().toList(); final vSizeForNoChange = BigInt.from( @@ -608,7 +608,7 @@ mixin PaynymInterface final txData = TxData( raw: txn.item1, recipients: [ - ( + TxRecipient( address: targetPaymentCodeString, amount: amountToSend, isChange: false, @@ -619,7 +619,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.map((e) => e.utxo).toSet(), + utxos: utxoSigningData.toSet(), note: "PayNym connect", ); @@ -638,7 +638,7 @@ mixin PaynymInterface final txData = TxData( raw: txn.item1, recipients: [ - ( + TxRecipient( address: targetPaymentCodeString, amount: amountToSend, isChange: false, @@ -649,7 +649,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.map((e) => e.utxo).toSet(), + utxos: utxoSigningData.toSet(), note: "PayNym connect", ); @@ -669,7 +669,7 @@ mixin PaynymInterface final txData = TxData( raw: txn.item1, recipients: [ - ( + TxRecipient( address: targetPaymentCodeString, amount: amountToSend, isChange: false, @@ -680,7 +680,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.map((e) => e.utxo).toSet(), + utxos: utxoSigningData.toSet(), note: "PayNym connect", ); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart index 2e609aeb0..0fad30a5e 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart @@ -4,6 +4,7 @@ import 'package:isar/isar.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; +import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../utilities/logger.dart'; @@ -46,14 +47,15 @@ mixin RbfInterface required TransactionV2 oldTransaction, required int newRate, }) async { - final note = await mainDB.isar.transactionNotes - .where() - .walletIdEqualTo(walletId) - .filter() - .txidEqualTo(oldTransaction.txid) - .findFirst(); + final note = + await mainDB.isar.transactionNotes + .where() + .walletIdEqualTo(walletId) + .filter() + .txidEqualTo(oldTransaction.txid) + .findFirst(); - final Set utxos = {}; + final Set utxos = {}; for (final input in oldTransaction.inputs) { final utxo = UTXO( walletId: walletId, @@ -71,7 +73,7 @@ mixin RbfInterface address: input.addresses.first, ); - utxos.add(utxo); + utxos.add(StandardInput(utxo)); } final List recipients = []; @@ -86,43 +88,43 @@ mixin RbfInterface final isChange = addressModel?.subType == AddressSubType.change; recipients.add( - ( + TxRecipient( address: address, amount: Amount( - rawValue: output.value, - fractionDigits: cryptoCurrency.fractionDigits), + rawValue: output.value, + fractionDigits: cryptoCurrency.fractionDigits, + ), isChange: isChange, ), ); } - final oldFee = oldTransaction - .getFee(fractionDigits: cryptoCurrency.fractionDigits) - .raw; - final inSum = utxos - .map((e) => BigInt.from(e.value)) - .fold(BigInt.zero, (p, e) => p + e); + final oldFee = + oldTransaction + .getFee(fractionDigits: cryptoCurrency.fractionDigits) + .raw; + final inSum = utxos.map((e) => e.value).fold(BigInt.zero, (p, e) => p + e); final noChange = recipients.map((e) => e.isChange).fold(false, (p, e) => p || e) == - false; - final otherAvailableUtxos = await mainDB - .getUTXOs(walletId) - .filter() - .isBlockedEqualTo(false) - .and() - .group( - (q) => q.usedIsNull().or().usedEqualTo(false), - ) - .findAll(); + false; + final otherAvailableUtxos = + await mainDB + .getUTXOs(walletId) + .filter() + .isBlockedEqualTo(false) + .and() + .group((q) => q.usedIsNull().or().usedEqualTo(false)) + .findAll(); final height = await chainHeight; otherAvailableUtxos.removeWhere( - (e) => !e.isConfirmed( - height, - cryptoCurrency.minConfirms, - cryptoCurrency.minCoinbaseConfirms, - ), + (e) => + !e.isConfirmed( + height, + cryptoCurrency.minConfirms, + cryptoCurrency.minCoinbaseConfirms, + ), ); TxData txData = TxData( @@ -138,7 +140,7 @@ mixin RbfInterface // safe to assume send all? txData = txData.copyWith( recipients: [ - ( + TxRecipient( address: recipients.first.address, amount: Amount( rawValue: inSum, @@ -159,8 +161,9 @@ mixin RbfInterface throw Exception("New fee in RBF has not changed at all"); } - final indexOfChangeOutput = - txData.recipients!.indexWhere((e) => e.isChange); + final indexOfChangeOutput = txData.recipients!.indexWhere( + (e) => e.isChange, + ); final removed = txData.recipients!.removeAt(indexOfChangeOutput); @@ -172,7 +175,7 @@ mixin RbfInterface // update recipients txData.recipients!.insert( indexOfChangeOutput, - ( + TxRecipient( address: removed.address, amount: Amount( rawValue: newChangeAmount, @@ -200,7 +203,11 @@ mixin RbfInterface } return await buildTransaction( txData: txData.copyWith( - usedUTXOs: txData.utxos!.toList(), + usedUTXOs: + txData.utxos! + .whereType() + .map((e) => e.utxo) + .toList(), fee: Amount( rawValue: newFee, fractionDigits: cryptoCurrency.fractionDigits, @@ -232,7 +239,7 @@ mixin RbfInterface } txData.recipients!.insert( indexOfChangeOutput, - ( + TxRecipient( address: removed.address, amount: Amount( rawValue: newChangeAmount, @@ -243,7 +250,7 @@ mixin RbfInterface ); final newUtxoSet = { - ...txData.utxos!, + ...txData.utxos!.whereType().map((e) => e.utxo), ...extraUtxos, }; @@ -257,14 +264,16 @@ mixin RbfInterface return await buildTransaction( txData: txData.copyWith( - utxos: newUtxoSet, + utxos: newUtxoSet.map((e) => StandardInput(e)).toSet(), usedUTXOs: newUtxoSet.toList(), fee: Amount( rawValue: newFee, fractionDigits: cryptoCurrency.fractionDigits, ), ), - utxoSigningData: await fetchBuildTxData(newUtxoSet.toList()), + utxoSigningData: await fetchBuildTxData( + newUtxoSet.map((e) => StandardInput(e)).toList(), + ), ); } } else { diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 02a257ea8..42cc50a79 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -480,8 +480,7 @@ mixin SparkInterface txb.setLockTime(await chainHeight); txb.setVersion(3 | (9 << 16)); - List<({String address, Amount amount, bool isChange})>? - recipientsWithFeeSubtracted; + List? recipientsWithFeeSubtracted; List<({String address, Amount amount, String memo, bool isChange})>? sparkRecipientsWithFeeSubtracted; final recipientCount = @@ -535,16 +534,18 @@ mixin SparkInterface if (txData.recipients![i].amount.raw == BigInt.zero) { continue; } - recipientsWithFeeSubtracted!.add(( - address: txData.recipients![i].address, - amount: Amount( - rawValue: - txData.recipients![i].amount.raw - - (estimatedFee ~/ BigInt.from(totalRecipientCount)), - fractionDigits: cryptoCurrency.fractionDigits, + recipientsWithFeeSubtracted!.add( + TxRecipient( + address: txData.recipients![i].address, + amount: Amount( + rawValue: + txData.recipients![i].amount.raw - + (estimatedFee ~/ BigInt.from(totalRecipientCount)), + fractionDigits: cryptoCurrency.fractionDigits, + ), + isChange: txData.recipients![i].isChange, ), - isChange: txData.recipients![i].isChange, - )); + ); final scriptPubKey = btc.Address.addressToOutputScript( txData.recipients![i].address, @@ -1556,7 +1557,9 @@ mixin SparkInterface for (final utxo in itr) { if (nValueToSelect > nValueIn) { setCoins.add( - (await fetchBuildTxData([utxo])).whereType().first, + (await fetchBuildTxData([ + StandardInput(utxo), + ])).whereType().first, ); nValueIn += BigInt.from(utxo.value); } @@ -2073,7 +2076,8 @@ mixin SparkInterface throw Exception("Attempted send of zero amount"); } - final utxos = txData.utxos; + final utxos = + txData.utxos?.whereType().map((e) => e.utxo).toList(); final bool coinControl = utxos != null; final utxosTotal = @@ -2228,7 +2232,7 @@ mixin SparkInterface txData: TxData( sparkNameInfo: data, recipients: [ - ( + TxRecipient( address: destinationAddress, amount: Amount.fromDecimal( Decimal.fromInt(kStandardSparkNamesFee[name.length] * years), diff --git a/pubspec.lock b/pubspec.lock index 4db79d477..9cbfc4ab4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -352,21 +352,17 @@ packages: coinlib: dependency: "direct overridden" description: - path: coinlib - ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 - resolved-ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 - url: "https://www.github.com/julian-CStack/coinlib" - source: git - version: "3.1.0" + path: "../coinlib/coinlib" + relative: true + source: path + version: "4.1.0" coinlib_flutter: dependency: "direct main" description: - path: coinlib_flutter - ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 - resolved-ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 - url: "https://www.github.com/julian-CStack/coinlib" - source: git - version: "3.0.0" + path: "../coinlib/coinlib_flutter" + relative: true + source: path + version: "4.0.0" collection: dependency: transitive description: @@ -1285,10 +1281,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.19.0" io: dependency: transitive description: @@ -1891,14 +1887,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.3" - rxdart: - dependency: "direct main" - description: - name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" - url: "https://pub.dev" - source: hosted - version: "0.27.7" sec: dependency: transitive description: From 921287cee7520233a645f23373f1f9eb33b36816 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 24 Jun 2025 09:52:25 -0600 Subject: [PATCH 136/206] temp hacks --- .../electrumx_interface.dart | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 877cb0783..96f13af8b 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -85,6 +85,18 @@ mixin ElectrumXInterface final List results = []; for (int i = 0; i < addrs.length; i++) { + // temp mweb hack + AddressType? type; + if (this is MwebInterface) { + final addr = coinlib.Address.fromString( + addrs[i], + cryptoCurrency.networkParams, + ); + if (addr is coinlib.MwebAddress) { + type = AddressType.mweb; + } + } + results.add( TxRecipient( address: addrs[i], @@ -103,6 +115,7 @@ mixin ElectrumXInterface .valueProperty() .findFirst()) != null, + addressType: type, ), ); } @@ -143,7 +156,9 @@ mixin ElectrumXInterface await (db.select(db.mwebUtxos) ..where((e) => e.used.equals(false))).get(); - availableOutputs.addAll(mwebUtxos.map((e) => MwebInput(e))); + for (final e in mwebUtxos) { + availableOutputs.add(MwebInput(e)); + } } final currentChainHeight = await chainHeight; @@ -241,7 +256,7 @@ mixin ElectrumXInterface final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); if (isSendAll || isSendAllCoinControlUtxos) { - if (satoshiAmountToSend != satoshisBeingUsed) { + if (satoshiAmountToSend != satoshisBeingUsed && !txData.isMweb) { throw Exception( "Something happened that should never actually happen. " "Please report this error to the developers.", @@ -621,6 +636,9 @@ mixin ElectrumXInterface final isMweb = hasMwebOutputs || hasMwebInputs; + print("IS MEB hasMwebInputs: $hasMwebInputs"); + print("IS MEB hasMwebOutputs: $hasMwebOutputs"); + coinlib.Transaction clTx = coinlib.Transaction( version: isMweb ? 2 : cryptoCurrency.transactionVersion, inputs: [], @@ -1784,6 +1802,36 @@ mixin ElectrumXInterface throw Exception("No recipients in attempted transaction!"); } + if (this is MwebInterface) { + bool hasMwebOutputs = false; + final recipients = + txData.recipients!.map((e) { + if (e.addressType == null) { + final addr = coinlib.Address.fromString( + e.address, + cryptoCurrency.networkParams, + ); + if (addr is coinlib.MwebAddress) { + hasMwebOutputs = true; + return TxRecipient( + address: e.address, + amount: e.amount, + isChange: e.isChange, + addressType: AddressType.mweb, + ); + } + } + return e; + }).toList(); + txData = txData.copyWith( + recipients: recipients, + isMweb: txData.isMweb || hasMwebOutputs, + ); + print("IS MEB FLAG AAAA: ${txData.isMweb}"); + } + + print("IS MEB FLAG: ${txData.isMweb}"); + final feeRateType = txData.feeRateType; final customSatsPerVByte = txData.satsPerVByte; final feeRateAmount = txData.feeRateAmount; From 15f84b483e69781819250dac496d157668589c96 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jun 2025 16:18:23 -0600 Subject: [PATCH 137/206] no need to update if empty list passed in --- lib/db/isar/main_db.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart index cb0163503..c8f7fc493 100644 --- a/lib/db/isar/main_db.dart +++ b/lib/db/isar/main_db.dart @@ -312,6 +312,9 @@ class MainDB { Future updateUTXOs(String walletId, List utxos) async { bool newUTXO = false; + + if (utxos.isEmpty) return newUTXO; + await isar.writeTxn(() async { final set = utxos.toSet(); for (final utxo in utxos) { From 11d6b2cc132eac430b68c6892aedc486ed854e14 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jun 2025 16:18:46 -0600 Subject: [PATCH 138/206] fix: respect verbose flag --- lib/electrumx_rpc/electrumx_client.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index 3852d9be9..da5cf2778 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -813,7 +813,10 @@ class ElectrumXClient { }) async { Logging.instance.d("attempting to fetch blockchain.transaction.get..."); await checkElectrumAdapter(); - final dynamic response = await getElectrumAdapter()!.getTransaction(txHash); + final dynamic response = await getElectrumAdapter()!.request( + 'blockchain.transaction.get', + [txHash, verbose], + ); Logging.instance.d("Fetching blockchain.transaction.get finished"); if (!verbose) { From e9f021cb51d18158a2bf56314ed9a2dfd2ed3246 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jun 2025 12:33:23 -0600 Subject: [PATCH 139/206] mweb (and pegin/pegout) transactions (with some bugs) and some relatively major refactoring in general --- lib/models/{signing_data.dart => input.dart} | 0 .../exchange_step_views/step_4_view.dart | 15 +- lib/pages/exchange_view/send_from_view.dart | 19 +- lib/pages/namecoin_names/buy_domain_view.dart | 1 + .../sub_widgets/transfer_option_widget.dart | 1 + .../sub_widgets/update_option_widget.dart | 1 + .../send_view/frost_ms/frost_send_view.dart | 1 + .../send_steps/frost_send_step_1b.dart | 4 +- lib/pages/send_view/send_view.dart | 40 +- lib/pages/send_view/token_send_view.dart | 8 +- .../desktop_coin_control_use_dialog.dart | 2 +- .../wallet_view/sub_widgets/desktop_send.dart | 38 +- .../sub_widgets/desktop_token_send.dart | 8 +- lib/wallets/crypto_currency/coins/banano.dart | 8 + .../crypto_currency/coins/bitcoin_frost.dart | 17 + .../crypto_currency/coins/cardano.dart | 8 + .../crypto_currency/coins/epiccash.dart | 8 + .../crypto_currency/coins/ethereum.dart | 8 + lib/wallets/crypto_currency/coins/nano.dart | 8 + lib/wallets/crypto_currency/coins/solana.dart | 8 + .../crypto_currency/coins/stellar.dart | 8 + lib/wallets/crypto_currency/coins/tezos.dart | 8 + lib/wallets/crypto_currency/coins/xelis.dart | 8 + .../crypto_currency/crypto_currency.dart | 1 + .../electrumx_currency_interface.dart | 20 + .../intermediate/cryptonote_currency.dart | 8 + .../intermediate/nano_currency.dart | 12 +- lib/wallets/models/tx_data.dart | 37 +- lib/wallets/models/tx_recipient.dart | 40 +- .../wallet/impl/bitcoin_frost_wallet.dart | 2 +- lib/wallets/wallet/impl/cardano_wallet.dart | 4 +- lib/wallets/wallet/impl/epiccash_wallet.dart | 6 +- lib/wallets/wallet/impl/litecoin_wallet.dart | 49 ++- lib/wallets/wallet/impl/namecoin_wallet.dart | 63 +-- lib/wallets/wallet/impl/particl_wallet.dart | 32 +- lib/wallets/wallet/impl/tezos_wallet.dart | 8 +- lib/wallets/wallet/impl/wownero_wallet.dart | 2 + lib/wallets/wallet/impl/xelis_wallet.dart | 1 + .../intermediate/lib_monero_wallet.dart | 2 +- .../intermediate/lib_salvium_wallet.dart | 2 +- .../bcash_interface.dart | 28 +- .../electrumx_interface.dart | 393 +++++++++--------- .../mweb_interface.dart | 190 +++++++-- .../paynym_interface.dart | 60 +-- .../rbf_interface.dart | 30 +- .../spark_interface.dart | 11 +- 46 files changed, 765 insertions(+), 463 deletions(-) rename lib/models/{signing_data.dart => input.dart} (100%) diff --git a/lib/models/signing_data.dart b/lib/models/input.dart similarity index 100% rename from lib/models/signing_data.dart rename to lib/models/input.dart diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index 11bc9fe82..d244ded98 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -230,12 +230,17 @@ class _Step4ViewState extends ConsumerState { Future txDataFuture; + final recipient = TxRecipient( + address: address, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(address)!, + ); + if (wallet is FiroWallet && !firoPublicSend) { txDataFuture = wallet.prepareSendSpark( txData: TxData( - recipients: [ - TxRecipient(address: address, amount: amount, isChange: false), - ], + recipients: [recipient], note: "${model.trade!.payInCurrency.toUpperCase()}/" "${model.trade!.payOutCurrency.toUpperCase()} exchange", @@ -250,9 +255,7 @@ class _Step4ViewState extends ConsumerState { : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - TxRecipient(address: address, amount: amount, isChange: false), - ], + recipients: [recipient], memo: memo, feeRateType: FeeRateType.average, note: diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index dd98dce23..fa0283ff4 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -283,6 +283,13 @@ class _SendFromCardState extends ConsumerState { TxData txData; Future txDataFuture; + final recipient = TxRecipient( + address: address, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(address)!, + ); + // if not firo then do normal send if (shouldSendPublicFiroFunds == null) { final memo = @@ -293,9 +300,7 @@ class _SendFromCardState extends ConsumerState { : null; txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - TxRecipient(address: address, amount: amount, isChange: false), - ], + recipients: [recipient], memo: memo, feeRateType: FeeRateType.average, ), @@ -306,18 +311,14 @@ class _SendFromCardState extends ConsumerState { if (shouldSendPublicFiroFunds) { txDataFuture = wallet.prepareSend( txData: TxData( - recipients: [ - TxRecipient(address: address, amount: amount, isChange: false), - ], + recipients: [recipient], feeRateType: FeeRateType.average, ), ); } else { txDataFuture = firoWallet.prepareSendSpark( txData: TxData( - recipients: [ - TxRecipient(address: address, amount: amount, isChange: false), - ], + recipients: [recipient], // feeRateType: FeeRateType.average, ), ); diff --git a/lib/pages/namecoin_names/buy_domain_view.dart b/lib/pages/namecoin_names/buy_domain_view.dart index 6b2695ef5..2943c6ec1 100644 --- a/lib/pages/namecoin_names/buy_domain_view.dart +++ b/lib/pages/namecoin_names/buy_domain_view.dart @@ -110,6 +110,7 @@ class _BuyDomainWidgetState extends ConsumerState { rawValue: BigInt.from(kNameNewAmountSats), fractionDigits: wallet.cryptoCurrency.fractionDigits, ), + addressType: myAddress.type, ), ], ); diff --git a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart index db869b5f3..89be6129c 100644 --- a/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/transfer_option_widget.dart @@ -140,6 +140,7 @@ class _TransferOptionWidgetState extends ConsumerState { rawValue: BigInt.from(kNameAmountSats), fractionDigits: wallet.cryptoCurrency.fractionDigits, ), + addressType: wallet.cryptoCurrency.getAddressType(_address!)!, ), ], note: "Transfer ${opName.constructedName}", diff --git a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart index ac9f665d6..4fd78fb70 100644 --- a/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart +++ b/lib/pages/namecoin_names/sub_widgets/update_option_widget.dart @@ -154,6 +154,7 @@ class _BuyDomainWidgetState extends ConsumerState { rawValue: BigInt.from(kNameAmountSats), fractionDigits: wallet.cryptoCurrency.fractionDigits, ), + addressType: _address.type, ), ], note: "Update ${opName.constructedName} (${opName.fullname})", diff --git a/lib/pages/send_view/frost_ms/frost_send_view.dart b/lib/pages/send_view/frost_ms/frost_send_view.dart index 70f9f964b..4b1014158 100644 --- a/lib/pages/send_view/frost_ms/frost_send_view.dart +++ b/lib/pages/send_view/frost_ms/frost_send_view.dart @@ -88,6 +88,7 @@ class _FrostSendViewState extends ConsumerState { address: e!.address, amount: e.amount!, isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(e.address)!, ), ) .toList(growable: false); diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart index 21d85fe9c..e5f6581a1 100644 --- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart +++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart @@ -3,8 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; import '../../../../frost_route_generator.dart'; +import '../../../../models/input.dart'; import '../../../../models/isar/models/isar_models.dart'; -import '../../../../models/signing_data.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/frost_wallet/frost_wallet_providers.dart'; import '../../../../providers/global/wallets_provider.dart'; @@ -97,6 +97,8 @@ class _FrostSendStep1bState extends ConsumerState { address: e.address, amount: e.amount, isChange: false, + addressType: + wallet.cryptoCurrency.getAddressType(e.address)!, ), ) .toList(), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 63df318e8..8c3af28e7 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -19,10 +19,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:tuple/tuple.dart'; +import '../../models/input.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; import '../../models/send_view_auto_fill_data.dart'; -import '../../models/signing_data.dart'; import '../../providers/providers.dart'; import '../../providers/ui/fee_rate_type_state_provider.dart'; import '../../providers/ui/preview_tx_button_state_provider.dart'; @@ -720,6 +720,7 @@ class _SendViewState extends ConsumerState { address: widget.accountLite!.code, amount: amount, isChange: false, + addressType: AddressType.unknown, ), ], satsPerVByte: isCustomFee.value ? customFeeRate : null, @@ -762,6 +763,8 @@ class _SendViewState extends ConsumerState { address: _address!, amount: amount, isChange: false, + addressType: + wallet.cryptoCurrency.getAddressType(_address!)!, ), ], feeRateType: ref.read(feeRateTypeMobileStateProvider), @@ -786,6 +789,10 @@ class _SendViewState extends ConsumerState { address: _address!, amount: amount, isChange: false, + addressType: + wallet.cryptoCurrency.getAddressType( + _address!, + )!, ), ], sparkRecipients: @@ -805,20 +812,26 @@ class _SendViewState extends ConsumerState { } } else if (wallet is MwebInterface && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { - txDataFuture = wallet.prepareSend( + txDataFuture = wallet.prepareSendMweb( txData: TxData( - isMweb: true, recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(_address!)!, + ), ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee.value ? customFeeRate : null, - utxos: - (wallet is CoinControlInterface && - coinControlEnabled && - selectedUTXOs.isNotEmpty) - ? selectedUTXOs - : null, + + // these will need to be mweb utxos + // utxos: + // (wallet is CoinControlInterface && + // coinControlEnabled && + // ref.read(pDesktopUseUTXOs).isNotEmpty) + // ? ref.read(pDesktopUseUTXOs) + // : null, ), ); } else { @@ -826,7 +839,12 @@ class _SendViewState extends ConsumerState { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(_address!)!, + ), ], memo: memo, feeRateType: ref.read(feeRateTypeMobileStateProvider), diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 70f076c01..fdf78136e 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -492,7 +492,13 @@ class _TokenSendViewState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: + tokenWallet.cryptoCurrency.getAddressType(_address!)!, + ), ], feeRateType: ref.read(feeRateTypeMobileStateProvider), note: noteController.text, diff --git a/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart index 4f8e8576f..a5e0ba924 100644 --- a/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart +++ b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart @@ -16,8 +16,8 @@ import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; import '../../db/isar/main_db.dart'; +import '../../models/input.dart'; import '../../models/isar/models/blockchain_data/utxo.dart'; -import '../../models/signing_data.dart'; import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount.dart'; diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index b5cb4e7c9..a2cf27fb5 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -17,6 +17,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import '../../../../models/isar/models/blockchain_data/address.dart'; import '../../../../models/isar/models/blockchain_data/utxo.dart'; import '../../../../models/isar/models/contact_entry.dart'; import '../../../../models/paynym/paynym_account_lite.dart'; @@ -315,6 +316,7 @@ class _DesktopSendState extends ConsumerState { address: widget.accountLite!.code, amount: amount, isChange: false, + addressType: AddressType.unknown, ), ], satsPerVByte: isCustomFee ? customFeeRate : null, @@ -358,6 +360,8 @@ class _DesktopSendState extends ConsumerState { address: _address!, amount: amount, isChange: false, + addressType: + wallet.cryptoCurrency.getAddressType(_address!)!, ), ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), @@ -383,6 +387,10 @@ class _DesktopSendState extends ConsumerState { address: _address!, amount: amount, isChange: false, + addressType: + wallet.cryptoCurrency.getAddressType( + _address!, + )!, ), ], sparkRecipients: @@ -402,20 +410,25 @@ class _DesktopSendState extends ConsumerState { } } else if (wallet is MwebInterface && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { - txDataFuture = wallet.prepareSend( + txDataFuture = wallet.prepareSendMweb( txData: TxData( - isMweb: true, recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(_address!)!, + ), ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), satsPerVByte: isCustomFee ? customFeeRate : null, - utxos: - (wallet is CoinControlInterface && - coinControlEnabled && - ref.read(pDesktopUseUTXOs).isNotEmpty) - ? ref.read(pDesktopUseUTXOs) - : null, + // these will need to be mweb utxos + // utxos: + // (wallet is CoinControlInterface && + // coinControlEnabled && + // ref.read(pDesktopUseUTXOs).isNotEmpty) + // ? ref.read(pDesktopUseUTXOs) + // : null, ), ); } else { @@ -423,7 +436,12 @@ class _DesktopSendState extends ConsumerState { txDataFuture = wallet.prepareSend( txData: TxData( recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: wallet.cryptoCurrency.getAddressType(_address!)!, + ), ], memo: memo, feeRateType: ref.read(feeRateTypeDesktopStateProvider), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index 581b5a824..bf57331ea 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -233,7 +233,13 @@ class _DesktopTokenSendState extends ConsumerState { txDataFuture = tokenWallet.prepareSend( txData: TxData( recipients: [ - TxRecipient(address: _address!, amount: amount, isChange: false), + TxRecipient( + address: _address!, + amount: amount, + isChange: false, + addressType: + tokenWallet.cryptoCurrency.getAddressType(_address!)!, + ), ], feeRateType: ref.read(feeRateTypeDesktopStateProvider), nonce: int.tryParse(nonceController.text), diff --git a/lib/wallets/crypto_currency/coins/banano.dart b/lib/wallets/crypto_currency/coins/banano.dart index 2a62acb57..eccb6fe38 100644 --- a/lib/wallets/crypto_currency/coins/banano.dart +++ b/lib/wallets/crypto_currency/coins/banano.dart @@ -102,4 +102,12 @@ class Banano extends NanoCurrency { throw UnsupportedError( "$runtimeType does not use bitcoin style derivation paths", ); + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.banano; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart index 330d3cb86..3edaea351 100644 --- a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart +++ b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:coinlib_flutter/coinlib_flutter.dart' as cl; import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; import '../../../models/isar/models/blockchain_data/address.dart'; @@ -247,4 +248,20 @@ class BitcoinFrost extends FrostCurrency { // @override BigInt get defaultFeeRate => BigInt.from(1000); // https://github.com/bitcoin/bitcoin/blob/feab35189bc00bc4cf15e9dcb5cf6b34ff3a1e91/test/functional/mempool_limit.py#L259 + + @override + AddressType? getAddressType(String address) { + try { + final clAddress = cl.Address.fromString(address, networkParams); + + return switch (clAddress) { + cl.P2PKHAddress() => AddressType.p2pkh, + cl.P2WSHAddress() => AddressType.p2sh, + cl.P2WPKHAddress() => AddressType.p2wpkh, + _ => null, + }; + } catch (_) { + return null; + } + } } diff --git a/lib/wallets/crypto_currency/coins/cardano.dart b/lib/wallets/crypto_currency/coins/cardano.dart index 976093a03..a59669eb7 100644 --- a/lib/wallets/crypto_currency/coins/cardano.dart +++ b/lib/wallets/crypto_currency/coins/cardano.dart @@ -128,4 +128,12 @@ class Cardano extends Bip39Currency { throw Exception("Unsupported network: $network"); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.cardanoShelley; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/epiccash.dart b/lib/wallets/crypto_currency/coins/epiccash.dart index d35c0fb74..b715f9623 100644 --- a/lib/wallets/crypto_currency/coins/epiccash.dart +++ b/lib/wallets/crypto_currency/coins/epiccash.dart @@ -129,4 +129,12 @@ class Epiccash extends Bip39Currency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.mimbleWimble; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/ethereum.dart b/lib/wallets/crypto_currency/coins/ethereum.dart index f6f3601a1..448f4c9ff 100644 --- a/lib/wallets/crypto_currency/coins/ethereum.dart +++ b/lib/wallets/crypto_currency/coins/ethereum.dart @@ -113,4 +113,12 @@ class Ethereum extends Bip39Currency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.ethereum; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/nano.dart b/lib/wallets/crypto_currency/coins/nano.dart index 07f464926..04622c54d 100644 --- a/lib/wallets/crypto_currency/coins/nano.dart +++ b/lib/wallets/crypto_currency/coins/nano.dart @@ -102,4 +102,12 @@ class Nano extends NanoCurrency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.nano; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/solana.dart b/lib/wallets/crypto_currency/coins/solana.dart index 39d243a1c..03331a922 100644 --- a/lib/wallets/crypto_currency/coins/solana.dart +++ b/lib/wallets/crypto_currency/coins/solana.dart @@ -122,4 +122,12 @@ class Solana extends Bip39Currency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.solana; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/stellar.dart b/lib/wallets/crypto_currency/coins/stellar.dart index 077564a50..1aa701f87 100644 --- a/lib/wallets/crypto_currency/coins/stellar.dart +++ b/lib/wallets/crypto_currency/coins/stellar.dart @@ -139,4 +139,12 @@ class Stellar extends Bip39Currency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.stellar; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/tezos.dart b/lib/wallets/crypto_currency/coins/tezos.dart index 78d3c02ad..179ae2ce1 100644 --- a/lib/wallets/crypto_currency/coins/tezos.dart +++ b/lib/wallets/crypto_currency/coins/tezos.dart @@ -220,4 +220,12 @@ class Tezos extends Bip39Currency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.tezos; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/coins/xelis.dart b/lib/wallets/crypto_currency/coins/xelis.dart index fc1eaaa20..62b33326b 100644 --- a/lib/wallets/crypto_currency/coins/xelis.dart +++ b/lib/wallets/crypto_currency/coins/xelis.dart @@ -141,4 +141,12 @@ class Xelis extends ElectrumCurrency { ); } } + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.xelis; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/crypto_currency.dart b/lib/wallets/crypto_currency/crypto_currency.dart index 4f6c232e6..0c2f2cb83 100644 --- a/lib/wallets/crypto_currency/crypto_currency.dart +++ b/lib/wallets/crypto_currency/crypto_currency.dart @@ -69,6 +69,7 @@ abstract class CryptoCurrency { String get genesisHash; bool validateAddress(String address); + AddressType? getAddressType(String address); NodeModel defaultNode({required bool isPrimary}); diff --git a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart index 387bf4454..c9d0da2b9 100644 --- a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart +++ b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart @@ -1,3 +1,6 @@ +import 'package:coinlib_flutter/coinlib_flutter.dart' as cl; + +import '../../../models/isar/models/blockchain_data/address.dart'; import '../intermediate/bip39_hd_currency.dart'; mixin ElectrumXCurrencyInterface on Bip39HDCurrency { @@ -5,4 +8,21 @@ mixin ElectrumXCurrencyInterface on Bip39HDCurrency { /// The default fee rate in satoshis per kilobyte. BigInt get defaultFeeRate; + + @override + AddressType? getAddressType(String address) { + try { + final clAddress = cl.Address.fromString(address, networkParams); + + return switch (clAddress) { + cl.P2PKHAddress() => AddressType.p2pkh, + cl.P2WSHAddress() => AddressType.p2sh, + cl.P2WPKHAddress() => AddressType.p2wpkh, + cl.MwebAddress() => AddressType.mweb, + _ => null, + }; + } catch (_) { + return null; + } + } } diff --git a/lib/wallets/crypto_currency/intermediate/cryptonote_currency.dart b/lib/wallets/crypto_currency/intermediate/cryptonote_currency.dart index 319a501ac..a0069e09b 100644 --- a/lib/wallets/crypto_currency/intermediate/cryptonote_currency.dart +++ b/lib/wallets/crypto_currency/intermediate/cryptonote_currency.dart @@ -13,4 +13,12 @@ abstract class CryptonoteCurrency extends CryptoCurrency @override AddressType get defaultAddressType => AddressType.cryptonote; + + @override + AddressType? getAddressType(String address) { + if (validateAddress(address)) { + return AddressType.cryptonote; + } + return null; + } } diff --git a/lib/wallets/crypto_currency/intermediate/nano_currency.dart b/lib/wallets/crypto_currency/intermediate/nano_currency.dart index a04cd57a0..a553a6d6c 100644 --- a/lib/wallets/crypto_currency/intermediate/nano_currency.dart +++ b/lib/wallets/crypto_currency/intermediate/nano_currency.dart @@ -1,4 +1,5 @@ import 'package:nanodart/nanodart.dart'; + import 'bip39_currency.dart'; abstract class NanoCurrency extends Bip39Currency { @@ -24,13 +25,10 @@ abstract class NanoCurrency extends Bip39Currency { List get possibleMnemonicLengths => [defaultSeedPhraseLength, 12]; @override - bool validateAddress(String address) => NanoAccounts.isValid( - nanoAccountType, - address, - ); + bool validateAddress(String address) => + NanoAccounts.isValid(nanoAccountType, address); @override - String get genesisHash => throw UnimplementedError( - "Not used in nano based coins", - ); + String get genesisHash => + throw UnimplementedError("Not used in nano based coins"); } diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart index bb2eb2cd1..9a8dffd21 100644 --- a/lib/wallets/models/tx_data.dart +++ b/lib/wallets/models/tx_data.dart @@ -3,11 +3,10 @@ import 'package:cs_salvium/cs_salvium.dart' as lib_salvium; import 'package:tezart/tezart.dart' as tezart; import 'package:web3dart/web3dart.dart' as web3dart; -import '../../db/drift/database.dart'; +import '../../models/input.dart'; import '../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/paynym/paynym_account_lite.dart'; -import '../../models/signing_data.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/enums/fee_rate_type_enum.dart'; import '../../widgets/eth_fee_form.dart'; @@ -17,6 +16,20 @@ import 'tx_recipient.dart'; export 'tx_recipient.dart'; +enum TxType { + regular, + mweb, + mwebPegIn, + mwebPegOut; + + bool isMweb() => switch (this) { + TxType.mweb => true, + TxType.mwebPegIn => true, + TxType.mwebPegOut => true, + _ => false, + }; +} + class TxData { final FeeRateType? feeRateType; final BigInt? feeRateAmount; @@ -37,7 +50,7 @@ class TxData { final List? recipients; final Set? utxos; - final List? usedUTXOs; + final List? usedUTXOs; final String? changeAddress; @@ -85,9 +98,7 @@ class TxData { // Namecoin Name related final NameOpState? opNameState; - // MWEB - final bool isMweb; - final List? usedMwebUtxos; + final TxType type; TxData({ this.feeRateType, @@ -123,8 +134,7 @@ class TxData { this.ignoreCachedBalanceChecks = false, this.opNameState, this.sparkNameInfo, - this.isMweb = false, - this.usedMwebUtxos, + this.type = TxType.regular, }); Amount? get amount { @@ -239,7 +249,7 @@ class TxData { String? memo, String? otherData, Set? utxos, - List? usedUTXOs, + List? usedUTXOs, List? recipients, String? frostMSConfig, List? frostSigners, @@ -272,8 +282,7 @@ class TxData { int validBlocks, })? sparkNameInfo, - bool? isMweb, - List? usedMwebUtxos, + TxType? type, }) { return TxData( feeRateType: feeRateType ?? this.feeRateType, @@ -311,8 +320,7 @@ class TxData { ignoreCachedBalanceChecks ?? this.ignoreCachedBalanceChecks, opNameState: opNameState ?? this.opNameState, sparkNameInfo: sparkNameInfo ?? this.sparkNameInfo, - isMweb: isMweb ?? this.isMweb, - usedMwebUtxos: usedMwebUtxos ?? this.usedMwebUtxos, + type: type ?? this.type, ); } @@ -351,7 +359,6 @@ class TxData { 'ignoreCachedBalanceChecks: $ignoreCachedBalanceChecks, ' 'opNameState: $opNameState, ' 'sparkNameInfo: $sparkNameInfo, ' - 'isMweb: $isMweb, ' - 'usedMwebUtxos: $usedMwebUtxos, ' + 'type: $type, ' '}'; } diff --git a/lib/wallets/models/tx_recipient.dart b/lib/wallets/models/tx_recipient.dart index 8dd0c3011..9173864d3 100644 --- a/lib/wallets/models/tx_recipient.dart +++ b/lib/wallets/models/tx_recipient.dart @@ -5,12 +5,48 @@ class TxRecipient { final String address; final Amount amount; final bool isChange; - final AddressType? addressType; + final AddressType addressType; TxRecipient({ required this.address, required this.amount, required this.isChange, - this.addressType, + required this.addressType, }); + + TxRecipient copyWith({ + String? address, + Amount? amount, + bool? isChange, + AddressType? addressType, + }) { + return TxRecipient( + address: address ?? this.address, + amount: amount ?? this.amount, + isChange: isChange ?? this.isChange, + addressType: addressType ?? this.addressType, + ); + } + + @override + String toString() { + return "TxRecipient{" + "address: $address, " + "amount: $amount, " + "isChange: $isChange, " + "addressType: $addressType" + "}"; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is TxRecipient && + address == other.address && + amount == other.amount && + isChange == other.isChange && + addressType == other.addressType; + + @override + int get hashCode => Object.hash(address, amount, isChange, addressType); } diff --git a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart index 33b6d3a0d..95f015c01 100644 --- a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart +++ b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart @@ -11,6 +11,7 @@ import 'package:isar/isar.dart'; import '../../../electrumx_rpc/cached_electrumx_client.dart'; import '../../../electrumx_rpc/electrumx_client.dart'; import '../../../models/balance.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/blockchain_data/utxo.dart'; @@ -18,7 +19,6 @@ import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/paymint/fee_object_model.dart'; -import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../services/event_bus/global_event_bus.dart'; import '../../../services/frost.dart'; diff --git a/lib/wallets/wallet/impl/cardano_wallet.dart b/lib/wallets/wallet/impl/cardano_wallet.dart index 5f4fdc37c..3909c5b4b 100644 --- a/lib/wallets/wallet/impl/cardano_wallet.dart +++ b/lib/wallets/wallet/impl/cardano_wallet.dart @@ -235,13 +235,11 @@ class CardanoWallet extends Bip39Wallet { // Check if we are sending all balance, which means no change and only one output for recipient. if (totalBalance == txData.amount!.raw) { final List newRecipients = [ - TxRecipient( - address: txData.recipients!.first.address, + txData.recipients!.first.copyWith( amount: Amount( rawValue: txData.amount!.raw - fee, fractionDigits: cryptoCurrency.fractionDigits, ), - isChange: txData.recipients!.first.isChange, ), ]; return txData.copyWith( diff --git a/lib/wallets/wallet/impl/epiccash_wallet.dart b/lib/wallets/wallet/impl/epiccash_wallet.dart index 9032a0c82..ea6654b12 100644 --- a/lib/wallets/wallet/impl/epiccash_wallet.dart +++ b/lib/wallets/wallet/impl/epiccash_wallet.dart @@ -646,11 +646,7 @@ class EpiccashWallet extends Bip39Wallet { } if (info.cachedBalance.spendable == recipient.amount) { - recipient = TxRecipient( - address: recipient.address, - amount: recipient.amount - feeAmount, - isChange: recipient.isChange, - ); + recipient = recipient.copyWith(amount: recipient.amount - feeAmount); } return txData.copyWith(recipients: [recipient], fee: feeAmount); diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index c8b2673f6..82769ee29 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -207,30 +207,35 @@ class LitecoinWallet // Parse outputs. final List outputs = []; for (final outputJson in txData["vout"] as List) { - OutputV2 output = OutputV2.fromElectrumXJson( - Map.from(outputJson as Map), - decimalPlaces: cryptoCurrency.fractionDigits, - isFullAmountNotSats: true, - // Need addresses before we can know if the wallet owns this input. - walletOwns: false, - ); + try { + OutputV2 output = OutputV2.fromElectrumXJson( + Map.from(outputJson as Map), + decimalPlaces: cryptoCurrency.fractionDigits, + isFullAmountNotSats: true, + // Need addresses before we can know if the wallet owns this input. + walletOwns: false, + ); - // If output was to my wallet, add value to amount received. - if (receivingAddresses - .intersection(output.addresses.toSet()) - .isNotEmpty) { - wasReceivedInThisWallet = true; - amountReceivedInThisWallet += output.value; - output = output.copyWith(walletOwns: true); - } else if (changeAddresses - .intersection(output.addresses.toSet()) - .isNotEmpty) { - wasReceivedInThisWallet = true; - changeAmountReceivedInThisWallet += output.value; - output = output.copyWith(walletOwns: true); - } + // If output was to my wallet, add value to amount received. + if (receivingAddresses + .intersection(output.addresses.toSet()) + .isNotEmpty) { + wasReceivedInThisWallet = true; + amountReceivedInThisWallet += output.value; + output = output.copyWith(walletOwns: true); + } else if (changeAddresses + .intersection(output.addresses.toSet()) + .isNotEmpty) { + wasReceivedInThisWallet = true; + changeAmountReceivedInThisWallet += output.value; + output = output.copyWith(walletOwns: true); + } - outputs.add(output); + outputs.add(output); + } catch (e, s) { + // TODO: mweb output parsing + Logging.instance.e("TODO", error: e, stackTrace: s); + } } final totalOut = outputs diff --git a/lib/wallets/wallet/impl/namecoin_wallet.dart b/lib/wallets/wallet/impl/namecoin_wallet.dart index 5cee5ce22..abf598c6f 100644 --- a/lib/wallets/wallet/impl/namecoin_wallet.dart +++ b/lib/wallets/wallet/impl/namecoin_wallet.dart @@ -5,11 +5,11 @@ import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; import 'package:isar/isar.dart'; import 'package:namecoin/namecoin.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/enums/fee_rate_type_enum.dart'; @@ -578,6 +578,8 @@ class NamecoinWallet noteName += ".bit"; } + final receivingAddress = (await getCurrentReceivingAddress())!; + TxData txData = TxData( utxos: {StandardInput(utxo)}, opNameState: NameOpState( @@ -594,12 +596,13 @@ class NamecoinWallet feeRateType: kNameTxDefaultFeeRate, // TODO: make configurable? recipients: [ TxRecipient( - address: (await getCurrentReceivingAddress())!.value, + address: receivingAddress.value, isChange: false, amount: Amount( rawValue: BigInt.from(kNameAmountSats), fractionDigits: cryptoCurrency.fractionDigits, ), + addressType: receivingAddress.type, ), ], ); @@ -627,7 +630,7 @@ class NamecoinWallet /// Builds and signs a transaction Future _createNameTx({ required TxData txData, - required List utxoSigningData, + required List inputsWithKeys, required bool isForFeeCalcPurposesOnly, }) async { Logging.instance.d("Starting _createNameTx ----------"); @@ -667,19 +670,19 @@ class NamecoinWallet : 0xffffffff - 1; // Add transaction inputs - for (int i = 0; i < utxoSigningData.length; i++) { - final txid = utxoSigningData[i].utxo.txid; + for (int i = 0; i < inputsWithKeys.length; i++) { + final txid = inputsWithKeys[i].utxo.txid; final hash = Uint8List.fromList( txid.toUint8ListFromHex.reversed.toList(), ); - final prevOutpoint = coinlib.OutPoint(hash, utxoSigningData[i].utxo.vout); + final prevOutpoint = coinlib.OutPoint(hash, inputsWithKeys[i].utxo.vout); final prevOutput = coinlib.Output.fromAddress( - BigInt.from(utxoSigningData[i].utxo.value), + BigInt.from(inputsWithKeys[i].utxo.value), coinlib.Address.fromString( - utxoSigningData[i].utxo.address!, + inputsWithKeys[i].utxo.address!, cryptoCurrency.networkParams, ), ); @@ -688,11 +691,11 @@ class NamecoinWallet final coinlib.Input input; - switch (utxoSigningData[i].derivePathType) { + switch (inputsWithKeys[i].derivePathType) { case DerivePathType.bip44: input = coinlib.P2PKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].key!.publicKey, + publicKey: inputsWithKeys[i].key!.publicKey, sequence: sequence, ); @@ -710,7 +713,7 @@ class NamecoinWallet case DerivePathType.bip84: input = coinlib.P2WPKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].key!.publicKey, + publicKey: inputsWithKeys[i].key!.publicKey, sequence: sequence, ); @@ -719,7 +722,7 @@ class NamecoinWallet default: throw UnsupportedError( - "Unknown derivation path type found: ${utxoSigningData[i].derivePathType}", + "Unknown derivation path type found: ${inputsWithKeys[i].derivePathType}", ); } @@ -731,14 +734,14 @@ class NamecoinWallet scriptSigAsm: null, sequence: sequence, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: utxoSigningData[i].utxo.txid, - vout: utxoSigningData[i].utxo.vout, + txid: inputsWithKeys[i].utxo.txid, + vout: inputsWithKeys[i].utxo.vout, ), addresses: - utxoSigningData[i].utxo.address == null + inputsWithKeys[i].utxo.address == null ? [] - : [utxoSigningData[i].utxo.address!], - valueStringSats: utxoSigningData[i].utxo.value.toString(), + : [inputsWithKeys[i].utxo.address!], + valueStringSats: inputsWithKeys[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -808,13 +811,13 @@ class NamecoinWallet try { // Sign the transaction accordingly - for (int i = 0; i < utxoSigningData.length; i++) { - final value = BigInt.from(utxoSigningData[i].utxo.value); - final key = utxoSigningData[i].key!.privateKey!; + for (int i = 0; i < inputsWithKeys.length; i++) { + final value = BigInt.from(inputsWithKeys[i].utxo.value); + final key = inputsWithKeys[i].key!.privateKey!; if (clTx.inputs[i] is coinlib.TaprootKeyInput) { final taproot = coinlib.Taproot( - internalKey: utxoSigningData[i].key!.publicKey, + internalKey: inputsWithKeys[i].key!.publicKey, ); clTx = clTx.signTaproot( @@ -1115,8 +1118,8 @@ class NamecoinWallet final List recipientsAmtArray = [satoshiAmountToSend]; // gather required signing data - final utxoSigningData = - (await fetchBuildTxData( + final inputsWithKeys = + (await addSigningKeys( utxoObjectsToUse.map((e) => StandardInput(e)).toList(), )).whereType().toList(); @@ -1124,7 +1127,7 @@ class NamecoinWallet try { vSizeForOneOutput = (await _createNameTx( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, isForFeeCalcPurposesOnly: true, txData: txData.copyWith( recipients: await helperRecipientsConvert( @@ -1145,7 +1148,7 @@ class NamecoinWallet try { vSizeForTwoOutPuts = (await _createNameTx( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, isForFeeCalcPurposesOnly: true, txData: txData.copyWith( recipients: await helperRecipientsConvert( @@ -1197,7 +1200,7 @@ class NamecoinWallet ); final txnData = await _createNameTx( isForFeeCalcPurposesOnly: false, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( recipientsArray, @@ -1210,7 +1213,7 @@ class NamecoinWallet rawValue: feeForOneOutput, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: utxoSigningData.map((e) => e.utxo).toList(), + usedUTXOs: inputsWithKeys, ); } @@ -1259,7 +1262,7 @@ class NamecoinWallet ); TxData txnData = await _createNameTx( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, isForFeeCalcPurposesOnly: false, txData: txData.copyWith( recipients: await helperRecipientsConvert( @@ -1285,7 +1288,7 @@ class NamecoinWallet ); txnData = await _createNameTx( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, isForFeeCalcPurposesOnly: false, txData: txData.copyWith( recipients: await helperRecipientsConvert( @@ -1301,7 +1304,7 @@ class NamecoinWallet rawValue: feeBeingPaid, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: utxoSigningData.map((e) => e.utxo).toList(), + usedUTXOs: inputsWithKeys, ); } else { // Something went wrong here. It either overshot or undershot the estimated fee amount or the changeOutputSize diff --git a/lib/wallets/wallet/impl/particl_wallet.dart b/lib/wallets/wallet/impl/particl_wallet.dart index 19a9a9e20..08e27cc18 100644 --- a/lib/wallets/wallet/impl/particl_wallet.dart +++ b/lib/wallets/wallet/impl/particl_wallet.dart @@ -3,12 +3,12 @@ import 'dart:typed_data'; import 'package:bitcoindart/bitcoindart.dart' as bitcoindart; import 'package:isar/isar.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/extensions/impl/uint8_list.dart'; @@ -352,7 +352,7 @@ class ParticlWallet @override Future buildTransaction({ required TxData txData, - required covariant List utxoSigningData, + required covariant List inputsWithKeys, }) async { Logging.instance.d("Starting Particl buildTransaction ----------"); @@ -371,8 +371,8 @@ class ParticlWallet ); final List<({Uint8List? output, Uint8List? redeem})> extraData = []; - for (int i = 0; i < utxoSigningData.length; i++) { - final sd = utxoSigningData[i]; + for (int i = 0; i < inputsWithKeys.length; i++) { + final sd = inputsWithKeys[i]; final pubKey = sd.key!.publicKey.data; final bitcoindart.PaymentData? data; @@ -448,11 +448,11 @@ class ParticlWallet final List tempOutputs = []; // Add inputs. - for (var i = 0; i < utxoSigningData.length; i++) { - final txid = utxoSigningData[i].utxo.txid; + for (var i = 0; i < inputsWithKeys.length; i++) { + final txid = inputsWithKeys[i].utxo.txid; txb.addInput( txid, - utxoSigningData[i].utxo.vout, + inputsWithKeys[i].utxo.vout, null, extraData[i].output!, cryptoCurrency.networkParams.bech32Hrp, @@ -464,14 +464,14 @@ class ParticlWallet scriptSigAsm: null, sequence: 0xffffffff - 1, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: utxoSigningData[i].utxo.txid, - vout: utxoSigningData[i].utxo.vout, + txid: inputsWithKeys[i].utxo.txid, + vout: inputsWithKeys[i].utxo.vout, ), addresses: - utxoSigningData[i].utxo.address == null + inputsWithKeys[i].utxo.address == null ? [] - : [utxoSigningData[i].utxo.address!], - valueStringSats: utxoSigningData[i].utxo.value.toString(), + : [inputsWithKeys[i].utxo.address!], + valueStringSats: inputsWithKeys[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -508,15 +508,15 @@ class ParticlWallet // Sign. try { - for (var i = 0; i < utxoSigningData.length; i++) { + for (var i = 0; i < inputsWithKeys.length; i++) { txb.sign( vin: i, keyPair: bitcoindart.ECPair.fromPrivateKey( - utxoSigningData[i].key!.privateKey!.data, + inputsWithKeys[i].key!.privateKey!.data, network: convertedNetwork, - compressed: utxoSigningData[i].key!.privateKey!.compressed, + compressed: inputsWithKeys[i].key!.privateKey!.compressed, ), - witnessValue: utxoSigningData[i].utxo.value, + witnessValue: inputsWithKeys[i].utxo.value, redeemScript: extraData[i].redeem, overridePrefix: cryptoCurrency.networkParams.bech32Hrp, ); diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index d5028093b..2843d4a1a 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -251,13 +251,7 @@ class TezosWallet extends Bip39Wallet { await opList.simulate(); return txData.copyWith( - recipients: [ - TxRecipient( - amount: sendAmount, - address: txData.recipients!.first.address, - isChange: txData.recipients!.first.isChange, - ), - ], + recipients: [txData.recipients!.first.copyWith(amount: sendAmount)], // fee: fee, fee: Amount( rawValue: opList.operations diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart index b632943d0..a8d5e1c65 100644 --- a/lib/wallets/wallet/impl/wownero_wallet.dart +++ b/lib/wallets/wallet/impl/wownero_wallet.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:compat/compat.dart' as lib_monero_compat; import 'package:cs_monero/cs_monero.dart' as lib_monero; +import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/fee_rate_type_enum.dart'; import '../../crypto_currency/crypto_currency.dart'; @@ -59,6 +60,7 @@ class WowneroWallet extends LibMoneroWallet { "WW3iVcnoAY6K9zNdU4qmdvZELefx6xZz4PMpTwUifRkvMQckyadhSPYMVPJhBdYE8P9c27fg9RPmVaWNFx1cDaj61HnetqBiy", amount: amount, isChange: false, + addressType: AddressType.cryptonote, ), ], feeRateType: feeRateType, diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart index cc11b48f2..eea19dbdb 100644 --- a/lib/wallets/wallet/impl/xelis_wallet.dart +++ b/lib/wallets/wallet/impl/xelis_wallet.dart @@ -730,6 +730,7 @@ class XelisWallet extends LibXelisWallet { 'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m', amount: amount, isChange: false, + addressType: AddressType.xelis, ), ]; diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart index 763162fd0..d29e97976 100644 --- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart @@ -11,6 +11,7 @@ import 'package:stack_wallet_backup/generate_password.dart'; import '../../../db/hive/db.dart'; import '../../../models/balance.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/blockchain_data/utxo.dart'; @@ -21,7 +22,6 @@ import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; -import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; diff --git a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart index 2c47a843d..f18cba8d0 100644 --- a/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_salvium_wallet.dart @@ -9,6 +9,7 @@ import 'package:mutex/mutex.dart'; import 'package:stack_wallet_backup/generate_password.dart'; import '../../../models/balance.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/blockchain_data/utxo.dart'; @@ -19,7 +20,6 @@ import '../../../models/keys/cw_key_data.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../models/node_model.dart'; import '../../../models/paymint/fee_object_model.dart'; -import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart index 492f727b0..410f11d2e 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart @@ -2,11 +2,11 @@ import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitbox/src/utils/network.dart' as bitbox_utils; import 'package:isar/isar.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/logger.dart'; import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../../models/tx_data.dart'; @@ -18,7 +18,7 @@ mixin BCashInterface @override Future buildTransaction({ required TxData txData, - required covariant List utxoSigningData, + required covariant List inputsWithKeys, }) async { Logging.instance.d("Starting buildTransaction ----------"); @@ -35,10 +35,10 @@ mixin BCashInterface final List tempOutputs = []; // Add transaction inputs - for (int i = 0; i < utxoSigningData.length; i++) { + for (int i = 0; i < inputsWithKeys.length; i++) { builder.addInput( - utxoSigningData[i].utxo.txid, - utxoSigningData[i].utxo.vout, + inputsWithKeys[i].utxo.txid, + inputsWithKeys[i].utxo.vout, ); tempInputs.add( @@ -47,14 +47,14 @@ mixin BCashInterface scriptSigAsm: null, sequence: 0xffffffff - 1, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: utxoSigningData[i].utxo.txid, - vout: utxoSigningData[i].utxo.vout, + txid: inputsWithKeys[i].utxo.txid, + vout: inputsWithKeys[i].utxo.vout, ), addresses: - utxoSigningData[i].utxo.address == null + inputsWithKeys[i].utxo.address == null ? [] - : [utxoSigningData[i].utxo.address!], - valueStringSats: utxoSigningData[i].utxo.value.toString(), + : [inputsWithKeys[i].utxo.address!], + valueStringSats: inputsWithKeys[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -92,9 +92,9 @@ mixin BCashInterface try { // Sign the transaction accordingly - for (int i = 0; i < utxoSigningData.length; i++) { + for (int i = 0; i < inputsWithKeys.length; i++) { final bitboxEC = bitbox.ECPair.fromPrivateKey( - utxoSigningData[i].key!.privateKey!.data, + inputsWithKeys[i].key!.privateKey!.data, network: bitbox_utils.Network( cryptoCurrency.networkParams.privHDPrefix, cryptoCurrency.networkParams.pubHDPrefix, @@ -103,10 +103,10 @@ mixin BCashInterface cryptoCurrency.networkParams.wifPrefix, cryptoCurrency.networkParams.p2pkhPrefix, ), - compressed: utxoSigningData[i].key!.privateKey!.compressed, + compressed: inputsWithKeys[i].key!.privateKey!.compressed, ); - builder.sign(i, bitboxEC, utxoSigningData[i].utxo.value); + builder.sign(i, bitboxEC, inputsWithKeys[i].utxo.value); } } catch (e, s) { Logging.instance.e( diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 96f13af8b..05ad0a58a 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -11,13 +11,13 @@ import '../../../electrumx_rpc/cached_electrumx_client.dart'; import '../../../electrumx_rpc/client_manager.dart'; import '../../../electrumx_rpc/electrumx_client.dart'; import '../../../models/coinlib/exp2pkh_address.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; import '../../../models/keys/view_only_wallet_data.dart'; import '../../../models/paymint/fee_object_model.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/enums/fee_rate_type_enum.dart'; @@ -85,17 +85,10 @@ mixin ElectrumXInterface final List results = []; for (int i = 0; i < addrs.length; i++) { - // temp mweb hack - AddressType? type; - if (this is MwebInterface) { - final addr = coinlib.Address.fromString( - addrs[i], - cryptoCurrency.networkParams, - ); - if (addr is coinlib.MwebAddress) { - type = AddressType.mweb; - } - } + // assume address is valid at this point so if getAddressType fails for + // some reason default to unknown + final type = + cryptoCurrency.getAddressType(addrs[i]) ?? AddressType.unknown; results.add( TxRecipient( @@ -130,6 +123,7 @@ mixin ElectrumXInterface required bool isSendAllCoinControlUtxos, int additionalOutputs = 0, List? utxos, + BigInt? overrideFeeAmount, }) async { Logging.instance.d("Starting coinSelection ----------"); @@ -145,20 +139,25 @@ mixin ElectrumXInterface final int? satsPerVByte = txData.satsPerVByte; final selectedTxFeeRate = txData.feeRateAmount!; - final List availableOutputs = - utxos ?? - (await mainDB.getUTXOs(walletId).findAll()) - .map((e) => StandardInput(e)) - .toList(); - if (this is MwebInterface && utxos == null) { - final db = Drift.get(walletId); - final mwebUtxos = - await (db.select(db.mwebUtxos) - ..where((e) => e.used.equals(false))).get(); - - for (final e in mwebUtxos) { - availableOutputs.add(MwebInput(e)); + final List availableOutputs; + + if (txData.type == TxType.mweb || txData.type == TxType.mwebPegOut) { + if (utxos == null) { + final db = Drift.get(walletId); + final mwebUtxos = + await (db.select(db.mwebUtxos) + ..where((e) => e.used.equals(false))).get(); + + availableOutputs = mwebUtxos.map((e) => MwebInput(e)).toList(); + } else { + availableOutputs = utxos; } + } else { + availableOutputs = + utxos ?? + (await mainDB.getUTXOs(walletId).findAll()) + .map((e) => StandardInput(e)) + .toList(); } final currentChainHeight = await chainHeight; @@ -253,10 +252,10 @@ mixin ElectrumXInterface final List recipientsAmtArray = [satoshiAmountToSend]; // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + final inputsWithKeys = await addSigningKeys(utxoObjectsToUse); if (isSendAll || isSendAllCoinControlUtxos) { - if (satoshiAmountToSend != satoshisBeingUsed && !txData.isMweb) { + if (satoshiAmountToSend != satoshisBeingUsed) { throw Exception( "Something happened that should never actually happen. " "Please report this error to the developers.", @@ -267,9 +266,10 @@ mixin ElectrumXInterface recipientAddress: recipientAddress, satoshiAmountToSend: satoshiAmountToSend, satoshisBeingUsed: satoshisBeingUsed, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, satsPerVByte: satsPerVByte, feeRatePerKB: selectedTxFeeRate, + overrideFeeAmount: overrideFeeAmount, ); } @@ -277,7 +277,7 @@ mixin ElectrumXInterface try { vSizeForOneOutput = (await buildTransaction( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( [recipientAddress], @@ -297,7 +297,7 @@ mixin ElectrumXInterface try { vSizeForTwoOutPuts = (await buildTransaction( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( [recipientAddress, (await getCurrentChangeAddress())!.value], @@ -317,23 +317,27 @@ mixin ElectrumXInterface } // Assume 1 output, only for recipient and no change - final feeForOneOutput = BigInt.from( - satsPerVByte != null - ? (satsPerVByte * vSizeForOneOutput) - : estimateTxFee( - vSize: vSizeForOneOutput, - feeRatePerKB: selectedTxFeeRate, - ), - ); + final feeForOneOutput = + overrideFeeAmount ?? + BigInt.from( + satsPerVByte != null + ? (satsPerVByte * vSizeForOneOutput) + : estimateTxFee( + vSize: vSizeForOneOutput, + feeRatePerKB: selectedTxFeeRate, + ), + ); // Assume 2 outputs, one for recipient and one for change - final feeForTwoOutputs = BigInt.from( - satsPerVByte != null - ? (satsPerVByte * vSizeForTwoOutPuts) - : estimateTxFee( - vSize: vSizeForTwoOutPuts, - feeRatePerKB: selectedTxFeeRate, - ), - ); + final feeForTwoOutputs = + overrideFeeAmount ?? + BigInt.from( + satsPerVByte != null + ? (satsPerVByte * vSizeForTwoOutPuts) + : estimateTxFee( + vSize: vSizeForTwoOutPuts, + feeRatePerKB: selectedTxFeeRate, + ), + ); Logging.instance.d("feeForTwoOutputs: $feeForTwoOutputs"); Logging.instance.d("feeForOneOutput: $feeForOneOutput"); @@ -346,7 +350,7 @@ mixin ElectrumXInterface Logging.instance.d('Fee being paid: $difference sats'); Logging.instance.d('Estimated fee: $feeForOneOutput'); final txnData = await buildTransaction( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( recipientsArray, @@ -359,11 +363,7 @@ mixin ElectrumXInterface rawValue: feeForOneOutput, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: - utxoSigningData - .whereType() - .map((e) => e.utxo) - .toList(), + usedUTXOs: inputsWithKeys, ); } @@ -412,12 +412,13 @@ mixin ElectrumXInterface Logging.instance.d('Estimated fee: $feeForTwoOutputs'); TxData txnData = await buildTransaction( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( recipientsArray, recipientsAmtArray, ), + usedUTXOs: inputsWithKeys, ), ); @@ -441,12 +442,13 @@ mixin ElectrumXInterface Logging.instance.d('Adjusted Estimated fee: $feeForTwoOutputs'); txnData = await buildTransaction( - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( recipientsArray, recipientsAmtArray, ), + usedUTXOs: inputsWithKeys, ), ); } @@ -456,11 +458,7 @@ mixin ElectrumXInterface rawValue: feeBeingPaid, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: - utxoSigningData - .whereType() - .map((e) => e.utxo) - .toList(), + usedUTXOs: inputsWithKeys, ); } else { // Something went wrong here. It either overshot or undershot the estimated fee amount or the changeOutputSize @@ -480,37 +478,46 @@ mixin ElectrumXInterface required String recipientAddress, required BigInt satoshiAmountToSend, required BigInt satoshisBeingUsed, - required List utxoSigningData, + required List inputsWithKeys, required int? satsPerVByte, required BigInt feeRatePerKB, + BigInt? overrideFeeAmount, }) async { Logging.instance.d("Attempting to send all $cryptoCurrency"); if (txData.recipients!.length != 1) { throw Exception("Send all to more than one recipient not yet supported"); } - final int vSizeForOneOutput = - (await buildTransaction( - utxoSigningData: utxoSigningData, - txData: txData.copyWith( - recipients: await helperRecipientsConvert( - [recipientAddress], - [satoshisBeingUsed - BigInt.one], + BigInt feeForOneOutput; + if (overrideFeeAmount == null) { + final int vSizeForOneOutput = + (await buildTransaction( + inputsWithKeys: inputsWithKeys, + txData: txData.copyWith( + recipients: await helperRecipientsConvert( + [recipientAddress], + [satoshisBeingUsed - BigInt.one], + ), ), - ), - )).vSize!; - BigInt feeForOneOutput = BigInt.from( - satsPerVByte != null - ? (satsPerVByte * vSizeForOneOutput) - : estimateTxFee(vSize: vSizeForOneOutput, feeRatePerKB: feeRatePerKB), - ); + )).vSize!; + feeForOneOutput = BigInt.from( + satsPerVByte != null + ? (satsPerVByte * vSizeForOneOutput) + : estimateTxFee( + vSize: vSizeForOneOutput, + feeRatePerKB: feeRatePerKB, + ), + ); - if (satsPerVByte == null) { - final roughEstimate = - roughFeeEstimate(utxoSigningData.length, 1, feeRatePerKB).raw; - if (feeForOneOutput < roughEstimate) { - feeForOneOutput = roughEstimate; + if (satsPerVByte == null) { + final roughEstimate = + roughFeeEstimate(inputsWithKeys.length, 1, feeRatePerKB).raw; + if (feeForOneOutput < roughEstimate) { + feeForOneOutput = roughEstimate; + } } + } else { + feeForOneOutput = overrideFeeAmount; } final amount = satoshiAmountToSend - feeForOneOutput; @@ -525,7 +532,7 @@ mixin ElectrumXInterface txData: txData.copyWith( recipients: await helperRecipientsConvert([recipientAddress], [amount]), ), - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, ); return data.copyWith( @@ -533,30 +540,26 @@ mixin ElectrumXInterface rawValue: feeForOneOutput, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: - utxoSigningData - .whereType() - .map((e) => e.utxo) - .toList(), + usedUTXOs: inputsWithKeys, ); } - Future> fetchBuildTxData(List utxosToUse) async { + Future> addSigningKeys(List utxosToUse) async { // return data - final List signingData = []; + final List inputsWithKeys = []; try { // Populating the addresses to check for (var i = 0; i < utxosToUse.length; i++) { final input = utxosToUse[i]; if (input is MwebInput) { - signingData.add(input); + inputsWithKeys.add(input); } else if (input is StandardInput) { final derivePathType = cryptoCurrency.addressType( address: input.address!, ); - signingData.add( + inputsWithKeys.add( StandardInput(input.utxo, derivePathType: derivePathType), ); } else { @@ -566,7 +569,7 @@ mixin ElectrumXInterface final root = await getRootHDNode(); - for (final sd in signingData.whereType()) { + for (final sd in inputsWithKeys.whereType()) { coinlib.HDPrivateKey? keys; final address = await mainDB.getAddress(walletId, sd.utxo.address!); if (address?.derivationPath != null) { @@ -608,7 +611,7 @@ mixin ElectrumXInterface sd.key = keys; } - return signingData; + return inputsWithKeys; } catch (e, s) { Logging.instance.e("fetchBuildTxData() threw", error: e, stackTrace: s); rethrow; @@ -618,7 +621,7 @@ mixin ElectrumXInterface /// Builds and signs a transaction Future buildTransaction({ required TxData txData, - required List utxoSigningData, + required List inputsWithKeys, }) async { Logging.instance.d("Starting buildTransaction ----------"); @@ -628,19 +631,8 @@ mixin ElectrumXInterface final List prevOuts = []; - final hasMwebInputs = utxoSigningData.whereType().isNotEmpty; - final hasMwebOutputs = - txData.recipients! - .where((e) => e.addressType == AddressType.mweb) - .isNotEmpty; - - final isMweb = hasMwebOutputs || hasMwebInputs; - - print("IS MEB hasMwebInputs: $hasMwebInputs"); - print("IS MEB hasMwebOutputs: $hasMwebOutputs"); - coinlib.Transaction clTx = coinlib.Transaction( - version: isMweb ? 2 : cryptoCurrency.transactionVersion, + version: txData.type.isMweb() ? 2 : cryptoCurrency.transactionVersion, inputs: [], outputs: [], ); @@ -652,8 +644,8 @@ mixin ElectrumXInterface : 0xffffffff - 1; // Add transaction inputs - for (var i = 0; i < utxoSigningData.length; i++) { - final data = utxoSigningData[i]; + for (var i = 0; i < inputsWithKeys.length; i++) { + final data = inputsWithKeys[i]; if (data is MwebInput) { final address = data.address; @@ -682,7 +674,7 @@ mixin ElectrumXInterface vout: index, ), addresses: [address], - valueStringSats: utxoSigningData[i].value.toString(), + valueStringSats: inputsWithKeys[i].value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -766,9 +758,7 @@ mixin ElectrumXInterface ), ); } else { - throw Exception( - "Unknown input type: ${utxoSigningData[i].runtimeType}", - ); + throw Exception("Unknown input type: ${inputsWithKeys[i].runtimeType}"); } } @@ -826,8 +816,8 @@ mixin ElectrumXInterface try { // Sign the transaction accordingly - for (var i = 0; i < utxoSigningData.length; i++) { - final data = utxoSigningData[i]; + for (var i = 0; i < inputsWithKeys.length; i++) { + final data = inputsWithKeys[i]; if (data is MwebInput) { // do nothing @@ -859,7 +849,7 @@ mixin ElectrumXInterface } } else { throw Exception( - "Unknown input type: ${utxoSigningData[i].runtimeType}", + "Unknown input type: ${inputsWithKeys[i].runtimeType}", ); } } @@ -873,28 +863,32 @@ mixin ElectrumXInterface } return txData.copyWith( - isMweb: isMweb, raw: clTx.toHex(), // dirty shortcut for peercoin's weirdness vSize: this is PeercoinWallet ? clTx.size : clTx.vSize(), - tempTx: TransactionV2( - walletId: walletId, - blockHash: null, - hash: clTx.hashHex, - txid: clTx.txid, - height: null, - timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, - inputs: List.unmodifiable(tempInputs), - outputs: List.unmodifiable(tempOutputs), - version: clTx.version, - type: - tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e) && - txData.paynymAccountLite == null - ? TransactionType.sentToSelf - : TransactionType.outgoing, - subType: TransactionSubType.none, - otherData: null, - ), + tempTx: + txData.type.isMweb() + ? null + : TransactionV2( + walletId: walletId, + blockHash: null, + hash: clTx.hashHex, + txid: clTx.txid, + height: null, + timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000, + inputs: List.unmodifiable(tempInputs), + outputs: List.unmodifiable(tempOutputs), + version: clTx.version, + type: + tempOutputs + .map((e) => e.walletOwns) + .fold(true, (p, e) => p &= e) && + txData.paynymAccountLite == null + ? TransactionType.sentToSelf + : TransactionType.outgoing, + subType: TransactionSubType.none, + otherData: null, + ), ); } @@ -1775,14 +1769,30 @@ mixin ElectrumXInterface txData = txData.copyWith( usedUTXOs: - txData.usedUTXOs!.map((e) => e.copyWith(used: true)).toList(), + txData.usedUTXOs!.map((e) { + if (e is StandardInput) { + return StandardInput( + e.utxo.copyWith(used: true), + derivePathType: e.derivePathType, + ); + } else if (e is MwebInput) { + return MwebInput(e.utxo.copyWith(used: true)); + } else { + return e; + } + }).toList(), // TODO revisit setting these both txHash: txHash, txid: txHash, ); // mark utxos as used - await mainDB.putUTXOs(txData.usedUTXOs!); + await mainDB.putUTXOs( + txData.usedUTXOs! + .whereType() + .map((e) => e.utxo) + .toList(), + ); return await updateSentCachedTxData(txData: txData); } catch (e, s) { @@ -1802,41 +1812,13 @@ mixin ElectrumXInterface throw Exception("No recipients in attempted transaction!"); } - if (this is MwebInterface) { - bool hasMwebOutputs = false; - final recipients = - txData.recipients!.map((e) { - if (e.addressType == null) { - final addr = coinlib.Address.fromString( - e.address, - cryptoCurrency.networkParams, - ); - if (addr is coinlib.MwebAddress) { - hasMwebOutputs = true; - return TxRecipient( - address: e.address, - amount: e.amount, - isChange: e.isChange, - addressType: AddressType.mweb, - ); - } - } - return e; - }).toList(); - txData = txData.copyWith( - recipients: recipients, - isMweb: txData.isMweb || hasMwebOutputs, - ); - print("IS MEB FLAG AAAA: ${txData.isMweb}"); - } - - print("IS MEB FLAG: ${txData.isMweb}"); - final feeRateType = txData.feeRateType; final customSatsPerVByte = txData.satsPerVByte; final feeRateAmount = txData.feeRateAmount; final utxos = txData.utxos; + bool isSendAll = false; + final bool coinControl = utxos != null; final isSendAllCoinControlUtxos = @@ -1844,9 +1826,11 @@ mixin ElectrumXInterface txData.amount!.raw == utxos.map((e) => e.value).fold(BigInt.zero, (p, e) => p + e); + final TxData result; + if (customSatsPerVByte != null) { // check for send all - bool isSendAll = false; + isSendAll = false; if (txData.ignoreCachedBalanceChecks || txData.amount == info.cachedBalance.spendable) { isSendAll = true; @@ -1860,23 +1844,13 @@ mixin ElectrumXInterface isSendAll = true; } - final result = await coinSelection( + result = await coinSelection( txData: txData.copyWith(feeRateAmount: BigInt.from(-1)), isSendAll: isSendAll, utxos: utxos?.toList(), coinControl: coinControl, isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, ); - - Logging.instance.d("PREPARE SEND RESULT: $result"); - - if (result.fee!.raw.toInt() < result.vSize!) { - throw Exception( - "Error in fee calculation: Transaction fee cannot be less than vSize", - ); - } - - return result; } else if (feeRateType is FeeRateType || feeRateAmount is BigInt) { late final BigInt rate; if (feeRateType is FeeRateType) { @@ -1901,51 +1875,58 @@ mixin ElectrumXInterface } // check for send all - bool isSendAll = false; + isSendAll = false; if (txData.amount == info.cachedBalance.spendable) { isSendAll = true; } - final result = await coinSelection( + result = await coinSelection( txData: txData.copyWith(feeRateAmount: rate), isSendAll: isSendAll, utxos: utxos?.toList(), coinControl: coinControl, isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, ); + } else { + throw ArgumentError("Invalid fee rate argument provided!"); + } - Logging.instance.d("prepare send: $result"); - if (result.fee!.raw.toInt() < result.vSize!) { - throw Exception( - "Error in fee calculation: Transaction fee (${result.fee!.raw.toInt()}) cannot " - "be less than vSize (${result.vSize})", - ); - } + if (result.fee!.raw.toInt() < result.vSize!) { + throw Exception( + "Error in fee calculation: Transaction fee (${result.fee!.raw.toInt()}) cannot " + "be less than vSize (${result.vSize})", + ); + } - // mweb - if (result.isMweb) { - final mwebData = await coinSelection( - txData: result.copyWith( - recipients: - result.recipients! - .where( - (e) => - !(e.isChange && e.addressType == AddressType.mweb), - ) - .toList(), - ), - coinControl: coinControl, - isSendAll: isSendAll, - isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, - ); + // mweb + if (result.type.isMweb()) { + final fee = await (this as MwebInterface).mwebFee(txData: result); - return await (this as MwebInterface).processMwebTransaction(mwebData); - } + TxData mwebData = await coinSelection( + txData: result.copyWith( + recipients: result.recipients!.where((e) => !(e.isChange)).toList(), + ), + coinControl: coinControl, + isSendAll: isSendAll, + isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, + overrideFeeAmount: fee.raw, + ); - return result; - } else { - throw ArgumentError("Invalid fee rate argument provided!"); + if (mwebData.type == TxType.mwebPegIn) { + mwebData = await buildTransaction( + txData: mwebData, + inputsWithKeys: mwebData.usedUTXOs!, + ); + } + final data = await (this as MwebInterface).processMwebTransaction( + mwebData, + ); + return data.copyWith(fee: fee); } + + Logging.instance.d("prepare send: $result"); + + return result; } catch (e, s) { Logging.instance.e( "Exception rethrown from prepareSend(): ", diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index 61ac5f030..16ccb0eaf 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -10,10 +10,10 @@ import 'package:mweb_client/mweb_client.dart'; import '../../../db/drift/database.dart'; import '../../../models/balance.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/blocks_remaining_event.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; @@ -240,7 +240,10 @@ mixin MwebInterface blockHash: null, // ?? hash: "", txid: fakeTxid, - timestamp: utxo.blockTime, + timestamp: + utxo.height < 1 + ? DateTime.now().millisecondsSinceEpoch ~/ 1000 + : utxo.blockTime, height: utxo.height, inputs: [], outputs: [ @@ -353,7 +356,68 @@ mixin MwebInterface ), ); - return txData.copyWith(raw: Uint8List.fromList(response.rawTx).toHex); + if (txData.type == TxType.mwebPegIn) { + cl.Transaction clTx = cl.Transaction.fromBytes( + Uint8List.fromList(response.rawTx), + ); + + assert(response.rawTx.toString() == clTx.toBytes().toList().toString()); + final List prevOuts = []; + + for (int i = 0; i < txData.usedUTXOs!.length; i++) { + final data = txData.usedUTXOs![i]; + if (data is StandardInput) { + final prevOutput = cl.Output.fromAddress( + BigInt.from(data.utxo.value), + cl.Address.fromString( + data.utxo.address!, + cryptoCurrency.networkParams, + ), + ); + + prevOuts.add(prevOutput); + } + } + + for (int i = 0; i < txData.usedUTXOs!.length; i++) { + final data = txData.usedUTXOs![i]; + + if (data is MwebInput) { + // do nothing + } else if (data is StandardInput) { + final value = BigInt.from(data.utxo.value); + final key = data.key!.privateKey!; + if (clTx.inputs[i] is cl.TaprootKeyInput) { + final taproot = cl.Taproot(internalKey: data.key!.publicKey); + + clTx = clTx.signTaproot( + inputN: i, + key: taproot.tweakPrivateKey(key), + prevOuts: prevOuts, + ); + } else if (clTx.inputs[i] is cl.LegacyWitnessInput) { + clTx = clTx.signLegacyWitness(inputN: i, key: key, value: value); + } else if (clTx.inputs[i] is cl.LegacyInput) { + clTx = clTx.signLegacy(inputN: i, key: key); + } else if (clTx.inputs[i] is cl.TaprootSingleScriptSigInput) { + clTx = clTx.signTaprootSingleScriptSig( + inputN: i, + key: key, + prevOuts: prevOuts, + ); + } else { + throw Exception( + "Unable to sign input of type ${clTx.inputs[i].runtimeType}", + ); + } + } else { + throw Exception("Unknown input type: ${data.runtimeType}"); + } + } + return txData.copyWith(raw: clTx.toHex()); + } else { + return txData.copyWith(raw: Uint8List.fromList(response.rawTx).toHex); + } } Future _confirmSendMweb({required TxData txData}) async { @@ -375,17 +439,41 @@ mixin MwebInterface final txHash = response.txid; Logging.instance.d("Sent txHash: $txHash"); - txData = txData.copyWith(txHash: txHash, txid: txHash); + txData = txData.copyWith( + usedUTXOs: + txData.usedUTXOs!.map((e) { + if (e is StandardInput) { + return StandardInput( + e.utxo.copyWith(used: true), + derivePathType: e.derivePathType, + ); + } else if (e is MwebInput) { + return MwebInput(e.utxo.copyWith(used: true)); + } else { + return e; + } + }).toList(), + txHash: txHash, + txid: txHash, + ); + + // mark utxos as used + await mainDB.putUTXOs( + txData.usedUTXOs! + .whereType() + .map((e) => e.utxo) + .toList(), + ); // Update used mweb utxos as used in database. They should already have // been marked as isUsed. - if (txData.usedMwebUtxos != null && txData.usedMwebUtxos!.isNotEmpty) { + if (txData.usedUTXOs!.whereType().isNotEmpty) { final db = Drift.get(walletId); await db.transaction(() async { - for (final utxo in txData.usedMwebUtxos!) { + for (final utxo in txData.usedUTXOs!.whereType()) { await db .into(db.mwebUtxos) - .insertOnConflictUpdate(utxo.toCompanion(false)); + .insertOnConflictUpdate(utxo.utxo.toCompanion(false)); } }); } else { @@ -406,6 +494,34 @@ mixin MwebInterface } } + @override + Future prepareSend({required TxData txData}) async { + final hasMwebOutputs = + txData.recipients! + .where((e) => e.addressType == AddressType.mweb) + .isNotEmpty; + if (hasMwebOutputs) { + // assume pegin tx + txData = txData.copyWith(type: TxType.mwebPegIn); + } + + return super.prepareSend(txData: txData); + } + + /// prepare mweb transaction where spending mweb outputs + Future prepareSendMweb({required TxData txData}) async { + final hasMwebOutputs = + txData.recipients! + .where((e) => e.addressType == AddressType.mweb) + .isNotEmpty; + + final type = hasMwebOutputs ? TxType.mweb : TxType.mwebPegOut; + + txData = txData.copyWith(type: type); + + return super.prepareSend(txData: txData); + } + Future anonymizeAllMweb() async { if (!info.isMwebEnabled) { Logging.instance.e( @@ -445,7 +561,7 @@ mixin MwebInterface // TODO finish final txData = await prepareSend( txData: TxData( - isMweb: true, + type: TxType.mwebPegIn, feeRateType: FeeRateType.average, utxos: spendableUtxos.map((e) => StandardInput(e)).toSet(), recipients: [ @@ -460,7 +576,6 @@ mixin MwebInterface fractionDigits: cryptoCurrency.fractionDigits, ), ), - isChange: false, addressType: AddressType.mweb, ), @@ -468,9 +583,7 @@ mixin MwebInterface ), ); - final processed = await processMwebTransaction(txData); - - await _confirmSendMweb(txData: processed); + await _confirmSendMweb(txData: txData); } catch (e, s) { Logging.instance.w( "Exception caught in anonymizeAllMweb(): ", @@ -532,7 +645,7 @@ mixin MwebInterface @override Future confirmSend({required TxData txData}) async { - if (txData.isMweb) { + if (txData.type.isMweb()) { return await _confirmSendMweb(txData: txData); } else { return await super.confirmSend(txData: txData); @@ -816,8 +929,15 @@ mixin MwebInterface } } - // TODO: this is broken Future mwebFee({required TxData txData}) async { + final outputs = txData.recipients!; + final utxos = txData.usedUTXOs!; + + final sumOfUtxosValue = utxos.fold(BigInt.zero, (p, e) => p + e.value); + + final preOutputSum = outputs.fold(BigInt.zero, (p, e) => p + e.amount.raw); + final fee = sumOfUtxosValue - preOutputSum; + final client = await _client; final resp = await client.create( @@ -826,21 +946,19 @@ mixin MwebInterface scanSecret: await _scanSecret, spendSecret: await _spendSecret, feeRatePerKb: Int64(txData.feeRateAmount!.toInt()), - dryRun: false, + dryRun: true, ), ); - final tx = cl.Transaction.fromBytes(Uint8List.fromList(resp.rawTx)); - - final used = [ - ...txData.usedUTXOs?.map((e) => StandardInput(e)) ?? [], - ...txData.usedMwebUtxos?.map((e) => MwebInput(e)) ?? [], - ]; + final processedTx = cl.Transaction.fromBytes( + Uint8List.fromList(resp.rawTx), + ); + BigInt maxBI(BigInt a, BigInt b) => a > b ? a : b; final posUtxos = - used + utxos .where( - (utxo) => tx.inputs.any( + (utxo) => processedTx.inputs.any( (input) => input.prevOut.hash.toHex == Uint8List.fromList( @@ -850,29 +968,21 @@ mixin MwebInterface ) .toList(); - final preInSum = used.fold(BigInt.zero, (p, e) => p + e.value); - final posOutputSum = tx.outputs.fold( + final posOutputSum = processedTx.outputs.fold( BigInt.zero, (acc, output) => acc + output.value, ); final mwebInputSum = - preInSum - posUtxos.fold(BigInt.zero, (p, e) => p + e.value); - - final preOutputSum = txData.recipients!.fold( - BigInt.zero, - (p, e) => p + e.amount.raw, - ); - - final difference = preOutputSum - mwebInputSum; - - final expectedPegin = difference > BigInt.zero ? difference : BigInt.zero; - - final fee = preInSum - preOutputSum; - + sumOfUtxosValue - posUtxos.fold(BigInt.zero, (p, e) => p + e.value); + final expectedPegin = maxBI(BigInt.zero, (preOutputSum - mwebInputSum)); BigInt feeIncrease = posOutputSum - expectedPegin; - if (expectedPegin > BigInt.zero && fee == BigInt.zero) { - feeIncrease += txData.fee!.raw + txData.feeRateAmount! * BigInt.from(41); + + if (expectedPegin > BigInt.zero) { + feeIncrease += BigInt.from( + (txData.feeRateAmount! / BigInt.from(1000) * 41).ceil(), + ); } + return Amount( rawValue: fee + feeIncrease, fractionDigits: cryptoCurrency.fractionDigits, diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart index 1a62c46ef..3ad0425d5 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart @@ -14,11 +14,11 @@ import 'package:tuple/tuple.dart'; import '../../../exceptions/wallet/insufficient_balance_exception.dart'; import '../../../exceptions/wallet/paynym_send_exception.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/bip32_utils.dart'; import '../../../utilities/bip47_utils.dart'; @@ -383,6 +383,7 @@ mixin PaynymInterface address: sendToAddress.value, amount: txData.recipients!.first.amount, isChange: false, + addressType: sendToAddress.type, ), ], ), @@ -526,15 +527,15 @@ mixin PaynymInterface } // gather required signing data - final utxoSigningData = - (await fetchBuildTxData( + final inputsWithKeys = + (await addSigningKeys( utxoObjectsToUse.map((e) => StandardInput(e)).toList(), )).whereType().toList(); final vSizeForNoChange = BigInt.from( (await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: BigInt.zero, // override amount to get around absurd fees error overrideAmountForTesting: satoshisBeingUsed, @@ -544,7 +545,7 @@ mixin PaynymInterface final vSizeForWithChange = BigInt.from( (await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: satoshisBeingUsed - amountToSend.raw, )).item2, ); @@ -587,7 +588,7 @@ mixin PaynymInterface feeForWithChange) { var txn = await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: changeAmount, ); @@ -600,7 +601,7 @@ mixin PaynymInterface feeBeingPaid += BigInt.one; txn = await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: changeAmount, ); } @@ -612,6 +613,7 @@ mixin PaynymInterface address: targetPaymentCodeString, amount: amountToSend, isChange: false, + addressType: AddressType.unknown, ), ], fee: Amount( @@ -619,7 +621,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.toSet(), + utxos: inputsWithKeys.toSet(), note: "PayNym connect", ); @@ -629,7 +631,7 @@ mixin PaynymInterface // than the dust limit. Try without change final txn = await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: BigInt.zero, ); @@ -642,6 +644,7 @@ mixin PaynymInterface address: targetPaymentCodeString, amount: amountToSend, isChange: false, + addressType: AddressType.unknown, ), ], fee: Amount( @@ -649,7 +652,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.toSet(), + utxos: inputsWithKeys.toSet(), note: "PayNym connect", ); @@ -660,7 +663,7 @@ mixin PaynymInterface // build without change here final txn = await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, - utxoSigningData: utxoSigningData, + inputsWithKeys: inputsWithKeys, change: BigInt.zero, ); @@ -673,6 +676,7 @@ mixin PaynymInterface address: targetPaymentCodeString, amount: amountToSend, isChange: false, + addressType: AddressType.unknown, ), ], fee: Amount( @@ -680,7 +684,7 @@ mixin PaynymInterface fractionDigits: cryptoCurrency.fractionDigits, ), vSize: txn.item2, - utxos: utxoSigningData.toSet(), + utxos: inputsWithKeys.toSet(), note: "PayNym connect", ); @@ -709,7 +713,7 @@ mixin PaynymInterface // equal to its vSize Future> _createNotificationTx({ required String targetPaymentCodeString, - required List utxoSigningData, + required List inputsWithKeys, required BigInt change, BigInt? overrideAmountForTesting, }) async { @@ -720,7 +724,7 @@ mixin PaynymInterface ); final myCode = await getPaymentCode(isSegwit: false); - final utxo = utxoSigningData.first.utxo; + final utxo = inputsWithKeys.first.utxo; final txPoint = utxo.txid.toUint8ListFromHex.reversed.toList(); final txPointIndex = utxo.vout; @@ -729,7 +733,7 @@ mixin PaynymInterface final buffer = rev.buffer.asByteData(); buffer.setUint32(txPoint.length, txPointIndex, Endian.little); - final myKeyPair = utxoSigningData.first.key!; + final myKeyPair = inputsWithKeys.first.key!; final S = SecretPoint( myKeyPair.privateKey!.data, @@ -759,8 +763,8 @@ mixin PaynymInterface outputs: [], ); - for (var i = 0; i < utxoSigningData.length; i++) { - final txid = utxoSigningData[i].utxo.txid; + for (var i = 0; i < inputsWithKeys.length; i++) { + final txid = inputsWithKeys[i].utxo.txid; final hash = Uint8List.fromList( txid.toUint8ListFromHex.reversed.toList(), @@ -768,13 +772,13 @@ mixin PaynymInterface final prevOutpoint = coinlib.OutPoint( hash, - utxoSigningData[i].utxo.vout, + inputsWithKeys[i].utxo.vout, ); final prevOutput = coinlib.Output.fromAddress( - BigInt.from(utxoSigningData[i].utxo.value), + BigInt.from(inputsWithKeys[i].utxo.value), coinlib.Address.fromString( - utxoSigningData[i].utxo.address!, + inputsWithKeys[i].utxo.address!, cryptoCurrency.networkParams, ), ); @@ -783,12 +787,12 @@ mixin PaynymInterface final coinlib.Input input; - switch (utxoSigningData[i].derivePathType) { + switch (inputsWithKeys[i].derivePathType) { case DerivePathType.bip44: case DerivePathType.bch44: input = coinlib.P2PKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].key!.publicKey, + publicKey: inputsWithKeys[i].key!.publicKey, sequence: 0xffffffff - 1, ); @@ -806,7 +810,7 @@ mixin PaynymInterface case DerivePathType.bip84: input = coinlib.P2WPKHInput( prevOut: prevOutpoint, - publicKey: utxoSigningData[i].key!.publicKey, + publicKey: inputsWithKeys[i].key!.publicKey, sequence: 0xffffffff - 1, ); @@ -815,7 +819,7 @@ mixin PaynymInterface default: throw UnsupportedError( - "Unknown derivation path type found: ${utxoSigningData[i].derivePathType}", + "Unknown derivation path type found: ${inputsWithKeys[i].derivePathType}", ); } @@ -887,13 +891,13 @@ mixin PaynymInterface } // sign rest of possible inputs - for (int i = 1; i < utxoSigningData.length; i++) { - final value = BigInt.from(utxoSigningData[i].utxo.value); - final key = utxoSigningData[i].key!.privateKey!; + for (int i = 1; i < inputsWithKeys.length; i++) { + final value = BigInt.from(inputsWithKeys[i].utxo.value); + final key = inputsWithKeys[i].key!.privateKey!; if (clTx.inputs[i] is coinlib.TaprootKeyInput) { final taproot = coinlib.Taproot( - internalKey: utxoSigningData[i].key!.publicKey, + internalKey: inputsWithKeys[i].key!.publicKey, ); clTx = clTx.signTaproot( diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart index 0fad30a5e..03a8b6dd6 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart @@ -2,9 +2,9 @@ import 'dart:convert'; import 'package:isar/isar.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/enums/fee_rate_type_enum.dart'; import '../../../utilities/logger.dart'; @@ -95,6 +95,7 @@ mixin RbfInterface fractionDigits: cryptoCurrency.fractionDigits, ), isChange: isChange, + addressType: cryptoCurrency.getAddressType(address)!, ), ); } @@ -147,6 +148,7 @@ mixin RbfInterface fractionDigits: cryptoCurrency.fractionDigits, ), isChange: false, + addressType: recipients.first.addressType, ), ], ); @@ -175,13 +177,11 @@ mixin RbfInterface // update recipients txData.recipients!.insert( indexOfChangeOutput, - TxRecipient( - address: removed.address, + removed.copyWith( amount: Amount( rawValue: newChangeAmount, fractionDigits: cryptoCurrency.fractionDigits, ), - isChange: removed.isChange, ), ); Logging.instance.d( @@ -203,17 +203,13 @@ mixin RbfInterface } return await buildTransaction( txData: txData.copyWith( - usedUTXOs: - txData.utxos! - .whereType() - .map((e) => e.utxo) - .toList(), + usedUTXOs: txData.utxos!.toList(), fee: Amount( rawValue: newFee, fractionDigits: cryptoCurrency.fractionDigits, ), ), - utxoSigningData: await fetchBuildTxData(txData.utxos!.toList()), + inputsWithKeys: await addSigningKeys(txData.utxos!.toList()), ); // if change amount is negative @@ -239,19 +235,17 @@ mixin RbfInterface } txData.recipients!.insert( indexOfChangeOutput, - TxRecipient( - address: removed.address, + removed.copyWith( amount: Amount( rawValue: newChangeAmount, fractionDigits: cryptoCurrency.fractionDigits, ), - isChange: removed.isChange, ), ); final newUtxoSet = { - ...txData.utxos!.whereType().map((e) => e.utxo), - ...extraUtxos, + ...txData.utxos!.whereType(), + ...extraUtxos.map((e) => StandardInput(e)), }; // TODO: remove assert @@ -264,16 +258,14 @@ mixin RbfInterface return await buildTransaction( txData: txData.copyWith( - utxos: newUtxoSet.map((e) => StandardInput(e)).toSet(), + utxos: newUtxoSet, usedUTXOs: newUtxoSet.toList(), fee: Amount( rawValue: newFee, fractionDigits: cryptoCurrency.fractionDigits, ), ), - utxoSigningData: await fetchBuildTxData( - newUtxoSet.map((e) => StandardInput(e)).toList(), - ), + inputsWithKeys: await addSigningKeys(newUtxoSet.toList()), ); } } else { diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index 42cc50a79..d5d5e756d 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -15,11 +15,11 @@ import 'package:logger/logger.dart'; import '../../../db/drift/database.dart' show Drift; import '../../../db/sqlite/firo_cache.dart'; import '../../../models/balance.dart'; +import '../../../models/input.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/isar_models.dart'; -import '../../../models/signing_data.dart'; import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart'; import '../../../services/event_bus/global_event_bus.dart'; import '../../../services/spark_names_service.dart'; @@ -535,15 +535,13 @@ mixin SparkInterface continue; } recipientsWithFeeSubtracted!.add( - TxRecipient( - address: txData.recipients![i].address, + txData.recipients![i].copyWith( amount: Amount( rawValue: txData.recipients![i].amount.raw - (estimatedFee ~/ BigInt.from(totalRecipientCount)), fractionDigits: cryptoCurrency.fractionDigits, ), - isChange: txData.recipients![i].isChange, ), ); @@ -1557,7 +1555,7 @@ mixin SparkInterface for (final utxo in itr) { if (nValueToSelect > nValueIn) { setCoins.add( - (await fetchBuildTxData([ + (await addSigningKeys([ StandardInput(utxo), ])).whereType().first, ); @@ -1921,7 +1919,7 @@ mixin SparkInterface rawValue: nFeeRet, fractionDigits: cryptoCurrency.fractionDigits, ), - usedUTXOs: vin.map((e) => e.utxo).toList(), + usedUTXOs: vin, tempTx: TransactionV2( walletId: walletId, blockHash: null, @@ -2239,6 +2237,7 @@ mixin SparkInterface fractionDigits: cryptoCurrency.fractionDigits, ), isChange: false, + addressType: cryptoCurrency.getAddressType(destinationAddress)!, ), ], ), From 9fdcdc2edd10fcd445d73594ff366aae88705303 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jun 2025 14:54:15 -0600 Subject: [PATCH 140/206] balance fixes --- .../sub_widgets/favorite_card.dart | 5 +++ .../mweb_interface.dart | 37 +++++-------------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/lib/pages/wallets_view/sub_widgets/favorite_card.dart b/lib/pages/wallets_view/sub_widgets/favorite_card.dart index 1133731dc..aad2dc5db 100644 --- a/lib/pages/wallets_view/sub_widgets/favorite_card.dart +++ b/lib/pages/wallets_view/sub_widgets/favorite_card.dart @@ -219,6 +219,11 @@ class _FavoriteCardState extends ConsumerState { ref.watch(pWalletBalanceSecondary(walletId)).total; total += ref.watch(pWalletBalanceTertiary(walletId)).total; + } else if (ref.watch( + pWalletInfo(walletId).select((s) => s.isMwebEnabled), + )) { + total += + ref.watch(pWalletBalanceSecondary(walletId)).total; } Amount fiatTotal = Amount.zero; diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index 16ccb0eaf..226a9a547 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -32,8 +32,6 @@ import 'electrumx_interface.dart'; mixin MwebInterface on ElectrumXInterface implements ExternalWallet { - // TODO - StreamSubscription? _mwebUtxoSubscription; Future get _scanSecret async => @@ -465,23 +463,8 @@ mixin MwebInterface .toList(), ); - // Update used mweb utxos as used in database. They should already have - // been marked as isUsed. - if (txData.usedUTXOs!.whereType().isNotEmpty) { - final db = Drift.get(walletId); - await db.transaction(() async { - for (final utxo in txData.usedUTXOs!.whereType()) { - await db - .into(db.mwebUtxos) - .insertOnConflictUpdate(utxo.utxo.toCompanion(false)); - } - }); - } else { - Logging.instance.w( - "txData.usedMwebUtxos is empty or null when it very " - "likely should not be!", - ); - } + // Update used mweb utxos as used in database + await _checkSpentMwebUtxos(); return await updateSentCachedTxData(txData: txData); } catch (e, s) { @@ -597,9 +580,7 @@ mixin MwebInterface Future _checkSpentMwebUtxos() async { try { final db = Drift.get(walletId); - final mwebUtxos = - await (db.select(db.mwebUtxos) - ..where((e) => e.used.equals(false))).get(); + final mwebUtxos = await db.select(db.mwebUtxos).get(); final client = await _client; @@ -607,16 +588,16 @@ mixin MwebInterface SpentRequest(outputId: mwebUtxos.map((e) => e.outputId)), ); - final updated = mwebUtxos.where( - (e) => spent.outputId.contains(e.outputId), - ); - await db.transaction(() async { - for (final utxo in updated) { + for (final utxo in mwebUtxos) { await db .into(db.mwebUtxos) .insertOnConflictUpdate( - utxo.toCompanion(false).copyWith(used: const Value(true)), + utxo + .toCompanion(false) + .copyWith( + used: Value(spent.outputId.contains(utxo.outputId)), + ), ); } }); From d41b3de12a60ef3afef8c826a1b840e1c9237d2f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jun 2025 15:03:43 -0600 Subject: [PATCH 141/206] use mweb enabled coinlib --- pubspec.lock | 24 +++++++++++-------- scripts/app_config/templates/pubspec.template | 13 +++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 9cbfc4ab4..840c40fee 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -151,10 +151,10 @@ packages: dependency: "direct main" description: name: blockchain_utils - sha256: ebb6c336ba0120de0982c50d8bc597cb494a530bd22bd462895bb5cebde405af + sha256: "1e4f30b98d92f7ccf2eda009a23b53871a1c9b8b6dfa00bb1eb17ec00ae5eeeb" url: "https://pub.dev" source: hosted - version: "3.4.0" + version: "3.6.0" boolean_selector: dependency: transitive description: @@ -352,16 +352,20 @@ packages: coinlib: dependency: "direct overridden" description: - path: "../coinlib/coinlib" - relative: true - source: path + path: coinlib + ref: da1b3659e296660ac2b36f81d155d2362a2b3195 + resolved-ref: da1b3659e296660ac2b36f81d155d2362a2b3195 + url: "https://www.github.com/julian-CStack/coinlib" + source: git version: "4.1.0" coinlib_flutter: dependency: "direct main" description: - path: "../coinlib/coinlib_flutter" - relative: true - source: path + path: coinlib_flutter + ref: da1b3659e296660ac2b36f81d155d2362a2b3195 + resolved-ref: da1b3659e296660ac2b36f81d155d2362a2b3195 + url: "https://www.github.com/julian-CStack/coinlib" + source: git version: "4.0.0" collection: dependency: transitive @@ -1281,10 +1285,10 @@ packages: dependency: "direct main" description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.17.0" io: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index de8d4dadc..494224d6a 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -77,7 +77,6 @@ dependencies: local_auth: ^2.3.0 permission_handler: ^12.0.0+1 flutter_local_notifications: ^17.2.2 - rxdart: ^0.27.3 zxcvbn: ^1.0.0 dart_numerics: ^0.0.6 @@ -174,7 +173,11 @@ dependencies: convert: ^3.1.1 flutter_hooks: ^0.20.3 meta: ^1.9.1 - coinlib_flutter: ^3.0.0 + coinlib_flutter: + git: + url: https://www.github.com/julian-CStack/coinlib + path: coinlib_flutter + ref: da1b3659e296660ac2b36f81d155d2362a2b3195 electrum_adapter: git: url: https://github.com/cypherstack/electrum_adapter.git @@ -264,19 +267,17 @@ dependency_overrides: win32: ^5.5.4 # namecoin names lib needs to be updated - #coinlib: ^3.0.0 - #coinlib_flutter: ^3.0.0 coinlib: git: url: https://www.github.com/julian-CStack/coinlib path: coinlib - ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 + ref: da1b3659e296660ac2b36f81d155d2362a2b3195 coinlib_flutter: git: url: https://www.github.com/julian-CStack/coinlib path: coinlib_flutter - ref: fd5f658320f00a2e281ccaee97c2d2a77b4aa966 + ref: da1b3659e296660ac2b36f81d155d2362a2b3195 bip47: git: From 6fa12ce33657ae784b918a4e420f730f716de781 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jun 2025 15:24:25 -0600 Subject: [PATCH 142/206] fix: mweb tx change --- .../electrumx_interface.dart | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 05ad0a58a..73fb6bb36 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -134,6 +134,14 @@ mixin ElectrumXInterface throw Exception("Coin control used where utxos is null!"); } + Future
      changeAddress() async { + if (txData.type == TxType.mweb || txData.type == TxType.mwebPegOut) { + return (await (this as MwebInterface).getMwebChangeAddress())!; + } else { + return (await getCurrentChangeAddress())!; + } + } + final recipientAddress = txData.recipients!.first.address; final satoshiAmountToSend = txData.amount!.raw; final int? satsPerVByte = txData.satsPerVByte; @@ -300,7 +308,7 @@ mixin ElectrumXInterface inputsWithKeys: inputsWithKeys, txData: txData.copyWith( recipients: await helperRecipientsConvert( - [recipientAddress, (await getCurrentChangeAddress())!.value], + [recipientAddress, (await changeAddress()).value], [ satoshiAmountToSend, maxBI( @@ -393,15 +401,17 @@ mixin ElectrumXInterface // check if possible to add the change output if (changeOutputSize > cryptoCurrency.dustLimit.raw && difference - changeOutputSize == feeForTwoOutputs) { - // generate new change address if current change address has been used - await checkChangeAddressForTransactions(); - final String newChangeAddress = - (await getCurrentChangeAddress())!.value; + if (!(txData.type == TxType.mweb || + txData.type == TxType.mwebPegOut)) { + // generate new change address if current change address has been used + await checkChangeAddressForTransactions(); + } + final newChangeAddress = await changeAddress(); BigInt feeBeingPaid = difference - changeOutputSize; // add change output - recipientsArray.add(newChangeAddress); + recipientsArray.add(newChangeAddress.value); recipientsAmtArray.add(changeOutputSize); Logging.instance.d('2 outputs in tx'); From e2da4711597a59cf8a035f1027f65a42e57a7dd4 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 30 Jun 2025 09:27:39 -0600 Subject: [PATCH 143/206] fix: mweb spend all --- .../wallet_view/sub_widgets/desktop_send.dart | 5 +++- .../electrumx_interface.dart | 26 +++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index a2cf27fb5..567f3a94a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -888,7 +888,10 @@ class _DesktopSendState extends ConsumerState { amount = ref.read(pWalletBalance(walletId)).spendable; break; case BalanceType.private: - amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; + amount = + coin is Firo + ? ref.read(pWalletBalanceTertiary(walletId)).spendable + : ref.read(pWalletBalanceSecondary(walletId)).spendable; break; } } else { diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 73fb6bb36..f36e882d7 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -263,7 +263,8 @@ mixin ElectrumXInterface final inputsWithKeys = await addSigningKeys(utxoObjectsToUse); if (isSendAll || isSendAllCoinControlUtxos) { - if (satoshiAmountToSend != satoshisBeingUsed) { + if ((overrideFeeAmount ?? BigInt.zero) + satoshiAmountToSend != + satoshisBeingUsed) { throw Exception( "Something happened that should never actually happen. " "Please report this error to the developers.", @@ -272,7 +273,6 @@ mixin ElectrumXInterface return await _sendAllBuilder( txData: txData, recipientAddress: recipientAddress, - satoshiAmountToSend: satoshiAmountToSend, satoshisBeingUsed: satoshisBeingUsed, inputsWithKeys: inputsWithKeys, satsPerVByte: satsPerVByte, @@ -486,7 +486,6 @@ mixin ElectrumXInterface Future _sendAllBuilder({ required TxData txData, required String recipientAddress, - required BigInt satoshiAmountToSend, required BigInt satoshisBeingUsed, required List inputsWithKeys, required int? satsPerVByte, @@ -530,9 +529,9 @@ mixin ElectrumXInterface feeForOneOutput = overrideFeeAmount; } - final amount = satoshiAmountToSend - feeForOneOutput; + final satoshiAmountToSend = satoshisBeingUsed - feeForOneOutput; - if (amount.isNegative) { + if (satoshiAmountToSend.isNegative) { throw Exception( "Estimated fee ($feeForOneOutput sats) is greater than balance!", ); @@ -540,7 +539,10 @@ mixin ElectrumXInterface final data = await buildTransaction( txData: txData.copyWith( - recipients: await helperRecipientsConvert([recipientAddress], [amount]), + recipients: await helperRecipientsConvert( + [recipientAddress], + [satoshiAmountToSend], + ), ), inputsWithKeys: inputsWithKeys, ); @@ -1822,6 +1824,10 @@ mixin ElectrumXInterface throw Exception("No recipients in attempted transaction!"); } + final balance = + txData.type == TxType.mweb || txData.type == TxType.mwebPegOut + ? info.cachedBalanceSecondary + : info.cachedBalance; final feeRateType = txData.feeRateType; final customSatsPerVByte = txData.satsPerVByte; final feeRateAmount = txData.feeRateAmount; @@ -1842,15 +1848,13 @@ mixin ElectrumXInterface // check for send all isSendAll = false; if (txData.ignoreCachedBalanceChecks || - txData.amount == info.cachedBalance.spendable) { + txData.amount == balance.spendable) { isSendAll = true; } if (coinControl && this is CpfpInterface && - txData.amount == - (info.cachedBalance.spendable + - info.cachedBalance.pendingSpendable)) { + txData.amount == (balance.spendable + balance.pendingSpendable)) { isSendAll = true; } @@ -1886,7 +1890,7 @@ mixin ElectrumXInterface // check for send all isSendAll = false; - if (txData.amount == info.cachedBalance.spendable) { + if (txData.amount == balance.spendable) { isSendAll = true; } From 74d3c9fd107df24bb138c79466cfabc813f9839e Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 30 Jun 2025 10:45:16 -0600 Subject: [PATCH 144/206] fix: mweb anon all (pegin everything) --- .../electrumx_interface.dart | 11 ++++++---- .../mweb_interface.dart | 21 ++++++++++--------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index f36e882d7..3e0328108 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -265,10 +265,13 @@ mixin ElectrumXInterface if (isSendAll || isSendAllCoinControlUtxos) { if ((overrideFeeAmount ?? BigInt.zero) + satoshiAmountToSend != satoshisBeingUsed) { - throw Exception( - "Something happened that should never actually happen. " - "Please report this error to the developers.", - ); + // hack check + if (txData.type != TxType.mwebPegIn) { + throw Exception( + "Something happened that should never actually happen. " + "Please report this error to the developers.", + ); + } } return await _sendAllBuilder( txData: txData, diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index 226a9a547..dadaf6f5f 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -541,24 +541,25 @@ mixin MwebInterface throw Exception("No available UTXOs found to anonymize"); } + final amount = spendableUtxos.fold( + Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits), + (p, e) => + p + + Amount( + rawValue: BigInt.from(e.value), + fractionDigits: cryptoCurrency.fractionDigits, + ), + ); + // TODO finish final txData = await prepareSend( txData: TxData( type: TxType.mwebPegIn, feeRateType: FeeRateType.average, - utxos: spendableUtxos.map((e) => StandardInput(e)).toSet(), recipients: [ TxRecipient( address: (await getCurrentReceivingMwebAddress())!.value, - amount: spendableUtxos.fold( - Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits), - (p, e) => - p + - Amount( - rawValue: BigInt.from(e.value), - fractionDigits: cryptoCurrency.fractionDigits, - ), - ), + amount: amount, isChange: false, addressType: AddressType.mweb, ), From 0cfa2701fb159b7fb72ff0191f9ed94712ddb953 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 30 Jun 2025 12:19:30 -0600 Subject: [PATCH 145/206] prevent mweb pegin transactions with non witness inputs from being broadcast (and getting dropped by network) --- .../electrumx_interface.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 3e0328108..7e669b07e 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -658,10 +658,14 @@ mixin ElectrumXInterface ? 0xffffffff - 10 : 0xffffffff - 1; + bool isMweb = false; + bool hasNonWitnessInput = false; + // Add transaction inputs for (var i = 0; i < inputsWithKeys.length; i++) { final data = inputsWithKeys[i]; if (data is MwebInput) { + isMweb = true; final address = data.address; final addr = await mainDB.getAddress(walletId, address); @@ -753,6 +757,10 @@ mixin ElectrumXInterface ); } + if (input is! coinlib.WitnessInput) { + hasNonWitnessInput = true; + } + clTx = clTx.addInput(input); tempInputs.add( @@ -798,6 +806,7 @@ mixin ElectrumXInterface } final coinlib.Output output; if (address is coinlib.MwebAddress) { + isMweb = true; output = coinlib.Output.fromProgram( txData.recipients![i].amount.raw, address.program, @@ -829,6 +838,12 @@ mixin ElectrumXInterface ); } + if (isMweb) { + if (hasNonWitnessInput) { + throw Exception("Found non witness input in mweb tx"); + } + } + try { // Sign the transaction accordingly for (var i = 0; i < inputsWithKeys.length; i++) { From 5073be77afdba4ba15d86cb38d6ad6f2102a385d Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 30 Jun 2025 13:14:08 -0600 Subject: [PATCH 146/206] update generated and handle mweb outputs in litecoin electrumx tx parsing --- lib/db/drift/database.g.dart | 953 +++++++----------- .../models/blockchain_data/transaction.g.dart | 2 + .../blockchain_data/v2/transaction_v2.g.dart | 2 + .../tx_v2/transaction_v2_details_view.dart | 427 +++++--- lib/wallets/wallet/impl/litecoin_wallet.dart | 24 +- .../mweb_interface.dart | 42 +- test/cached_electrumx_test.mocks.dart | 15 - .../pages/send_view/send_view_test.mocks.dart | 15 - .../exchange/exchange_view_test.mocks.dart | 15 - .../managed_favorite_test.mocks.dart | 15 - .../node_options_sheet_test.mocks.dart | 15 - .../transaction_card_test.mocks.dart | 15 - 12 files changed, 705 insertions(+), 835 deletions(-) diff --git a/lib/db/drift/database.g.dart b/lib/db/drift/database.g.dart index 416fa4170..67660d3a6 100644 --- a/lib/db/drift/database.g.dart +++ b/lib/db/drift/database.g.dart @@ -12,97 +12,66 @@ class $SparkNamesTable extends SparkNames static const VerificationMeta _nameMeta = const VerificationMeta('name'); @override late final GeneratedColumn name = GeneratedColumn( - 'name', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - $customConstraints: 'UNIQUE NOT NULL COLLATE NOCASE', - ); - static const VerificationMeta _addressMeta = const VerificationMeta( - 'address', - ); + 'name', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'UNIQUE NOT NULL COLLATE NOCASE'); + static const VerificationMeta _addressMeta = + const VerificationMeta('address'); @override late final GeneratedColumn address = GeneratedColumn( - 'address', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - ); - static const VerificationMeta _validUntilMeta = const VerificationMeta( - 'validUntil', - ); + 'address', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _validUntilMeta = + const VerificationMeta('validUntil'); @override late final GeneratedColumn validUntil = GeneratedColumn( - 'valid_until', - aliasedName, - false, - type: DriftSqlType.int, - requiredDuringInsert: true, - ); - static const VerificationMeta _additionalInfoMeta = const VerificationMeta( - 'additionalInfo', - ); + 'valid_until', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _additionalInfoMeta = + const VerificationMeta('additionalInfo'); @override late final GeneratedColumn additionalInfo = GeneratedColumn( - 'additional_info', - aliasedName, - true, - type: DriftSqlType.string, - requiredDuringInsert: false, - ); + 'additional_info', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); @override - List get $columns => [ - name, - address, - validUntil, - additionalInfo, - ]; + List get $columns => + [name, address, validUntil, additionalInfo]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; static const String $name = 'spark_names'; @override - VerificationContext validateIntegrity( - Insertable instance, { - bool isInserting = false, - }) { + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { final context = VerificationContext(); final data = instance.toColumns(true); if (data.containsKey('name')) { context.handle( - _nameMeta, - name.isAcceptableOrUnknown(data['name']!, _nameMeta), - ); + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); } else if (isInserting) { context.missing(_nameMeta); } if (data.containsKey('address')) { - context.handle( - _addressMeta, - address.isAcceptableOrUnknown(data['address']!, _addressMeta), - ); + context.handle(_addressMeta, + address.isAcceptableOrUnknown(data['address']!, _addressMeta)); } else if (isInserting) { context.missing(_addressMeta); } if (data.containsKey('valid_until')) { context.handle( - _validUntilMeta, - validUntil.isAcceptableOrUnknown(data['valid_until']!, _validUntilMeta), - ); + _validUntilMeta, + validUntil.isAcceptableOrUnknown( + data['valid_until']!, _validUntilMeta)); } else if (isInserting) { context.missing(_validUntilMeta); } if (data.containsKey('additional_info')) { context.handle( - _additionalInfoMeta, - additionalInfo.isAcceptableOrUnknown( - data['additional_info']!, _additionalInfoMeta, - ), - ); + additionalInfo.isAcceptableOrUnknown( + data['additional_info']!, _additionalInfoMeta)); } return context; } @@ -113,25 +82,14 @@ class $SparkNamesTable extends SparkNames SparkName map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return SparkName( - name: - attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}name'], - )!, - address: - attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}address'], - )!, - validUntil: - attachedDatabase.typeMapping.read( - DriftSqlType.int, - data['${effectivePrefix}valid_until'], - )!, - additionalInfo: attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}additional_info'], - ), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + address: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}address'])!, + validUntil: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}valid_until'])!, + additionalInfo: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}additional_info']), ); } @@ -146,12 +104,11 @@ class SparkName extends DataClass implements Insertable { final String address; final int validUntil; final String? additionalInfo; - const SparkName({ - required this.name, - required this.address, - required this.validUntil, - this.additionalInfo, - }); + const SparkName( + {required this.name, + required this.address, + required this.validUntil, + this.additionalInfo}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -169,17 +126,14 @@ class SparkName extends DataClass implements Insertable { name: Value(name), address: Value(address), validUntil: Value(validUntil), - additionalInfo: - additionalInfo == null && nullToAbsent - ? const Value.absent() - : Value(additionalInfo), + additionalInfo: additionalInfo == null && nullToAbsent + ? const Value.absent() + : Value(additionalInfo), ); } - factory SparkName.fromJson( - Map json, { - ValueSerializer? serializer, - }) { + factory SparkName.fromJson(Map json, + {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return SparkName( name: serializer.fromJson(json['name']), @@ -199,28 +153,27 @@ class SparkName extends DataClass implements Insertable { }; } - SparkName copyWith({ - String? name, - String? address, - int? validUntil, - Value additionalInfo = const Value.absent(), - }) => SparkName( - name: name ?? this.name, - address: address ?? this.address, - validUntil: validUntil ?? this.validUntil, - additionalInfo: - additionalInfo.present ? additionalInfo.value : this.additionalInfo, - ); + SparkName copyWith( + {String? name, + String? address, + int? validUntil, + Value additionalInfo = const Value.absent()}) => + SparkName( + name: name ?? this.name, + address: address ?? this.address, + validUntil: validUntil ?? this.validUntil, + additionalInfo: + additionalInfo.present ? additionalInfo.value : this.additionalInfo, + ); SparkName copyWithCompanion(SparkNamesCompanion data) { return SparkName( name: data.name.present ? data.name.value : this.name, address: data.address.present ? data.address.value : this.address, validUntil: data.validUntil.present ? data.validUntil.value : this.validUntil, - additionalInfo: - data.additionalInfo.present - ? data.additionalInfo.value - : this.additionalInfo, + additionalInfo: data.additionalInfo.present + ? data.additionalInfo.value + : this.additionalInfo, ); } @@ -266,9 +219,9 @@ class SparkNamesCompanion extends UpdateCompanion { required int validUntil, this.additionalInfo = const Value.absent(), this.rowid = const Value.absent(), - }) : name = Value(name), - address = Value(address), - validUntil = Value(validUntil); + }) : name = Value(name), + address = Value(address), + validUntil = Value(validUntil); static Insertable custom({ Expression? name, Expression? address, @@ -285,13 +238,12 @@ class SparkNamesCompanion extends UpdateCompanion { }); } - SparkNamesCompanion copyWith({ - Value? name, - Value? address, - Value? validUntil, - Value? additionalInfo, - Value? rowid, - }) { + SparkNamesCompanion copyWith( + {Value? name, + Value? address, + Value? validUntil, + Value? additionalInfo, + Value? rowid}) { return SparkNamesCompanion( name: name ?? this.name, address: address ?? this.address, @@ -341,158 +293,103 @@ class $MwebUtxosTable extends MwebUtxos final GeneratedDatabase attachedDatabase; final String? _alias; $MwebUtxosTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _outputIdMeta = const VerificationMeta( - 'outputId', - ); + static const VerificationMeta _outputIdMeta = + const VerificationMeta('outputId'); @override late final GeneratedColumn outputId = GeneratedColumn( - 'output_id', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - ); - static const VerificationMeta _addressMeta = const VerificationMeta( - 'address', - ); + 'output_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _addressMeta = + const VerificationMeta('address'); @override late final GeneratedColumn address = GeneratedColumn( - 'address', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - ); + 'address', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); static const VerificationMeta _valueMeta = const VerificationMeta('value'); @override late final GeneratedColumn value = GeneratedColumn( - 'value', - aliasedName, - false, - type: DriftSqlType.int, - requiredDuringInsert: true, - ); + 'value', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); static const VerificationMeta _heightMeta = const VerificationMeta('height'); @override late final GeneratedColumn height = GeneratedColumn( - 'height', - aliasedName, - false, - type: DriftSqlType.int, - requiredDuringInsert: true, - ); - static const VerificationMeta _blockTimeMeta = const VerificationMeta( - 'blockTime', - ); + 'height', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _blockTimeMeta = + const VerificationMeta('blockTime'); @override late final GeneratedColumn blockTime = GeneratedColumn( - 'block_time', - aliasedName, - false, - type: DriftSqlType.int, - requiredDuringInsert: true, - ); - static const VerificationMeta _blockedMeta = const VerificationMeta( - 'blocked', - ); + 'block_time', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _blockedMeta = + const VerificationMeta('blocked'); @override late final GeneratedColumn blocked = GeneratedColumn( - 'blocked', - aliasedName, - false, - type: DriftSqlType.bool, - requiredDuringInsert: true, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("blocked" IN (0, 1))', - ), - ); + 'blocked', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("blocked" IN (0, 1))')); static const VerificationMeta _usedMeta = const VerificationMeta('used'); @override late final GeneratedColumn used = GeneratedColumn( - 'used', - aliasedName, - false, - type: DriftSqlType.bool, - requiredDuringInsert: true, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("used" IN (0, 1))', - ), - ); + 'used', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("used" IN (0, 1))')); @override - List get $columns => [ - outputId, - address, - value, - height, - blockTime, - blocked, - used, - ]; + List get $columns => + [outputId, address, value, height, blockTime, blocked, used]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; static const String $name = 'mweb_utxos'; @override - VerificationContext validateIntegrity( - Insertable instance, { - bool isInserting = false, - }) { + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { final context = VerificationContext(); final data = instance.toColumns(true); if (data.containsKey('output_id')) { - context.handle( - _outputIdMeta, - outputId.isAcceptableOrUnknown(data['output_id']!, _outputIdMeta), - ); + context.handle(_outputIdMeta, + outputId.isAcceptableOrUnknown(data['output_id']!, _outputIdMeta)); } else if (isInserting) { context.missing(_outputIdMeta); } if (data.containsKey('address')) { - context.handle( - _addressMeta, - address.isAcceptableOrUnknown(data['address']!, _addressMeta), - ); + context.handle(_addressMeta, + address.isAcceptableOrUnknown(data['address']!, _addressMeta)); } else if (isInserting) { context.missing(_addressMeta); } if (data.containsKey('value')) { context.handle( - _valueMeta, - value.isAcceptableOrUnknown(data['value']!, _valueMeta), - ); + _valueMeta, value.isAcceptableOrUnknown(data['value']!, _valueMeta)); } else if (isInserting) { context.missing(_valueMeta); } if (data.containsKey('height')) { - context.handle( - _heightMeta, - height.isAcceptableOrUnknown(data['height']!, _heightMeta), - ); + context.handle(_heightMeta, + height.isAcceptableOrUnknown(data['height']!, _heightMeta)); } else if (isInserting) { context.missing(_heightMeta); } if (data.containsKey('block_time')) { - context.handle( - _blockTimeMeta, - blockTime.isAcceptableOrUnknown(data['block_time']!, _blockTimeMeta), - ); + context.handle(_blockTimeMeta, + blockTime.isAcceptableOrUnknown(data['block_time']!, _blockTimeMeta)); } else if (isInserting) { context.missing(_blockTimeMeta); } if (data.containsKey('blocked')) { - context.handle( - _blockedMeta, - blocked.isAcceptableOrUnknown(data['blocked']!, _blockedMeta), - ); + context.handle(_blockedMeta, + blocked.isAcceptableOrUnknown(data['blocked']!, _blockedMeta)); } else if (isInserting) { context.missing(_blockedMeta); } if (data.containsKey('used')) { context.handle( - _usedMeta, - used.isAcceptableOrUnknown(data['used']!, _usedMeta), - ); + _usedMeta, used.isAcceptableOrUnknown(data['used']!, _usedMeta)); } else if (isInserting) { context.missing(_usedMeta); } @@ -505,41 +402,20 @@ class $MwebUtxosTable extends MwebUtxos MwebUtxo map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return MwebUtxo( - outputId: - attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}output_id'], - )!, - address: - attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}address'], - )!, - value: - attachedDatabase.typeMapping.read( - DriftSqlType.int, - data['${effectivePrefix}value'], - )!, - height: - attachedDatabase.typeMapping.read( - DriftSqlType.int, - data['${effectivePrefix}height'], - )!, - blockTime: - attachedDatabase.typeMapping.read( - DriftSqlType.int, - data['${effectivePrefix}block_time'], - )!, - blocked: - attachedDatabase.typeMapping.read( - DriftSqlType.bool, - data['${effectivePrefix}blocked'], - )!, - used: - attachedDatabase.typeMapping.read( - DriftSqlType.bool, - data['${effectivePrefix}used'], - )!, + outputId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}output_id'])!, + address: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}address'])!, + value: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}value'])!, + height: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}height'])!, + blockTime: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}block_time'])!, + blocked: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}blocked'])!, + used: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}used'])!, ); } @@ -557,15 +433,14 @@ class MwebUtxo extends DataClass implements Insertable { final int blockTime; final bool blocked; final bool used; - const MwebUtxo({ - required this.outputId, - required this.address, - required this.value, - required this.height, - required this.blockTime, - required this.blocked, - required this.used, - }); + const MwebUtxo( + {required this.outputId, + required this.address, + required this.value, + required this.height, + required this.blockTime, + required this.blocked, + required this.used}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -591,10 +466,8 @@ class MwebUtxo extends DataClass implements Insertable { ); } - factory MwebUtxo.fromJson( - Map json, { - ValueSerializer? serializer, - }) { + factory MwebUtxo.fromJson(Map json, + {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return MwebUtxo( outputId: serializer.fromJson(json['outputId']), @@ -620,23 +493,23 @@ class MwebUtxo extends DataClass implements Insertable { }; } - MwebUtxo copyWith({ - String? outputId, - String? address, - int? value, - int? height, - int? blockTime, - bool? blocked, - bool? used, - }) => MwebUtxo( - outputId: outputId ?? this.outputId, - address: address ?? this.address, - value: value ?? this.value, - height: height ?? this.height, - blockTime: blockTime ?? this.blockTime, - blocked: blocked ?? this.blocked, - used: used ?? this.used, - ); + MwebUtxo copyWith( + {String? outputId, + String? address, + int? value, + int? height, + int? blockTime, + bool? blocked, + bool? used}) => + MwebUtxo( + outputId: outputId ?? this.outputId, + address: address ?? this.address, + value: value ?? this.value, + height: height ?? this.height, + blockTime: blockTime ?? this.blockTime, + blocked: blocked ?? this.blocked, + used: used ?? this.used, + ); MwebUtxo copyWithCompanion(MwebUtxosCompanion data) { return MwebUtxo( outputId: data.outputId.present ? data.outputId.value : this.outputId, @@ -707,13 +580,13 @@ class MwebUtxosCompanion extends UpdateCompanion { required bool blocked, required bool used, this.rowid = const Value.absent(), - }) : outputId = Value(outputId), - address = Value(address), - value = Value(value), - height = Value(height), - blockTime = Value(blockTime), - blocked = Value(blocked), - used = Value(used); + }) : outputId = Value(outputId), + address = Value(address), + value = Value(value), + height = Value(height), + blockTime = Value(blockTime), + blocked = Value(blocked), + used = Value(used); static Insertable custom({ Expression? outputId, Expression? address, @@ -736,16 +609,15 @@ class MwebUtxosCompanion extends UpdateCompanion { }); } - MwebUtxosCompanion copyWith({ - Value? outputId, - Value? address, - Value? value, - Value? height, - Value? blockTime, - Value? blocked, - Value? used, - Value? rowid, - }) { + MwebUtxosCompanion copyWith( + {Value? outputId, + Value? address, + Value? value, + Value? height, + Value? blockTime, + Value? blocked, + Value? used, + Value? rowid}) { return MwebUtxosCompanion( outputId: outputId ?? this.outputId, address: address ?? this.address, @@ -816,22 +688,20 @@ abstract class _$WalletDatabase extends GeneratedDatabase { List get allSchemaEntities => [sparkNames, mwebUtxos]; } -typedef $$SparkNamesTableCreateCompanionBuilder = - SparkNamesCompanion Function({ - required String name, - required String address, - required int validUntil, - Value additionalInfo, - Value rowid, - }); -typedef $$SparkNamesTableUpdateCompanionBuilder = - SparkNamesCompanion Function({ - Value name, - Value address, - Value validUntil, - Value additionalInfo, - Value rowid, - }); +typedef $$SparkNamesTableCreateCompanionBuilder = SparkNamesCompanion Function({ + required String name, + required String address, + required int validUntil, + Value additionalInfo, + Value rowid, +}); +typedef $$SparkNamesTableUpdateCompanionBuilder = SparkNamesCompanion Function({ + Value name, + Value address, + Value validUntil, + Value additionalInfo, + Value rowid, +}); class $$SparkNamesTableFilterComposer extends Composer<_$WalletDatabase, $SparkNamesTable> { @@ -843,24 +713,17 @@ class $$SparkNamesTableFilterComposer super.$removeJoinBuilderFromRootComposer, }); ColumnFilters get name => $composableBuilder( - column: $table.name, - builder: (column) => ColumnFilters(column), - ); + column: $table.name, builder: (column) => ColumnFilters(column)); ColumnFilters get address => $composableBuilder( - column: $table.address, - builder: (column) => ColumnFilters(column), - ); + column: $table.address, builder: (column) => ColumnFilters(column)); ColumnFilters get validUntil => $composableBuilder( - column: $table.validUntil, - builder: (column) => ColumnFilters(column), - ); + column: $table.validUntil, builder: (column) => ColumnFilters(column)); ColumnFilters get additionalInfo => $composableBuilder( - column: $table.additionalInfo, - builder: (column) => ColumnFilters(column), - ); + column: $table.additionalInfo, + builder: (column) => ColumnFilters(column)); } class $$SparkNamesTableOrderingComposer @@ -873,24 +736,17 @@ class $$SparkNamesTableOrderingComposer super.$removeJoinBuilderFromRootComposer, }); ColumnOrderings get name => $composableBuilder( - column: $table.name, - builder: (column) => ColumnOrderings(column), - ); + column: $table.name, builder: (column) => ColumnOrderings(column)); ColumnOrderings get address => $composableBuilder( - column: $table.address, - builder: (column) => ColumnOrderings(column), - ); + column: $table.address, builder: (column) => ColumnOrderings(column)); ColumnOrderings get validUntil => $composableBuilder( - column: $table.validUntil, - builder: (column) => ColumnOrderings(column), - ); + column: $table.validUntil, builder: (column) => ColumnOrderings(column)); ColumnOrderings get additionalInfo => $composableBuilder( - column: $table.additionalInfo, - builder: (column) => ColumnOrderings(column), - ); + column: $table.additionalInfo, + builder: (column) => ColumnOrderings(column)); } class $$SparkNamesTableAnnotationComposer @@ -909,127 +765,101 @@ class $$SparkNamesTableAnnotationComposer $composableBuilder(column: $table.address, builder: (column) => column); GeneratedColumn get validUntil => $composableBuilder( - column: $table.validUntil, - builder: (column) => column, - ); + column: $table.validUntil, builder: (column) => column); GeneratedColumn get additionalInfo => $composableBuilder( - column: $table.additionalInfo, - builder: (column) => column, - ); + column: $table.additionalInfo, builder: (column) => column); } -class $$SparkNamesTableTableManager - extends - RootTableManager< - _$WalletDatabase, - $SparkNamesTable, - SparkName, - $$SparkNamesTableFilterComposer, - $$SparkNamesTableOrderingComposer, - $$SparkNamesTableAnnotationComposer, - $$SparkNamesTableCreateCompanionBuilder, - $$SparkNamesTableUpdateCompanionBuilder, - ( - SparkName, - BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>, - ), - SparkName, - PrefetchHooks Function() - > { +class $$SparkNamesTableTableManager extends RootTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), + SparkName, + PrefetchHooks Function()> { $$SparkNamesTableTableManager(_$WalletDatabase db, $SparkNamesTable table) - : super( - TableManagerState( + : super(TableManagerState( db: db, table: table, - createFilteringComposer: - () => $$SparkNamesTableFilterComposer($db: db, $table: table), - createOrderingComposer: - () => $$SparkNamesTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: - () => $$SparkNamesTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: - ({ - Value name = const Value.absent(), - Value address = const Value.absent(), - Value validUntil = const Value.absent(), - Value additionalInfo = const Value.absent(), - Value rowid = const Value.absent(), - }) => SparkNamesCompanion( - name: name, - address: address, - validUntil: validUntil, - additionalInfo: additionalInfo, - rowid: rowid, - ), - createCompanionCallback: - ({ - required String name, - required String address, - required int validUntil, - Value additionalInfo = const Value.absent(), - Value rowid = const Value.absent(), - }) => SparkNamesCompanion.insert( - name: name, - address: address, - validUntil: validUntil, - additionalInfo: additionalInfo, - rowid: rowid, - ), - withReferenceMapper: - (p0) => - p0 - .map( - (e) => ( - e.readTable(table), - BaseReferences(db, table, e), - ), - ) - .toList(), + createFilteringComposer: () => + $$SparkNamesTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SparkNamesTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$SparkNamesTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value name = const Value.absent(), + Value address = const Value.absent(), + Value validUntil = const Value.absent(), + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SparkNamesCompanion( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + createCompanionCallback: ({ + required String name, + required String address, + required int validUntil, + Value additionalInfo = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SparkNamesCompanion.insert( + name: name, + address: address, + validUntil: validUntil, + additionalInfo: additionalInfo, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), prefetchHooksCallback: null, - ), - ); + )); } -typedef $$SparkNamesTableProcessedTableManager = - ProcessedTableManager< - _$WalletDatabase, - $SparkNamesTable, - SparkName, - $$SparkNamesTableFilterComposer, - $$SparkNamesTableOrderingComposer, - $$SparkNamesTableAnnotationComposer, - $$SparkNamesTableCreateCompanionBuilder, - $$SparkNamesTableUpdateCompanionBuilder, - ( - SparkName, - BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>, - ), - SparkName, - PrefetchHooks Function() - >; -typedef $$MwebUtxosTableCreateCompanionBuilder = - MwebUtxosCompanion Function({ - required String outputId, - required String address, - required int value, - required int height, - required int blockTime, - required bool blocked, - required bool used, - Value rowid, - }); -typedef $$MwebUtxosTableUpdateCompanionBuilder = - MwebUtxosCompanion Function({ - Value outputId, - Value address, - Value value, - Value height, - Value blockTime, - Value blocked, - Value used, - Value rowid, - }); +typedef $$SparkNamesTableProcessedTableManager = ProcessedTableManager< + _$WalletDatabase, + $SparkNamesTable, + SparkName, + $$SparkNamesTableFilterComposer, + $$SparkNamesTableOrderingComposer, + $$SparkNamesTableAnnotationComposer, + $$SparkNamesTableCreateCompanionBuilder, + $$SparkNamesTableUpdateCompanionBuilder, + (SparkName, BaseReferences<_$WalletDatabase, $SparkNamesTable, SparkName>), + SparkName, + PrefetchHooks Function()>; +typedef $$MwebUtxosTableCreateCompanionBuilder = MwebUtxosCompanion Function({ + required String outputId, + required String address, + required int value, + required int height, + required int blockTime, + required bool blocked, + required bool used, + Value rowid, +}); +typedef $$MwebUtxosTableUpdateCompanionBuilder = MwebUtxosCompanion Function({ + Value outputId, + Value address, + Value value, + Value height, + Value blockTime, + Value blocked, + Value used, + Value rowid, +}); class $$MwebUtxosTableFilterComposer extends Composer<_$WalletDatabase, $MwebUtxosTable> { @@ -1041,39 +871,25 @@ class $$MwebUtxosTableFilterComposer super.$removeJoinBuilderFromRootComposer, }); ColumnFilters get outputId => $composableBuilder( - column: $table.outputId, - builder: (column) => ColumnFilters(column), - ); + column: $table.outputId, builder: (column) => ColumnFilters(column)); ColumnFilters get address => $composableBuilder( - column: $table.address, - builder: (column) => ColumnFilters(column), - ); + column: $table.address, builder: (column) => ColumnFilters(column)); ColumnFilters get value => $composableBuilder( - column: $table.value, - builder: (column) => ColumnFilters(column), - ); + column: $table.value, builder: (column) => ColumnFilters(column)); ColumnFilters get height => $composableBuilder( - column: $table.height, - builder: (column) => ColumnFilters(column), - ); + column: $table.height, builder: (column) => ColumnFilters(column)); ColumnFilters get blockTime => $composableBuilder( - column: $table.blockTime, - builder: (column) => ColumnFilters(column), - ); + column: $table.blockTime, builder: (column) => ColumnFilters(column)); ColumnFilters get blocked => $composableBuilder( - column: $table.blocked, - builder: (column) => ColumnFilters(column), - ); + column: $table.blocked, builder: (column) => ColumnFilters(column)); ColumnFilters get used => $composableBuilder( - column: $table.used, - builder: (column) => ColumnFilters(column), - ); + column: $table.used, builder: (column) => ColumnFilters(column)); } class $$MwebUtxosTableOrderingComposer @@ -1086,39 +902,25 @@ class $$MwebUtxosTableOrderingComposer super.$removeJoinBuilderFromRootComposer, }); ColumnOrderings get outputId => $composableBuilder( - column: $table.outputId, - builder: (column) => ColumnOrderings(column), - ); + column: $table.outputId, builder: (column) => ColumnOrderings(column)); ColumnOrderings get address => $composableBuilder( - column: $table.address, - builder: (column) => ColumnOrderings(column), - ); + column: $table.address, builder: (column) => ColumnOrderings(column)); ColumnOrderings get value => $composableBuilder( - column: $table.value, - builder: (column) => ColumnOrderings(column), - ); + column: $table.value, builder: (column) => ColumnOrderings(column)); ColumnOrderings get height => $composableBuilder( - column: $table.height, - builder: (column) => ColumnOrderings(column), - ); + column: $table.height, builder: (column) => ColumnOrderings(column)); ColumnOrderings get blockTime => $composableBuilder( - column: $table.blockTime, - builder: (column) => ColumnOrderings(column), - ); + column: $table.blockTime, builder: (column) => ColumnOrderings(column)); ColumnOrderings get blocked => $composableBuilder( - column: $table.blocked, - builder: (column) => ColumnOrderings(column), - ); + column: $table.blocked, builder: (column) => ColumnOrderings(column)); ColumnOrderings get used => $composableBuilder( - column: $table.used, - builder: (column) => ColumnOrderings(column), - ); + column: $table.used, builder: (column) => ColumnOrderings(column)); } class $$MwebUtxosTableAnnotationComposer @@ -1152,104 +954,87 @@ class $$MwebUtxosTableAnnotationComposer $composableBuilder(column: $table.used, builder: (column) => column); } -class $$MwebUtxosTableTableManager - extends - RootTableManager< - _$WalletDatabase, - $MwebUtxosTable, - MwebUtxo, - $$MwebUtxosTableFilterComposer, - $$MwebUtxosTableOrderingComposer, - $$MwebUtxosTableAnnotationComposer, - $$MwebUtxosTableCreateCompanionBuilder, - $$MwebUtxosTableUpdateCompanionBuilder, - ( - MwebUtxo, - BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>, - ), - MwebUtxo, - PrefetchHooks Function() - > { +class $$MwebUtxosTableTableManager extends RootTableManager< + _$WalletDatabase, + $MwebUtxosTable, + MwebUtxo, + $$MwebUtxosTableFilterComposer, + $$MwebUtxosTableOrderingComposer, + $$MwebUtxosTableAnnotationComposer, + $$MwebUtxosTableCreateCompanionBuilder, + $$MwebUtxosTableUpdateCompanionBuilder, + (MwebUtxo, BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>), + MwebUtxo, + PrefetchHooks Function()> { $$MwebUtxosTableTableManager(_$WalletDatabase db, $MwebUtxosTable table) - : super( - TableManagerState( + : super(TableManagerState( db: db, table: table, - createFilteringComposer: - () => $$MwebUtxosTableFilterComposer($db: db, $table: table), - createOrderingComposer: - () => $$MwebUtxosTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: - () => $$MwebUtxosTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: - ({ - Value outputId = const Value.absent(), - Value address = const Value.absent(), - Value value = const Value.absent(), - Value height = const Value.absent(), - Value blockTime = const Value.absent(), - Value blocked = const Value.absent(), - Value used = const Value.absent(), - Value rowid = const Value.absent(), - }) => MwebUtxosCompanion( - outputId: outputId, - address: address, - value: value, - height: height, - blockTime: blockTime, - blocked: blocked, - used: used, - rowid: rowid, - ), - createCompanionCallback: - ({ - required String outputId, - required String address, - required int value, - required int height, - required int blockTime, - required bool blocked, - required bool used, - Value rowid = const Value.absent(), - }) => MwebUtxosCompanion.insert( - outputId: outputId, - address: address, - value: value, - height: height, - blockTime: blockTime, - blocked: blocked, - used: used, - rowid: rowid, - ), - withReferenceMapper: - (p0) => - p0 - .map( - (e) => ( - e.readTable(table), - BaseReferences(db, table, e), - ), - ) - .toList(), + createFilteringComposer: () => + $$MwebUtxosTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$MwebUtxosTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$MwebUtxosTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value outputId = const Value.absent(), + Value address = const Value.absent(), + Value value = const Value.absent(), + Value height = const Value.absent(), + Value blockTime = const Value.absent(), + Value blocked = const Value.absent(), + Value used = const Value.absent(), + Value rowid = const Value.absent(), + }) => + MwebUtxosCompanion( + outputId: outputId, + address: address, + value: value, + height: height, + blockTime: blockTime, + blocked: blocked, + used: used, + rowid: rowid, + ), + createCompanionCallback: ({ + required String outputId, + required String address, + required int value, + required int height, + required int blockTime, + required bool blocked, + required bool used, + Value rowid = const Value.absent(), + }) => + MwebUtxosCompanion.insert( + outputId: outputId, + address: address, + value: value, + height: height, + blockTime: blockTime, + blocked: blocked, + used: used, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), prefetchHooksCallback: null, - ), - ); + )); } -typedef $$MwebUtxosTableProcessedTableManager = - ProcessedTableManager< - _$WalletDatabase, - $MwebUtxosTable, - MwebUtxo, - $$MwebUtxosTableFilterComposer, - $$MwebUtxosTableOrderingComposer, - $$MwebUtxosTableAnnotationComposer, - $$MwebUtxosTableCreateCompanionBuilder, - $$MwebUtxosTableUpdateCompanionBuilder, - (MwebUtxo, BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>), - MwebUtxo, - PrefetchHooks Function() - >; +typedef $$MwebUtxosTableProcessedTableManager = ProcessedTableManager< + _$WalletDatabase, + $MwebUtxosTable, + MwebUtxo, + $$MwebUtxosTableFilterComposer, + $$MwebUtxosTableOrderingComposer, + $$MwebUtxosTableAnnotationComposer, + $$MwebUtxosTableCreateCompanionBuilder, + $$MwebUtxosTableUpdateCompanionBuilder, + (MwebUtxo, BaseReferences<_$WalletDatabase, $MwebUtxosTable, MwebUtxo>), + MwebUtxo, + PrefetchHooks Function()>; class $WalletDatabaseManager { final _$WalletDatabase _db; diff --git a/lib/models/isar/models/blockchain_data/transaction.g.dart b/lib/models/isar/models/blockchain_data/transaction.g.dart index 0d34d133d..3d9a3d409 100644 --- a/lib/models/isar/models/blockchain_data/transaction.g.dart +++ b/lib/models/isar/models/blockchain_data/transaction.g.dart @@ -368,6 +368,7 @@ const _TransactionsubTypeEnumValueMap = { 'sparkMint': 6, 'sparkSpend': 7, 'ordinal': 8, + 'mweb': 9, }; const _TransactionsubTypeValueEnumMap = { 0: TransactionSubType.none, @@ -379,6 +380,7 @@ const _TransactionsubTypeValueEnumMap = { 6: TransactionSubType.sparkMint, 7: TransactionSubType.sparkSpend, 8: TransactionSubType.ordinal, + 9: TransactionSubType.mweb, }; const _TransactiontypeEnumValueMap = { 'outgoing': 0, diff --git a/lib/models/isar/models/blockchain_data/v2/transaction_v2.g.dart b/lib/models/isar/models/blockchain_data/v2/transaction_v2.g.dart index 68d8a18c5..6c2ffde6d 100644 --- a/lib/models/isar/models/blockchain_data/v2/transaction_v2.g.dart +++ b/lib/models/isar/models/blockchain_data/v2/transaction_v2.g.dart @@ -389,6 +389,7 @@ const _TransactionV2subTypeEnumValueMap = { 'sparkMint': 6, 'sparkSpend': 7, 'ordinal': 8, + 'mweb': 9, }; const _TransactionV2subTypeValueEnumMap = { 0: TransactionSubType.none, @@ -400,6 +401,7 @@ const _TransactionV2subTypeValueEnumMap = { 6: TransactionSubType.sparkMint, 7: TransactionSubType.sparkSpend, 8: TransactionSubType.ordinal, + 9: TransactionSubType.mweb, }; const _TransactionV2typeEnumValueMap = { 'outgoing': 0, diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index c6ff6c0d5..c2a7e9adf 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -1852,147 +1852,306 @@ class _TransactionV2DetailsViewState isDesktop ? const _Divider() : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: !isDesktop, - builder: - (child) => Row( - children: [ - Expanded(child: child), - SimpleCopyButton( - data: _transaction.txid, + + _transaction.txid.startsWith("mweb_outputId_") && + _transaction.subType == + TransactionSubType.mweb + ? RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: !isDesktop, + builder: + (child) => Row( + children: [ + Expanded(child: child), + SimpleCopyButton( + data: _transaction + .txid + .replaceFirst( + "mweb_outputId_", + "", + ), + ), + ], ), - ], + child: Text( + "MWEB Output ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - child: Text( - "Transaction ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), + ), + const SizedBox(height: 8), + SelectableText( + _transaction.txid.replaceFirst( + "mweb_outputId_", + "", + ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // if (coin is Litecoin && + // coin.network == + // CryptoCurrencyNetwork + // .main) + // const SizedBox(height: 8), + // if (coin is Litecoin && + // coin.network == + // CryptoCurrencyNetwork + // .main) + // CustomTextButton( + // text: + // "Open in block explorer", + // onTap: () async { + // final uri = + // getBlockExplorerTransactionUrlFor( + // coin: coin, + // txid: _transaction + // .txid + // .replaceFirst( + // "mweb_outputId_", + // "", + // ), + // ); + // + // if (ref + // .read( + // prefsChangeNotifierProvider, + // ) + // .hideBlockExplorerWarning == + // false) { + // final shouldContinue = + // await showExplorerWarning( + // "${uri.scheme}://${uri.host}", + // ); + // + // if (!shouldContinue) { + // return; + // } + // } + // try { + // await launchUrl( + // uri, + // mode: + // LaunchMode + // .externalApplication, + // ); + // } catch (_) { + // if (context.mounted) { + // unawaited( + // showDialog( + // context: context, + // builder: + // ( + // _, + // ) => StackOkDialog( + // title: + // "Could not open in block explorer", + // message: + // "Failed to open \"${uri.toString()}\"", + // ), + // ), + // ); + // } + // } + // }, + // ), + ], ), - const SizedBox(height: 8), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.txid, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + ), + if (isDesktop) + const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: _transaction.txid + .replaceFirst( + "mweb_outputId_", + "", + ), ), - if (coin is! Epiccash) - const SizedBox(height: 8), - if (coin is! Epiccash) - CustomTextButton( - text: "Open in block explorer", - onTap: () async { - final uri = - getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); - - if (ref - .read( - prefsChangeNotifierProvider, + ], + ), + ) + : RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: !isDesktop, + builder: + (child) => Row( + children: [ + Expanded(child: child), + SimpleCopyButton( + data: + _transaction.txid, + ), + ], + ), + child: Text( + "Transaction ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ), + const SizedBox(height: 8), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.txid, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - .hideBlockExplorerWarning == - false) { - final shouldContinue = - await showExplorerWarning( - "${uri.scheme}://${uri.host}", - ); + : STextStyles.itemSubtitle12( + context, + ), + ), + if (coin is! Epiccash) + const SizedBox(height: 8), + if (coin is! Epiccash) + CustomTextButton( + text: + "Open in block explorer", + onTap: () async { + final uri = + getBlockExplorerTransactionUrlFor( + coin: coin, + txid: + _transaction.txid, + ); + + if (ref + .read( + prefsChangeNotifierProvider, + ) + .hideBlockExplorerWarning == + false) { + final shouldContinue = + await showExplorerWarning( + "${uri.scheme}://${uri.host}", + ); - if (!shouldContinue) { - return; - } - } - - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - try { - await launchUrl( - uri, - mode: - LaunchMode - .externalApplication, - ); - } catch (_) { - if (context.mounted) { - unawaited( - showDialog( - context: context, - builder: - ( - _, - ) => StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), - ), - ); - } - } finally { - // Future.delayed( - // const Duration(seconds: 1), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - } - }, - ), - // ), - // ), - ], - ), + if (!shouldContinue) { + return; + } + } + + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + try { + await launchUrl( + uri, + mode: + LaunchMode + .externalApplication, + ); + } catch (_) { + if (context.mounted) { + unawaited( + showDialog( + context: context, + builder: + ( + _, + ) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), + ), + ); + } + } finally { + // Future.delayed( + // const Duration(seconds: 1), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); + } + }, + ), + // ), + // ), + ], + ), + ), + if (isDesktop) + const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: _transaction.txid, + ), + ], ), - if (isDesktop) const SizedBox(width: 12), - if (isDesktop) - IconCopyButton(data: _transaction.txid), - ], - ), - ), + ), // if ((coin is FiroTestNet || coin is Firo) && // _transaction.subType == "mint") // const SizedBox( diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index 82769ee29..af69c019d 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:isar/isar.dart'; +import '../../../db/drift/database.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; @@ -232,9 +233,26 @@ class LitecoinWallet } outputs.add(output); - } catch (e, s) { - // TODO: mweb output parsing - Logging.instance.e("TODO", error: e, stackTrace: s); + } catch (_) { + if (outputJson["ismweb"] == true) { + final outputId = outputJson["output_id"] as String; + + final db = Drift.get(walletId); + + final mwebUtxo = + await (db.select( + db.mwebUtxos, + )..where((e) => e.outputId.equals(outputId))).getSingleOrNull(); + + final output = OutputV2.isarCantDoRequiredInDefaultConstructor( + scriptPubKeyHex: "mweb", + scriptPubKeyAsm: null, + valueStringSats: mwebUtxo?.value.toString() ?? "0", + addresses: [outputId], + walletOwns: mwebUtxo != null, + ); + outputs.add(output); + } } } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index dadaf6f5f..d37f74fa1 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -177,6 +177,7 @@ mixin MwebInterface Future _stopUpdateMwebUtxos() async => await _mwebUtxoSubscription?.cancel(); + Future _startUpdateMwebUtxos() async { await _stopUpdateMwebUtxos(); @@ -215,19 +216,17 @@ mixin MwebInterface (e) => e.outputId.equals(utxo.outputId), )).getSingleOrNull(); - await db - .into(db.mwebUtxos) - .insertOnConflictUpdate( - MwebUtxosCompanion( - outputId: Value(prev?.outputId ?? utxo.outputId), - address: Value(prev?.address ?? utxo.address), - value: Value(utxo.value.toInt()), - height: Value(utxo.height), - blockTime: Value(utxo.blockTime), - blocked: Value(prev?.blocked ?? false), - used: Value(prev?.used ?? false), - ), - ); + final newUtxo = MwebUtxosCompanion( + outputId: Value(prev?.outputId ?? utxo.outputId), + address: Value(prev?.address ?? utxo.address), + value: Value(utxo.value.toInt()), + height: Value(utxo.height), + blockTime: Value(utxo.blockTime), + blocked: Value(prev?.blocked ?? false), + used: Value(prev?.used ?? false), + ); + + await db.into(db.mwebUtxos).insertOnConflictUpdate(newUtxo); }); // TODO get real txid one day @@ -268,7 +267,7 @@ mixin MwebInterface await mainDB.updateOrPutTransactionV2s([tx]); - await updateBalance(mwebOnly: true); + await updateBalance(); if (utxo.height > fromHeight) { await info.updateOtherData( @@ -655,12 +654,9 @@ mixin MwebInterface } @override - Future updateBalance({bool mwebOnly = false}) async { - Future? normalBalanceFuture; - if (!mwebOnly) { - // call to super to update transparent balance - normalBalanceFuture = super.updateBalance(); - } + Future updateBalance() async { + // call to super to update transparent balance + final normalBalanceFuture = super.updateBalance(); if (info.isMwebEnabled) { final start = DateTime.now(); @@ -738,10 +734,8 @@ mixin MwebInterface } } - if (!mwebOnly) { - // wait for normalBalanceFuture to complete before returning - await normalBalanceFuture; - } + // wait for normalBalanceFuture to complete before returning + await normalBalanceFuture; } @override diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index 0d5b6a2f4..22ab2a712 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -1261,21 +1261,6 @@ class MockPrefs extends _i1.Mock implements _i10.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index 84a91812a..7ea2055fc 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -1181,21 +1181,6 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 1f78d9ce4..643d6cc6b 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -622,21 +622,6 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index 14bc27820..410094cdf 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -905,21 +905,6 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index a346758aa..9b7d99828 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -780,21 +780,6 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index 939703910..cd8edb2ab 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -878,21 +878,6 @@ class MockPrefs extends _i1.Mock implements _i13.Prefs { returnValueForMissingStub: null, ); - @override - bool get useMweb => (super.noSuchMethod( - Invocation.getter(#useMweb), - returnValue: false, - ) as bool); - - @override - set useMweb(bool? useMweb) => super.noSuchMethod( - Invocation.setter( - #useMweb, - useMweb, - ), - returnValueForMissingStub: null, - ); - @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), From f00e85ffeffc7e5ab1894113117b59931c0af6a3 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 1 Jul 2025 09:13:50 -0600 Subject: [PATCH 147/206] mweb toggle dialog --- .../wallet_settings_wallet_settings_view.dart | 123 ++++++++++++++++++ .../more_features/more_features_dialog.dart | 12 +- 2 files changed, 132 insertions(+), 3 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index a1f9f19dc..312a61a77 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -8,6 +8,8 @@ * */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -23,12 +25,15 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; +import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/rounded_white_container.dart'; import '../../../../widgets/stack_dialog.dart'; import '../../../pinpad_views/lock_screen_view.dart'; @@ -53,6 +58,7 @@ class WalletSettingsWalletSettingsView extends ConsumerStatefulWidget { class _WalletSettingsWalletSettingsViewState extends ConsumerState { late final DSBController _switchController; + late final DSBController _switchControllerMwebToggle; bool _switchDuressToggleLock = false; // Mutex. Future _switchDuressToggled() async { @@ -135,6 +141,72 @@ class _WalletSettingsWalletSettingsViewState } } + bool _switchMwebToggleToggledLock = false; // Mutex. + Future _switchMwebToggleToggled() async { + if (_switchMwebToggleToggledLock) { + return; + } + _switchMwebToggleToggledLock = true; // Lock mutex. + + try { + if (_switchControllerMwebToggle.isOn?.call() != true) { + final canContinue = await showDialog( + context: context, + builder: (context) { + return StackDialog( + title: "Notice", + message: + "Activating MWEB requires some synchronization with the p2p network. " + "This process currently takes around 30 minutes to complete, " + "as it involves synchronizing on-chain MWEB related data.", + leftButton: SecondaryButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + label: "Cancel", + ), + rightButton: PrimaryButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + label: "Continue", + ), + ); + }, + ); + + if (canContinue == true) { + await _updateMwebToggle(true); + + unawaited( + (ref.read(pWallets).getWallet(widget.walletId) as MwebInterface) + .open(), + ); + } + } else { + await _updateMwebToggle(false); + } + } finally { + // ensure _switchMwebToggleToggledLock is set to false no matter what. + _switchMwebToggleToggledLock = false; + } + } + + Future _updateMwebToggle(bool value) async { + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.mwebEnabled: value}, + isar: ref.read(mainDBProvider).isar, + ); + + if (_switchControllerMwebToggle.isOn != null) { + if (_switchControllerMwebToggle.isOn!.call() != value) { + _switchControllerMwebToggle.activate?.call(); + } + } + } + Future _updateAddressReuse(bool shouldReuse) async { await ref .read(pWalletInfo(widget.walletId)) @@ -153,6 +225,7 @@ class _WalletSettingsWalletSettingsViewState @override void initState() { _switchController = DSBController(); + _switchControllerMwebToggle = DSBController(); super.initState(); } @@ -304,6 +377,56 @@ class _WalletSettingsWalletSettingsViewState ), ), ), + if (wallet is MwebInterface) const SizedBox(height: 8), + if (wallet is MwebInterface) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: _switchMwebToggleToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable MWEB", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select( + (value) => value.otherData, + ), + )[WalletInfoKeys.mwebEnabled] + as bool? ?? + false, + controller: _switchControllerMwebToggle, + ), + ), + ), + ], + ), + ), + ), + ), if (!ref.watch(pDuress)) const SizedBox(height: 8), if (!ref.watch(pDuress)) RoundedWhiteContainer( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index b3510022c..cac59a502 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -24,6 +24,7 @@ import '../../../../../utilities/text_styles.dart'; import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../../widgets/custom_buttons/draggable_switch_button.dart'; import '../../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../../widgets/desktop/desktop_dialog_close_button.dart'; @@ -198,7 +199,7 @@ class _MoreFeaturesDialogState extends ConsumerState { Padding( padding: const EdgeInsets.only(left: 32), child: Text( - "Warning!", + "Notice", style: STextStyles.desktopH3(context), ), ), @@ -216,7 +217,9 @@ class _MoreFeaturesDialogState extends ConsumerState { mainAxisSize: MainAxisSize.min, children: [ Text( - "TODO warning about extra data downloaded and initial sync/scan time", + "Activating MWEB requires some synchronization with the p2p network. " + "This process currently takes around 30 minutes to complete, " + "as it involves synchronizing on-chain MWEB related data.", style: STextStyles.desktopTextSmall(context), ), const SizedBox(height: 43), @@ -255,7 +258,10 @@ class _MoreFeaturesDialogState extends ConsumerState { if (canContinue == true) { await _updateMwebToggle(true); - unawaited(ref.read(pWallets).getWallet(widget.walletId).init()); + unawaited( + (ref.read(pWallets).getWallet(widget.walletId) as MwebInterface) + .open(), + ); } } else { await _updateMwebToggle(false); From 95d3772e03990b725385fc82843abf1b4baa111c Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 1 Jul 2025 09:27:12 -0600 Subject: [PATCH 148/206] mweb address on mobile receive view --- lib/pages/receive_view/receive_view.dart | 94 +++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index 9c8abcb6c..35d5c8ad9 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -28,6 +28,7 @@ import '../../utilities/assets.dart'; import '../../utilities/clipboard_interface.dart'; import '../../utilities/constants.dart'; import '../../utilities/enums/derive_path_type_enum.dart'; +import '../../utilities/show_loading.dart'; import '../../utilities/text_styles.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; @@ -36,6 +37,7 @@ import '../../wallets/wallet/intermediate/bip39_hd_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; import '../../widgets/background.dart'; @@ -74,6 +76,7 @@ class _ReceiveViewState extends ConsumerState { late final ClipboardInterface clipboard; late final bool _supportsSpark; late final bool _showMultiType; + late bool supportsMweb; int _currentIndex = 0; @@ -202,6 +205,31 @@ class _ReceiveViewState extends ConsumerState { } } + Future
      _generateNewMwebAddress() async { + final wallet = ref.read(pWallets).getWallet(walletId) as MwebInterface; + + final address = await wallet.generateNextMwebAddress(); + await ref.read(mainDBProvider).isar.writeTxn(() async { + await ref.read(mainDBProvider).isar.addresses.put(address); + }); + + return address; + } + + Future generateNewMwebAddress() async { + final address = await showLoading
      ( + whileFuture: _generateNewMwebAddress(), + context: context, + message: "Generating address", + ); + + if (mounted && address != null) { + setState(() { + _addressMap[AddressType.mweb] = address.value; + }); + } + } + @override void initState() { walletId = widget.walletId; @@ -209,12 +237,17 @@ class _ReceiveViewState extends ConsumerState { clipboard = widget.clipboard; final wallet = ref.read(pWallets).getWallet(walletId); _supportsSpark = wallet is SparkInterface; + supportsMweb = + wallet is MwebInterface && + !wallet.info.isViewOnly && + wallet.info.isMwebEnabled; if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { _showMultiType = false; } else { _showMultiType = _supportsSpark || + supportsMweb || (wallet is! BCashInterface && wallet is Bip39HDWallet && wallet.supportedAddressTypes.length > 1); @@ -231,6 +264,10 @@ class _ReceiveViewState extends ConsumerState { (e) => e != wallet.info.mainAddressType, ), ); + + if (supportsMweb) { + _walletAddressTypes.insert(0, AddressType.mweb); + } } } @@ -285,6 +322,54 @@ class _ReceiveViewState extends ConsumerState { final ticker = widget.tokenContract?.symbol ?? coin.ticker; + ref.listen(pWalletInfo(walletId), (prev, next) { + if (prev?.isMwebEnabled != next.isMwebEnabled) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + supportsMweb = next.isMwebEnabled; + + if (supportsMweb && + !_walletAddressTypes.contains(AddressType.mweb)) { + _walletAddressTypes.insert(0, AddressType.mweb); + _addressSubMap[AddressType.mweb] = ref + .read(mainDBProvider) + .isar + .addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.mweb) + .sortByDerivationIndexDesc() + .findFirst() + .asStream() + .listen((event) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _addressMap[AddressType.mweb] = + event?.value ?? + _addressMap[AddressType.mweb] ?? + "[No address yet]"; + }); + } + }); + }); + } else { + _walletAddressTypes.remove(AddressType.mweb); + _addressSubMap[AddressType.mweb]?.cancel(); + _addressSubMap.remove(AddressType.mweb); + } + + if (_currentIndex >= _walletAddressTypes.length) { + _currentIndex = _walletAddressTypes.length - 1; + } + }); + } + }); + } + }); + final String address; if (_showMultiType) { address = _addressMap[_walletAddressTypes[_currentIndex]]!; @@ -302,7 +387,8 @@ class _ReceiveViewState extends ConsumerState { wallet.viewOnlyType == ViewOnlyWalletType.addressOnly) { canGen = false; } else { - canGen = (wallet is MultiAddressInterface || _supportsSpark); + canGen = + (wallet is MultiAddressInterface || _supportsSpark || supportsMweb); } return Background( @@ -590,7 +676,11 @@ class _ReceiveViewState extends ConsumerState { SecondaryButton( label: "Generate new address", onPressed: - _supportsSpark && + supportsMweb && + _walletAddressTypes[_currentIndex] == + AddressType.mweb + ? generateNewMwebAddress + : _supportsSpark && _walletAddressTypes[_currentIndex] == AddressType.spark ? generateNewSparkAddress From e8b2c597cdecb923fb81fc68c8ec8e201fc5bdbc Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 1 Jul 2025 10:08:26 -0600 Subject: [PATCH 149/206] adjust mweb toggle dialog info text --- .../wallet_settings_wallet_settings_view.dart | 5 ++--- .../sub_widgets/more_features/more_features_dialog.dart | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index 312a61a77..7792fb2e1 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -156,9 +156,8 @@ class _WalletSettingsWalletSettingsViewState return StackDialog( title: "Notice", message: - "Activating MWEB requires some synchronization with the p2p network. " - "This process currently takes around 30 minutes to complete, " - "as it involves synchronizing on-chain MWEB related data.", + "Activating MWEB requires synchronizing on-chain MWEB related data. " + "This currently requires about 800 MB of storage.", leftButton: SecondaryButton( onPressed: () { Navigator.of(context).pop(false); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index cac59a502..20f2524a6 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -217,9 +217,8 @@ class _MoreFeaturesDialogState extends ConsumerState { mainAxisSize: MainAxisSize.min, children: [ Text( - "Activating MWEB requires some synchronization with the p2p network. " - "This process currently takes around 30 minutes to complete, " - "as it involves synchronizing on-chain MWEB related data.", + "Activating MWEB requires synchronizing on-chain MWEB related data. " + "This currently requires about 800 MB of storage.", style: STextStyles.desktopTextSmall(context), ), const SizedBox(height: 43), From e0dfeb9acd3acf89f3f575d07becfacc9da5f425 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 1 Jul 2025 16:48:57 -0600 Subject: [PATCH 150/206] mwebd logs stream in debug mode --- lib/main.dart | 21 ++++++++++++++ lib/services/mwebd_service.dart | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index c521236fb..3ffda4012 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -59,6 +59,7 @@ import 'providers/providers.dart'; import 'route_generator.dart'; import 'services/exchange/exchange_data_loading_service.dart'; import 'services/locale_service.dart'; +import 'services/mwebd_service.dart'; import 'services/node_service.dart'; import 'services/notifications_api.dart'; import 'services/notifications_service.dart'; @@ -73,6 +74,7 @@ import 'utilities/logger.dart'; import 'utilities/prefs.dart'; import 'utilities/stack_file_system.dart'; import 'utilities/util.dart'; +import 'wallets/crypto_currency/crypto_currency.dart'; import 'wallets/isar/providers/all_wallets_info_provider.dart'; import 'wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import 'widgets/crypto_notifications.dart'; @@ -214,6 +216,25 @@ void main(List args) async { await CampfireMigration.init(); } + if (kDebugMode) { + unawaited( + MwebdService.instance + .logsStream(CryptoCurrencyNetwork.main) + .then( + (stream) => + stream.listen((line) => print("[MWEBD: MAINNET]: $line")), + ), + ); + unawaited( + MwebdService.instance + .logsStream(CryptoCurrencyNetwork.test) + .then( + (stream) => + stream.listen((line) => print("[MWEBD: TESTNET]: $line")), + ), + ); + } + // TODO: // This should be moved to happen during the loading animation instead of // showing a blank screen for 4-10 seconds. diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index 8f60a3d6f..f8b3a6a32 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'dart:math'; @@ -193,6 +194,54 @@ final class MwebdService { return _map[net]?.client; }); } + + Future> logsStream( + CryptoCurrencyNetwork net, { + Duration pollInterval = const Duration(milliseconds: 200), + }) async { + final controller = StreamController(); + int offset = 0; + String leftover = ''; + Timer? timer; + + final path = + "${(await StackFileSystem.applicationMwebdDirectory(net == CryptoCurrencyNetwork.main ? "mainnet" : "testnet")).path}" + "${Platform.pathSeparator}logs" + "${Platform.pathSeparator}debug.log"; + + Future poll() async { + if (!controller.isClosed) { + final file = File(path); + final length = await file.length(); + + if (length > offset) { + final raf = await file.open(); + await raf.setPosition(offset); + final bytes = await raf.read(length - offset); + await raf.close(); + + final chunk = utf8.decode(bytes); + final lines = (leftover + chunk).split('\n'); + leftover = lines.removeLast(); // possibly incomplete + + for (final line in lines) { + controller.add(line); + } + + offset = length; + } + } + } + + timer = Timer.periodic(pollInterval, (_) => poll()); + + controller.onCancel = () { + timer?.cancel(); + controller.close(); + }; + + return controller.stream; + } } // ============================================================================ From 53caa9b95fda1ba64ea0f8382ed7e8c716f2989e Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 1 Jul 2025 16:49:14 -0600 Subject: [PATCH 151/206] mweb mobile updates and fixes --- lib/pages/send_view/send_view.dart | 127 ++++++++++-------- .../dual_balance_selection_sheet.dart | 30 +++-- .../sub_widgets/wallet_summary_info.dart | 7 +- lib/pages/wallet_view/wallet_view.dart | 18 ++- lib/wallets/wallet/impl/litecoin_wallet.dart | 4 + 5 files changed, 109 insertions(+), 77 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 8c3af28e7..9ac52806f 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -607,13 +607,16 @@ class _SendViewState extends ConsumerState { final Amount amount = ref.read(pSendAmount)!; final Amount availableBalance; - if (isFiro) { + if (isFiro || ref.read(pWalletInfo(walletId)).isMwebEnabled) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case BalanceType.public: availableBalance = wallet.info.cachedBalance.spendable; break; case BalanceType.private: - availableBalance = wallet.info.cachedBalanceTertiary.spendable; + availableBalance = + isFiro + ? wallet.info.cachedBalanceTertiary.spendable + : wallet.info.cachedBalanceSecondary.spendable; break; } } else { @@ -975,14 +978,17 @@ class _SendViewState extends ConsumerState { if (showCoinControl && selectedUTXOs.isNotEmpty) { amount = _selectedUtxosAmount(selectedUTXOs); - } else if (isFiro) { + } else if (isFiro || ref.read(pWalletInfo(walletId)).isMwebEnabled) { switch (ref.read(publicPrivateBalanceStateProvider.state).state) { case BalanceType.public: amount = ref.read(pWalletBalance(walletId)).spendable; break; case BalanceType.private: - amount = ref.read(pWalletBalanceTertiary(walletId)).spendable; + amount = + isFiro + ? ref.read(pWalletBalanceTertiary(walletId)).spendable + : ref.read(pWalletBalanceSecondary(walletId)).spendable; break; } } else { @@ -1198,54 +1204,56 @@ class _SendViewState extends ConsumerState { @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final wallet = ref.watch(pWallets).getWallet(walletId); final String locale = ref.watch( localeServiceChangeNotifierProvider.select((value) => value.locale), ); + final balType = ref.watch(publicPrivateBalanceStateProvider); + + final isMwebEnabled = ref.watch( + pWalletInfo(walletId).select((s) => s.isMwebEnabled), + ); + final showPrivateBalance = coin is Firo || isMwebEnabled; + final showCoinControl = - wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, ), ) && - (coin is Firo - ? ref.watch(publicPrivateBalanceStateProvider) == BalanceType.public - : true); + ref.watch(pWallets).getWallet(walletId) is CoinControlInterface && + balType == BalanceType.public; - if (isFiro) { - final isExchangeAddress = ref.watch(pIsExchangeAddress); + final isExchangeAddress = ref.watch(pIsExchangeAddress); - ref.listen(publicPrivateBalanceStateProvider, (previous, next) { - selectedUTXOs = {}; - - if (ref.read(pSendAmount) == null) { - setState(() { - _calculateFeesFuture = calculateFees( - 0.toAmountAsRaw(fractionDigits: coin.fractionDigits), - ); - }); - } else { - setState(() { - _calculateFeesFuture = calculateFees(ref.read(pSendAmount)!); - }); - } + ref.listen(publicPrivateBalanceStateProvider, (previous, next) { + selectedUTXOs = {}; - if (previous != next && - next == BalanceType.private && - isExchangeAddress && - !_isFiroExWarningDisplayed) { - _isFiroExWarningDisplayed = true; - WidgetsBinding.instance.addPostFrameCallback( - (_) => showFiroExchangeAddressWarning( - context, - () => _isFiroExWarningDisplayed = false, - ), + if (ref.read(pSendAmount) == null) { + setState(() { + _calculateFeesFuture = calculateFees( + 0.toAmountAsRaw(fractionDigits: coin.fractionDigits), ); - } - }); - } + }); + } else { + setState(() { + _calculateFeesFuture = calculateFees(ref.read(pSendAmount)!); + }); + } + + if (previous != next && + next == BalanceType.private && + isExchangeAddress && + !_isFiroExWarningDisplayed) { + _isFiroExWarningDisplayed = true; + WidgetsBinding.instance.addPostFrameCallback( + (_) => showFiroExchangeAddressWarning( + context, + () => _isFiroExWarningDisplayed = false, + ), + ); + } + }); // add listener for epic cash to strip http:// and https:// prefixes if the address also ocntains an @ symbol (indicating an epicbox address) if (coin is Epiccash) { @@ -1346,9 +1354,9 @@ class _SendViewState extends ConsumerState { // const SizedBox( // height: 2, // ), - if (isFiro) + if (isFiro || isMwebEnabled) Text( - "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", + "${balType.name.capitalize()} balance", style: STextStyles.label( context, ).copyWith(fontSize: 10), @@ -1366,13 +1374,8 @@ class _SendViewState extends ConsumerState { Builder( builder: (context) { final Amount amount; - if (isFiro) { - switch (ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state) { + if (showPrivateBalance) { + switch (balType) { case BalanceType.public: amount = ref @@ -1388,9 +1391,13 @@ class _SendViewState extends ConsumerState { amount = ref .read( - pWalletBalanceTertiary( - walletId, - ), + isMwebEnabled + ? pWalletBalanceSecondary( + walletId, + ) + : pWalletBalanceTertiary( + walletId, + ), ) .spendable; break; @@ -1771,15 +1778,17 @@ class _SendViewState extends ConsumerState { } }, ), - if (isFiro) const SizedBox(height: 12), - if (isFiro) + if (isFiro || isMwebEnabled) + const SizedBox(height: 12), + if (isFiro || isMwebEnabled) Text( "Send from", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (isFiro) const SizedBox(height: 8), - if (isFiro) + if (isFiro || isMwebEnabled) + const SizedBox(height: 8), + if (isFiro || isMwebEnabled) Stack( children: [ TextField( @@ -1855,9 +1864,13 @@ class _SendViewState extends ConsumerState { amount = ref .watch( - pWalletBalanceTertiary( - walletId, - ), + isFiro + ? pWalletBalanceTertiary( + walletId, + ) + : pWalletBalanceSecondary( + walletId, + ), ) .spendable; break; diff --git a/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart b/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart index c8006b713..fbd9ad996 100644 --- a/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/dual_balance_selection_sheet.dart @@ -11,13 +11,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../../../providers/providers.dart'; import '../../../providers/wallet/public_private_balance_state_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount_formatter.dart'; import '../../../utilities/constants.dart'; import '../../../utilities/text_styles.dart'; -import '../../../wallets/wallet/impl/firo_wallet.dart'; +import '../../../wallets/crypto_currency/coins/firo.dart'; +import '../../../wallets/isar/providers/wallet_info_provider.dart'; class DualBalanceSelectionSheet extends ConsumerStatefulWidget { const DualBalanceSelectionSheet({super.key, required this.walletId}); @@ -43,12 +43,7 @@ class _FiroBalanceSelectionSheetState Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final wallet = ref.watch( - pWallets.select((value) => value.getWallet(walletId)), - ); - final firoWallet = wallet as FiroWallet; - - final coin = wallet.info.coin; + final coin = ref.watch(pWalletCoin(walletId)); return Container( decoration: BoxDecoration( @@ -141,7 +136,7 @@ class _FiroBalanceSelectionSheetState // Row( // children: [ Text( - "Spark balance", + "Private balance", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), @@ -150,9 +145,16 @@ class _FiroBalanceSelectionSheetState ref .watch(pAmountFormatter(coin)) .format( - firoWallet - .info - .cachedBalanceTertiary + ref + .watch( + coin is Firo + ? pWalletBalanceTertiary( + walletId, + ) + : pWalletBalanceSecondary( + walletId, + ), + ) .spendable, ), style: STextStyles.itemSubtitle(context), @@ -231,7 +233,9 @@ class _FiroBalanceSelectionSheetState ref .watch(pAmountFormatter(coin)) .format( - firoWallet.info.cachedBalance.spendable, + ref + .watch(pWalletBalance(walletId)) + .spendable, ), style: STextStyles.itemSubtitle(context), textAlign: TextAlign.left, diff --git a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart index 3b8e255e8..68e0123bc 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart @@ -94,14 +94,17 @@ class WalletSummaryInfo extends ConsumerWidget { final bool toggleBalance; - if (coin is Firo) { + if (coin is Firo || ref.watch(pWalletInfo(walletId)).isMwebEnabled) { toggleBalance = false; final type = ref.watch(publicPrivateBalanceStateProvider.state).state; title = "${_showAvailable ? "Available" : "Full"} ${type.name.capitalize()} balance"; switch (type) { case BalanceType.private: - final balance = ref.watch(pWalletBalanceTertiary(walletId)); + final balance = + coin is Firo + ? ref.watch(pWalletBalanceTertiary(walletId)) + : ref.watch(pWalletBalanceSecondary(walletId)); balanceToShow = _showAvailable ? balance.spendable : balance.total; break; diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 06697a1d9..1f8ecff20 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -56,6 +56,7 @@ import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; import '../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; @@ -432,9 +433,9 @@ class _WalletViewState extends ConsumerState { ), ), ); - final firoWallet = ref.read(pWallets).getWallet(walletId) as FiroWallet; + final wallet = ref.read(pWallets).getWallet(walletId); - final Amount publicBalance = firoWallet.info.cachedBalance.spendable; + final Amount publicBalance = wallet.info.cachedBalance.spendable; if (publicBalance <= Amount.zero) { shouldPop = true; if (mounted) { @@ -453,7 +454,11 @@ class _WalletViewState extends ConsumerState { } try { - await firoWallet.anonymizeAllSpark(); + if (wallet is MwebInterface && wallet.info.isMwebEnabled) { + await wallet.anonymizeAllMweb(); + } else { + await (wallet as FiroWallet).anonymizeAllSpark(); + } shouldPop = true; if (mounted) { Navigator.of( @@ -811,8 +816,11 @@ class _WalletViewState extends ConsumerState { ), ), ), - if (isSparkWallet) const SizedBox(height: 10), - if (isSparkWallet) + if (isSparkWallet || + ref.watch(pWalletInfo(walletId)).isMwebEnabled) + const SizedBox(height: 10), + if (isSparkWallet || + ref.watch(pWalletInfo(walletId)).isMwebEnabled) Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( diff --git a/lib/wallets/wallet/impl/litecoin_wallet.dart b/lib/wallets/wallet/impl/litecoin_wallet.dart index af69c019d..76205c252 100644 --- a/lib/wallets/wallet/impl/litecoin_wallet.dart +++ b/lib/wallets/wallet/impl/litecoin_wallet.dart @@ -292,6 +292,10 @@ class LitecoinWallet .isNotEmpty(); if (hasOrdinal) { subType = TransactionSubType.ordinal; + } else { + if (outputs.any((e) => e.scriptPubKeyHex == "mweb")) { + subType = TransactionSubType.mweb; + } } // making API calls for every output in every transaction is too expensive From 32bd98f0833b125be9edc9ba54006ae2ce76800c Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 2 Jul 2025 09:04:17 -0600 Subject: [PATCH 152/206] flutter_mwebd go requirement docs update and bump flutter_mwebd version with ios/macos build fix --- docs/building.md | 1 + scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/building.md b/docs/building.md index 3ee68cf98..a50abbeb3 100644 --- a/docs/building.md +++ b/docs/building.md @@ -7,6 +7,7 @@ Here you will find instructions on how to install the necessary tools for buildi - The only OS supported for building Android and Linux desktop is Ubuntu 20.04. Windows builds require using Ubuntu 20.04 on WSL2. macOS builds for itself and iOS. Advanced users may also be able to build on other Debian-based distributions like Linux Mint. - Android setup ([Android Studio](https://developer.android.com/studio) and subsequent dependencies) - 100 GB of storage +- Install go: [https://go.dev/doc/install](https://go.dev/doc/install) ## Linux host diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 494224d6a..e9b29aad1 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 - flutter_mwebd: ^0.0.1-pre.1 + flutter_mwebd: ^0.0.1-pre.2 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 01b067681a0d8451329ccca1eb7bdfb7391bd391 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 3 Jul 2025 08:52:28 -0600 Subject: [PATCH 153/206] fix utxos update "optimization" --- lib/db/isar/main_db.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart index c8f7fc493..0a0269025 100644 --- a/lib/db/isar/main_db.dart +++ b/lib/db/isar/main_db.dart @@ -313,8 +313,6 @@ class MainDB { Future updateUTXOs(String walletId, List utxos) async { bool newUTXO = false; - if (utxos.isEmpty) return newUTXO; - await isar.writeTxn(() async { final set = utxos.toSet(); for (final utxo in utxos) { @@ -343,7 +341,9 @@ class MainDB { } await isar.utxos.where().walletIdEqualTo(walletId).deleteAll(); - await isar.utxos.putAll(set.toList()); + if (set.isNotEmpty) { + await isar.utxos.putAll(set.toList()); + } }); return newUTXO; From ec630cffe146a8bfe12cca3af0e34a8b31cd7c6a Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 3 Jul 2025 08:56:03 -0600 Subject: [PATCH 154/206] bump flutter_mwebd version again (with ios build fix) --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 840c40fee..7ed655329 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -985,10 +985,10 @@ packages: dependency: "direct main" description: name: flutter_mwebd - sha256: b390f5c99aaddec5d4c785c6c3d96b786b4eb333e5e1fd0051079cec1aacf40a + sha256: f3b2f86b9b7352e1a6a33d2f4ed098d454a8841929b767e9390b14b66e243274 url: "https://pub.dev" source: hosted - version: "0.0.1-pre.1" + version: "0.0.1-pre.3" flutter_native_splash: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index e9b29aad1..e2a31c8ce 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 - flutter_mwebd: ^0.0.1-pre.2 + flutter_mwebd: ^0.0.1-pre.3 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 8b19fcbaba37e53104092d2e9314ae5331cc1663 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 3 Jul 2025 15:07:27 -0600 Subject: [PATCH 155/206] bump flutter_mwebd version yet again --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 7ed655329..5932dd93b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -985,10 +985,10 @@ packages: dependency: "direct main" description: name: flutter_mwebd - sha256: f3b2f86b9b7352e1a6a33d2f4ed098d454a8841929b767e9390b14b66e243274 + sha256: bc664ef047b5364c02fa1d75aa3b0d73c1ae888530857fb8a646e31e4dd3ce7c url: "https://pub.dev" source: hosted - version: "0.0.1-pre.3" + version: "0.0.1-pre.4" flutter_native_splash: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index e2a31c8ce..6f7f3cac2 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 - flutter_mwebd: ^0.0.1-pre.3 + flutter_mwebd: ^0.0.1-pre.4 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 483a41e38d21bbdcb1422bfa426e5b349992c73b Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 10:41:27 -0600 Subject: [PATCH 156/206] and again bump flutter_mwebd version, this time with windows build fix --- docs/building.md | 2 ++ scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/building.md b/docs/building.md index a50abbeb3..6aa647e53 100644 --- a/docs/building.md +++ b/docs/building.md @@ -164,6 +164,8 @@ cd scripts/windows ./deps.sh ``` +install go in WSL [https://go.dev/doc/install](https://go.dev/doc/install) (follow linux instructions) and ensure you have `x86_64-w64-mingw32-gcc` + and use `scripts/build_app.sh` to build plugins: ``` cd .. diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 6f7f3cac2..2a323afc7 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 - flutter_mwebd: ^0.0.1-pre.4 + flutter_mwebd: ^0.0.1-pre.5 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 338f6613e72b892f72f66bc98c2012285e13e15f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 12:50:38 -0600 Subject: [PATCH 157/206] again, but this time with linux fix --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 5932dd93b..66cfe0e85 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -985,10 +985,10 @@ packages: dependency: "direct main" description: name: flutter_mwebd - sha256: bc664ef047b5364c02fa1d75aa3b0d73c1ae888530857fb8a646e31e4dd3ce7c + sha256: f6daecf6a4e10dde0a2fbfe026d801cd41864c6464923d9a26a92c613c893173 url: "https://pub.dev" source: hosted - version: "0.0.1-pre.4" + version: "0.0.1-pre.6" flutter_native_splash: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 2a323afc7..4e60e7857 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.0 cs_salvium_flutter_libs: ^1.0.2 - flutter_mwebd: ^0.0.1-pre.5 + flutter_mwebd: ^0.0.1-pre.6 mweb_client: ^0.2.0 fixnum: ^1.1.1 From abeb82406068ef32ed6d98fb6c1efae4692c7713 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 14:43:58 -0600 Subject: [PATCH 158/206] mweb related ui tweaks --- lib/pages/wallet_view/wallet_view.dart | 10 +++++----- .../sub_widgets/desktop_wallet_features.dart | 15 ++++++++------- .../sub_widgets/mweb_desktop_wallet_summary.dart | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 1f8ecff20..dd4c29560 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -445,7 +445,7 @@ class _WalletViewState extends ConsumerState { unawaited( showFloatingFlushBar( type: FlushBarType.info, - message: "No funds available to anonymize!", + message: "No funds available to privatize!", context: context, ), ); @@ -467,7 +467,7 @@ class _WalletViewState extends ConsumerState { unawaited( showFloatingFlushBar( type: FlushBarType.success, - message: "Anonymize transaction submitted", + message: "Privatize transaction submitted", context: context, ), ); @@ -482,7 +482,7 @@ class _WalletViewState extends ConsumerState { context: context, builder: (_) => StackOkDialog( - title: "Anonymize all failed", + title: "Privatize all failed", message: "Reason: $e", ), ); @@ -839,7 +839,7 @@ class _WalletViewState extends ConsumerState { (context) => StackDialog( title: "Attention!", message: - "You're about to anonymize all of your public funds.", + "You're about to privatize all of your public funds.", leftButton: TextButton( onPressed: () { Navigator.of(context).pop(); @@ -880,7 +880,7 @@ class _WalletViewState extends ConsumerState { ); }, child: Text( - "Anonymize funds", + "Privatize funds", style: STextStyles.button( context, ).copyWith( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 17c055614..63722608b 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -11,6 +11,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -67,7 +68,7 @@ import '../desktop_wallet_view.dart'; import 'more_features/more_features_dialog.dart'; enum WalletFeature { - anonymizeFunds("Anonymize funds", "Anonymize funds"), + anonymizeFunds("Privatize funds", "Privatize funds"), swap("Swap", ""), buy("Buy", "Buy cryptocurrency"), paynym("PayNym", "Increased address privacy using BIP47"), @@ -163,7 +164,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { Text("Attention!", style: STextStyles.desktopH2(context)), const SizedBox(height: 16), Text( - "You're about to anonymize all of your public funds.", + "You're about to privatize all of your public funds.", style: STextStyles.desktopTextSmall(context), ), const SizedBox(height: 32), @@ -206,7 +207,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { builder: (context) => WillPopScope( child: const CustomLoadingOverlay( - message: "Anonymizing balance", + message: "Privatizing balance", eventBus: null, ), onWillPop: () async => shouldPop, @@ -226,7 +227,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { unawaited( showFloatingFlushBar( type: FlushBarType.info, - message: "No funds available to anonymize!", + message: "No funds available to privatize!", context: context, ), ); @@ -249,7 +250,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { unawaited( showFloatingFlushBar( type: FlushBarType.success, - message: "Anonymize transaction submitted", + message: "Privatize transaction submitted", context: context, ), ); @@ -273,7 +274,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Anonymize all failed", + "Privatize all failed", style: STextStyles.desktopH3(context), ), const Spacer(flex: 1), @@ -428,7 +429,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { _onSparkCoinsPressed, ), - if (!isViewOnly && wallet is MwebInterface) + if (kDebugMode && !isViewOnly && wallet is MwebInterface) ( WalletFeature.mwebUtxos, Assets.svg.coinControl.gamePad, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart index 942d08fa1..6ce1d19e4 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/mweb_desktop_wallet_summary.dart @@ -151,7 +151,7 @@ class _Prefix extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ SelectableText( - isMweb ? "MWEB" : "", + isMweb ? "Private" : "Public", style: STextStyles.w500_24(context), ), ], From 219b4d1a6142195b17151f38592bb7a87ea061f7 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 15:28:09 -0600 Subject: [PATCH 159/206] fix coin control pegin --- .../wallet/wallet_mixin_interfaces/electrumx_interface.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index 7e669b07e..e032cfce2 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -1938,6 +1938,7 @@ mixin ElectrumXInterface txData: result.copyWith( recipients: result.recipients!.where((e) => !(e.isChange)).toList(), ), + utxos: utxos?.toList(), coinControl: coinControl, isSendAll: isSendAll, isSendAllCoinControlUtxos: isSendAllCoinControlUtxos, From e7e053fa782823cba19ee9e662bb3ee3dbc3e7b5 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 16:28:55 -0600 Subject: [PATCH 160/206] ensure wallet has address of mweb output in local db --- .../wallet/wallet_mixin_interfaces/mweb_interface.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index d37f74fa1..a870aaa1e 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -229,6 +229,12 @@ mixin MwebInterface await db.into(db.mwebUtxos).insertOnConflictUpdate(newUtxo); }); + Address? addr = await mainDB.getAddress(walletId, utxo.address); + while (addr == null || addr.value != utxo.address) { + addr = await generateNextMwebAddress(); + await mainDB.updateOrPutAddresses([addr]); + } + // TODO get real txid one day final fakeTxid = "mweb_outputId_${utxo.outputId}"; From 6cb870e738f2c5e47b9c9c60ba3f783406eb4af5 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 4 Jul 2025 16:29:15 -0600 Subject: [PATCH 161/206] fix mweb -> mweb send all --- .../wallet_mixin_interfaces/electrumx_interface.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart index e032cfce2..e978a0bd7 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart @@ -265,8 +265,18 @@ mixin ElectrumXInterface if (isSendAll || isSendAllCoinControlUtxos) { if ((overrideFeeAmount ?? BigInt.zero) + satoshiAmountToSend != satoshisBeingUsed) { + Logging.instance.d("txData.type: ${txData.type}"); + Logging.instance.d("isSendAll: $isSendAll"); + Logging.instance.d( + "isSendAllCoinControlUtxos: $isSendAllCoinControlUtxos", + ); + Logging.instance.d("overrideFeeAmount: $overrideFeeAmount"); + Logging.instance.d("satoshiAmountToSend: $satoshiAmountToSend"); + Logging.instance.d("satoshisBeingUsed: $satoshisBeingUsed"); + // hack check - if (txData.type != TxType.mwebPegIn) { + if (!(txData.type == TxType.mwebPegIn || + (txData.type == TxType.mweb && overrideFeeAmount != null))) { throw Exception( "Something happened that should never actually happen. " "Please report this error to the developers.", From fe6ef0a06cae7127f29a4a099f4080393eacc5b1 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Jul 2025 08:05:22 -0600 Subject: [PATCH 162/206] fix receiving address query listener --- lib/pages/receive_view/receive_view.dart | 6 ++++++ .../wallet_view/sub_widgets/desktop_receive.dart | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index 35d5c8ad9..fe44acc9b 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -289,6 +289,9 @@ class _ReceiveViewState extends ConsumerState { .walletIdEqualTo(walletId) .filter() .typeEqualTo(type) + .and() + .not() + .subTypeEqualTo(AddressSubType.change) .sortByDerivationIndexDesc() .findFirst() .asStream() @@ -340,6 +343,9 @@ class _ReceiveViewState extends ConsumerState { .walletIdEqualTo(walletId) .filter() .typeEqualTo(AddressType.mweb) + .and() + .not() + .subTypeEqualTo(AddressSubType.change) .sortByDerivationIndexDesc() .findFirst() .asStream() diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index 20e780c97..5cea18ff2 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -284,6 +284,9 @@ class _DesktopReceiveState extends ConsumerState { .walletIdEqualTo(walletId) .filter() .typeEqualTo(type) + .and() + .not() + .subTypeEqualTo(AddressSubType.change) .sortByDerivationIndexDesc() .findFirst() .asStream() @@ -333,6 +336,9 @@ class _DesktopReceiveState extends ConsumerState { .walletIdEqualTo(walletId) .filter() .typeEqualTo(AddressType.mweb) + .and() + .not() + .subTypeEqualTo(AddressSubType.change) .sortByDerivationIndexDesc() .findFirst() .asStream() From 3c05f17640a89f92e2464ae4957705e9c7049b75 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Jul 2025 11:55:59 -0600 Subject: [PATCH 163/206] salvium block explorer uri fix --- lib/wallets/crypto_currency/coins/salvium.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/crypto_currency/coins/salvium.dart b/lib/wallets/crypto_currency/coins/salvium.dart index d7618094c..db794dc53 100644 --- a/lib/wallets/crypto_currency/coins/salvium.dart +++ b/lib/wallets/crypto_currency/coins/salvium.dart @@ -116,7 +116,7 @@ class Salvium extends CryptonoteCurrency { Uri defaultBlockExplorer(String txid) { switch (network) { case CryptoCurrencyNetwork.main: - return Uri.parse("https://explorer.salvium.io//tx/$txid"); + return Uri.parse("https://explorer.salvium.io/tx/$txid"); default: throw Exception( "Unsupported network for defaultBlockExplorer(): $network", From 401af1f8043c2c0fa49780b5d161f7bcfb2ad518 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Jul 2025 11:57:37 -0600 Subject: [PATCH 164/206] salvium price fix --- lib/services/price.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/services/price.dart b/lib/services/price.dart index 8dc686fa1..9641d0328 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -49,6 +49,7 @@ class PriceAPI { Nano: "nano", Banano: "banano", Xelis: "xelis", + Salvium: "salvium", }; static const refreshInterval = 60; From f54f9bfb90311f19e9a517e4388ee24daefaa3dc Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 9 Jul 2025 09:57:11 -0600 Subject: [PATCH 165/206] fix custom fee on desktop --- .../sub_widgets/desktop_send_fee_form.dart | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart index 6b08923ab..69757ac7c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart @@ -55,7 +55,15 @@ class _DesktopSendFeeFormState extends ConsumerState { bool get isEth => cryptoCurrency is Ethereum; - bool isCustomFee = false; + bool _isCustomFeeValue = false; + bool get _isCustomFee => _isCustomFeeValue; + set _isCustomFee(bool newValue) { + if (_isCustomFeeValue != newValue) { + _isCustomFeeValue = newValue; + widget.onCustomFeeOptionChanged.call(_isCustomFeeValue); + } + } + (FeeRateType, String?, String?)? feeSelectionResult; @override @@ -97,12 +105,12 @@ class _DesktopSendFeeFormState extends ConsumerState { ); if (feeSelectionResult != null) { - if (isCustomFee && + if (_isCustomFee && feeSelectionResult!.$1 != FeeRateType.custom) { - isCustomFee = false; - } else if (!isCustomFee && + _isCustomFee = false; + } else if (!_isCustomFee && feeSelectionResult!.$1 == FeeRateType.custom) { - isCustomFee = true; + _isCustomFee = true; } } @@ -113,7 +121,7 @@ class _DesktopSendFeeFormState extends ConsumerState { ), child: Text( "Transaction fee" - "${isCustomFee ? "" : " (${isEth ? "max" : "estimated"})"}", + "${_isCustomFee ? "" : " (${isEth ? "max" : "estimated"})"}", style: STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of( @@ -124,7 +132,7 @@ class _DesktopSendFeeFormState extends ConsumerState { ), ), const SizedBox(height: 10), - if (!isCustomFee) + if (!_isCustomFee) Padding( padding: const EdgeInsets.all(10), child: @@ -275,7 +283,7 @@ class _DesktopSendFeeFormState extends ConsumerState { ], ), ), - if (isCustomFee && isEth) + if (_isCustomFee && isEth) EthFeeForm( minGasLimit: widget.isToken @@ -284,7 +292,7 @@ class _DesktopSendFeeFormState extends ConsumerState { stateChanged: (value) => widget.onCustomEip1559FeeOptionChanged?.call(value), ), - if (isCustomFee && !isEth) + if (_isCustomFee && !isEth) Padding( padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( From 6d0a95e01a65f84a4ac68e35af6bf1fdefbc765b Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 15 Jul 2025 07:53:43 -0600 Subject: [PATCH 166/206] fix mweb output spent status (balance fix) --- .../mweb_interface.dart | 76 +++++++++---------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart index a870aaa1e..4480ef81b 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart @@ -216,17 +216,28 @@ mixin MwebInterface (e) => e.outputId.equals(utxo.outputId), )).getSingleOrNull(); - final newUtxo = MwebUtxosCompanion( - outputId: Value(prev?.outputId ?? utxo.outputId), - address: Value(prev?.address ?? utxo.address), - value: Value(utxo.value.toInt()), - height: Value(utxo.height), - blockTime: Value(utxo.blockTime), - blocked: Value(prev?.blocked ?? false), - used: Value(prev?.used ?? false), - ); + if (prev == null) { + final newUtxo = MwebUtxosCompanion( + outputId: Value(utxo.outputId), + address: Value(utxo.address), + value: Value(utxo.value.toInt()), + height: Value(utxo.height), + blockTime: Value(utxo.blockTime), + blocked: const Value(false), + used: const Value(false), + ); - await db.into(db.mwebUtxos).insertOnConflictUpdate(newUtxo); + await db.into(db.mwebUtxos).insert(newUtxo); + } else { + await db + .update(db.mwebUtxos) + .replace( + prev.copyWith( + blockTime: utxo.blockTime, + height: utxo.height, + ), + ); + } }); Address? addr = await mainDB.getAddress(walletId, utxo.address); @@ -469,7 +480,19 @@ mixin MwebInterface ); // Update used mweb utxos as used in database - await _checkSpentMwebUtxos(); + final usedMwebUtxos = + txData.usedUTXOs!.whereType().map((e) => e.utxo).toList(); + + Logging.instance.i("Used mweb inputs: $usedMwebUtxos"); + + if (usedMwebUtxos.isNotEmpty) { + final db = Drift.get(walletId); + await db.transaction(() async { + for (final used in usedMwebUtxos) { + await db.update(db.mwebUtxos).replace(used); + } + }); + } return await updateSentCachedTxData(txData: txData); } catch (e, s) { @@ -583,35 +606,6 @@ mixin MwebInterface } } - Future _checkSpentMwebUtxos() async { - try { - final db = Drift.get(walletId); - final mwebUtxos = await db.select(db.mwebUtxos).get(); - - final client = await _client; - - final spent = await client.spent( - SpentRequest(outputId: mwebUtxos.map((e) => e.outputId)), - ); - - await db.transaction(() async { - for (final utxo in mwebUtxos) { - await db - .into(db.mwebUtxos) - .insertOnConflictUpdate( - utxo - .toCompanion(false) - .copyWith( - used: Value(spent.outputId.contains(utxo.outputId)), - ), - ); - } - }); - } catch (e, s) { - Logging.instance.e("_checkSpentMwebUtxos()", error: e, stackTrace: s); - } - } - Future _checkAddresses() async { // check change first as it is index 0 Address? changeAddress = await getMwebChangeAddress(); @@ -667,8 +661,6 @@ mixin MwebInterface if (info.isMwebEnabled) { final start = DateTime.now(); try { - await _checkSpentMwebUtxos(); - final currentHeight = await chainHeight; final db = Drift.get(walletId); final mwebUtxos = From c73fef657a4ed51e32289838331c2323cc8c35f5 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 15 Jul 2025 08:03:29 -0600 Subject: [PATCH 167/206] fix missing coin control option --- lib/pages/send_view/send_view.dart | 2 +- .../my_stack_view/wallet_view/sub_widgets/desktop_send.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 9ac52806f..76aebaf33 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1222,7 +1222,7 @@ class _SendViewState extends ConsumerState { ), ) && ref.watch(pWallets).getWallet(walletId) is CoinControlInterface && - balType == BalanceType.public; + (showPrivateBalance ? balType == BalanceType.public : true); final isExchangeAddress = ref.watch(pIsExchangeAddress); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 567f3a94a..dd3a70f9d 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -1052,7 +1052,7 @@ class _DesktopSendState extends ConsumerState { ), ) && ref.watch(pWallets).getWallet(walletId) is CoinControlInterface && - balType == BalanceType.public; + (showPrivateBalance ? balType == BalanceType.public : true); return Column( crossAxisAlignment: CrossAxisAlignment.start, From d642b8f89a1a1363c85d81f671fd76c5d9c3aa9b Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 15 Jul 2025 09:12:23 -0600 Subject: [PATCH 168/206] update salvium dep --- pubspec.lock | 12 ++++++------ scripts/app_config/templates/pubspec.template | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 66cfe0e85..6113ff410 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -532,18 +532,18 @@ packages: dependency: "direct main" description: name: cs_salvium - sha256: "5711a9b547e9e5ba1d91e1c6b37ba94803b0b7c6ef56baf245b270e2a637b839" + sha256: "838a2f21b0ad567f68a5294360c4c96727b722037ae7bfdc26651c99d6c26bd3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" cs_salvium_flutter_libs: dependency: "direct main" description: name: cs_salvium_flutter_libs - sha256: cb2759e3d0829251cb13daa9e012f7821d9717ec1f1dedc9329c4012f99f386c + sha256: d7b6d257a2279526fb67f8f45f835e6432a221e231949829a26272d2bfd35b2b url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" cs_salvium_flutter_libs_android: dependency: transitive description: @@ -580,10 +580,10 @@ packages: dependency: transitive description: name: cs_salvium_flutter_libs_ios - sha256: "4c11cc7499ca7d3a8c0f2b29fcb4eaf4cd1475c5752f34856a3d4c0b721a6319" + sha256: "62739c13186aa4a89dd8dcb04ec7f7a01976a77a7cfa46172434b7c56b93938f" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" cs_salvium_flutter_libs_linux: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 4e60e7857..d5fb421dc 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -222,8 +222,8 @@ dependencies: drift: ^2.22.1 drift_flutter: ^0.2.3 path: ^1.9.1 - cs_salvium: ^1.2.0 - cs_salvium_flutter_libs: ^1.0.2 + cs_salvium: ^1.2.1 + cs_salvium_flutter_libs: ^1.0.3 flutter_mwebd: ^0.0.1-pre.6 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 1896c7f5bcf8694e593f5c5dc9ed9b260efe8362 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 15 Jul 2025 10:23:23 -0600 Subject: [PATCH 169/206] taproot address null error fix --- lib/wallets/crypto_currency/coins/bitcoin_frost.dart | 1 + .../crypto_currency/interfaces/electrumx_currency_interface.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart index 3edaea351..b24316b52 100644 --- a/lib/wallets/crypto_currency/coins/bitcoin_frost.dart +++ b/lib/wallets/crypto_currency/coins/bitcoin_frost.dart @@ -255,6 +255,7 @@ class BitcoinFrost extends FrostCurrency { final clAddress = cl.Address.fromString(address, networkParams); return switch (clAddress) { + cl.P2TRAddress() => AddressType.p2tr, cl.P2PKHAddress() => AddressType.p2pkh, cl.P2WSHAddress() => AddressType.p2sh, cl.P2WPKHAddress() => AddressType.p2wpkh, diff --git a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart index c9d0da2b9..9cc01cf64 100644 --- a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart +++ b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart @@ -18,6 +18,7 @@ mixin ElectrumXCurrencyInterface on Bip39HDCurrency { cl.P2PKHAddress() => AddressType.p2pkh, cl.P2WSHAddress() => AddressType.p2sh, cl.P2WPKHAddress() => AddressType.p2wpkh, + cl.P2TRAddress() => AddressType.p2tr, cl.MwebAddress() => AddressType.mweb, _ => null, }; From a8dd5ebdb1c4883495477cf5241c60949c8c38ae Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 15 Jul 2025 13:02:04 -0600 Subject: [PATCH 170/206] salvium ios lib fix should be there now --- pubspec.lock | 8 ++++---- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 6113ff410..39d500ae1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -540,10 +540,10 @@ packages: dependency: "direct main" description: name: cs_salvium_flutter_libs - sha256: d7b6d257a2279526fb67f8f45f835e6432a221e231949829a26272d2bfd35b2b + sha256: d1e49ed67632f77d863ad3eafc78db8867f155cf9decf156345ec75c92e0d026 url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" cs_salvium_flutter_libs_android: dependency: transitive description: @@ -580,10 +580,10 @@ packages: dependency: transitive description: name: cs_salvium_flutter_libs_ios - sha256: "62739c13186aa4a89dd8dcb04ec7f7a01976a77a7cfa46172434b7c56b93938f" + sha256: "54d18fbac60c8a602e4d0f967ea7d02fab71bff3e032f9576e159229ce372534" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" cs_salvium_flutter_libs_linux: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index d5fb421dc..ae6032744 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -223,7 +223,7 @@ dependencies: drift_flutter: ^0.2.3 path: ^1.9.1 cs_salvium: ^1.2.1 - cs_salvium_flutter_libs: ^1.0.3 + cs_salvium_flutter_libs: ^1.0.4 flutter_mwebd: ^0.0.1-pre.6 mweb_client: ^0.2.0 fixnum: ^1.1.1 From f0e4bac942cee288c0df480969b99cfa743f51ee Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 18 Jul 2025 08:19:12 -0600 Subject: [PATCH 171/206] new wallet solana null error fix --- .../new_wallet_recovery_phrase_warning_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index a3e6f0093..7e3f57d32 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -198,8 +198,8 @@ class _NewWalletRecoveryPhraseWarningViewState mnemonicPassphrase = ref.read(pNewWalletOptions.state).state!.mnemonicPassphrase; } else { - // this may not be epiccash specific? - if (coin is Epiccash) { + // this may not be epiccash and sol specific? + if (coin is Epiccash || coin is Solana) { mnemonicPassphrase = ""; } } From 1d1d27bba80300038633615c706690fd10adba56 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 21 Jul 2025 10:36:22 -0600 Subject: [PATCH 172/206] firo related ui tweaks --- .../spark_names/buy_spark_name_view.dart | 23 ++++++++++++++----- lib/pages/wallet_view/wallet_view.dart | 23 ++++++++++--------- .../sub_widgets/desktop_wallet_features.dart | 14 ++++++----- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart index 01f69fcaf..dafba756a 100644 --- a/lib/pages/spark_names/buy_spark_name_view.dart +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -23,6 +23,7 @@ import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/show_loading.dart'; import '../../utilities/text_styles.dart'; +import '../../wallets/crypto_currency/coins/firo.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../widgets/background.dart'; @@ -80,9 +81,21 @@ class _BuySparkNameViewState extends ConsumerState { } Future _preRegFuture() async { + final chosenAddress = addressController.text; + + if (chosenAddress.isEmpty) { + throw Exception( + "Please select the Spark address you want to link to your Spark Name", + ); + } + final wallet = ref.read(pWallets).getWallet(widget.walletId) as SparkInterface; + if (!(wallet.cryptoCurrency as Firo).validateSparkAddress(chosenAddress)) { + throw Exception("Invalid Spark address selected"); + } + final myAddresses = await wallet.mainDB.isar.addresses .where() @@ -94,10 +107,8 @@ class _BuySparkNameViewState extends ConsumerState { .valueProperty() .findAll(); - final chosenAddress = addressController.text; - if (!myAddresses.contains(chosenAddress)) { - throw Exception("Address does not belong to this wallet"); + throw Exception("Selected Spark address does not belong to this wallet"); } final txData = await wallet.prepareSparkNameTransaction( @@ -274,7 +285,7 @@ class _BuySparkNameViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Address", + "Spark address", style: Util.isDesktop ? STextStyles.w500_14(context).copyWith( @@ -311,7 +322,7 @@ class _BuySparkNameViewState extends ConsumerState { isDense: true, contentPadding: const EdgeInsets.all(16), hintStyle: STextStyles.fieldLabel(context), - hintText: "Address", + hintText: "Spark address (required)", border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, @@ -360,7 +371,7 @@ class _BuySparkNameViewState extends ConsumerState { isDense: true, contentPadding: const EdgeInsets.all(16), hintStyle: STextStyles.fieldLabel(context), - hintText: "Additional info", + hintText: "Additional info (optional)", border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index dd4c29560..1bb76d59e 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -1060,6 +1060,7 @@ class _WalletViewState extends ConsumerState { ), if (Constants.enableExchange && ref.watch(pWalletCoin(walletId)) is! FrostCurrency && + wallet is! FiroWallet && AppConfig.hasFeature(AppFeature.buy) && showExchange) WalletNavigationBarItemData( @@ -1067,6 +1068,17 @@ class _WalletViewState extends ConsumerState { icon: const BuyNavIcon(), onTap: () => _onBuyPressed(context), ), + if (wallet is SparkInterface) + WalletNavigationBarItemData( + label: "Names", + icon: const PaynymNavIcon(), + onTap: () { + Navigator.of(context).pushNamed( + SparkNamesHomeView.routeName, + arguments: widget.walletId, + ); + }, + ), ], moreItems: [ if (ref.watch( @@ -1153,17 +1165,6 @@ class _WalletViewState extends ConsumerState { ); }, ), - if (wallet is SparkInterface) - WalletNavigationBarItemData( - label: "Names", - icon: const PaynymNavIcon(), - onTap: () { - Navigator.of(context).pushNamed( - SparkNamesHomeView.routeName, - arguments: widget.walletId, - ); - }, - ), if (!viewOnly && wallet is PaynymInterface) WalletNavigationBarItemData( label: "PayNym", diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 63722608b..71cd7f196 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -403,6 +403,10 @@ class _DesktopWalletFeaturesState extends ConsumerState { Assets.svg.recycle, _onAnonymizeAllPressed, ), + + if (wallet is SparkInterface) + (WalletFeature.sparkNames, Assets.svg.robotHead, _onSparkNamesPressed), + if (!isViewOnly && Constants.enableExchange && AppConfig.hasFeature(AppFeature.swap) && @@ -412,9 +416,6 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (showExchange && AppConfig.hasFeature(AppFeature.buy)) (WalletFeature.buy, Assets.svg.swap, _onBuyPressed), - if (wallet is SparkInterface) - (WalletFeature.sparkNames, Assets.svg.robotHead, _onSparkNamesPressed), - if (showCoinControl) ( WalletFeature.coinControl, @@ -463,9 +464,10 @@ class _DesktopWalletFeaturesState extends ConsumerState { final options = _getOptions( wallet, - ref.watch( - prefsChangeNotifierProvider.select((value) => value.enableExchange), - ), + wallet is! FiroWallet && + ref.watch( + prefsChangeNotifierProvider.select((value) => value.enableExchange), + ), (wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( From db9a949274e9500a230d5609298c0d228016c76e Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Jul 2025 08:52:21 -0600 Subject: [PATCH 173/206] firo spark coin instantsend isLocked addition to local model --- lib/electrumx_rpc/electrumx_client.dart | 3 +- .../electrumx_response/spark_models.dart | 5 +- .../spark_coins/spark_coins_view.dart | 63 +++++++--------- lib/wallets/isar/models/spark_coin.dart | 21 +++--- lib/wallets/isar/models/spark_coin.g.dart | 72 +++++++++++++++++++ .../spark_interface.dart | 7 +- 6 files changed, 119 insertions(+), 52 deletions(-) diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index da5cf2778..befe70fc3 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -1036,7 +1036,7 @@ class ElectrumXClient { } } - /// Returns the txids of the current transactions found in the mempool + /// Returns the txids of the current spark transactions found in the mempool Future> getMempoolTxids({String? requestID}) async { try { final start = DateTime.now(); @@ -1089,6 +1089,7 @@ class ElectrumXClient { // the space after lTags is required lol lTags: List.from(entry.value["lTags "] as List), coins: List.from(entry.value["coins"] as List), + isLocked: entry.value["isLocked"] as bool, ), ); } diff --git a/lib/models/electrumx_response/spark_models.dart b/lib/models/electrumx_response/spark_models.dart index 43bf9f61f..22c6cf25f 100644 --- a/lib/models/electrumx_response/spark_models.dart +++ b/lib/models/electrumx_response/spark_models.dart @@ -3,12 +3,14 @@ class SparkMempoolData { final List serialContext; final List lTags; final List coins; + final bool isLocked; SparkMempoolData({ required this.txid, required this.serialContext, required this.lTags, required this.coins, + required this.isLocked, }); @override @@ -17,7 +19,8 @@ class SparkMempoolData { "txid: $txid, " "serialContext: $serialContext, " "lTags: $lTags, " - "coins: $coins" + "coins: $coins, " + "isLocked: $isLocked" "}"; } } diff --git a/lib/pages_desktop_specific/spark_coins/spark_coins_view.dart b/lib/pages_desktop_specific/spark_coins/spark_coins_view.dart index 8a937fab3..c2f2519c6 100644 --- a/lib/pages_desktop_specific/spark_coins/spark_coins_view.dart +++ b/lib/pages_desktop_specific/spark_coins/spark_coins_view.dart @@ -26,10 +26,7 @@ import '../../widgets/desktop/desktop_scaffold.dart'; import '../../widgets/isar_collection_watcher_list.dart'; class SparkCoinsView extends ConsumerWidget { - const SparkCoinsView({ - super.key, - required this.walletId, - }); + const SparkCoinsView({super.key, required this.walletId}); static const title = "Spark coins"; static const String routeName = "/sparkCoinsView"; @@ -47,32 +44,27 @@ class SparkCoinsView extends ConsumerWidget { leading: Expanded( child: Row( children: [ - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), AppBarIconButton( size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: Navigator.of(context).pop, ), - const SizedBox( - width: 12, - ), - Text( - title, - style: STextStyles.desktopH3(context), - ), + const SizedBox(width: 12), + Text(title, style: STextStyles.desktopH3(context)), const Spacer(), ], ), @@ -80,10 +72,7 @@ class SparkCoinsView extends ConsumerWidget { useSpacers: false, isCompactHeight: true, ), - body: Padding( - padding: const EdgeInsets.all(24), - child: child, - ), + body: Padding(padding: const EdgeInsets.all(24), child: child), ); }, child: ConditionalParent( @@ -98,26 +87,23 @@ class SparkCoinsView extends ConsumerWidget { leading: AppBarBackButton( onPressed: () => Navigator.of(context).pop(), ), - title: Text( - title, - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: child, + title: Text(title, style: STextStyles.navBarTitle(context)), ), + body: SafeArea(child: child), ), ); }, child: IsarCollectionWatcherList( itemName: title, - queryBuilder: () => ref - .read(mainDBProvider) - .isar - .sparkCoins - .where() - .walletIdEqualToAnyLTagHash(walletId) - .sortByHeightDesc(), + queryBuilder: + () => + ref + .read(mainDBProvider) + .isar + .sparkCoins + .where() + .walletIdEqualToAnyLTagHash(walletId) + .sortByHeightDesc(), itemBuilder: (SparkCoin? coin) { return [ ("TXID", coin?.txHash ?? "", 9), @@ -129,6 +115,7 @@ class SparkCoinsView extends ConsumerWidget { ("Group ID", coin?.groupId.toString() ?? "", 2), ("Type", coin?.type.name ?? "", 2), ("Used", coin?.isUsed.toString() ?? "", 2), + ("Locked", coin?.isLocked.toString() ?? "", 2), ]; }, ), diff --git a/lib/wallets/isar/models/spark_coin.dart b/lib/wallets/isar/models/spark_coin.dart index 9501bf06d..c16cee253 100644 --- a/lib/wallets/isar/models/spark_coin.dart +++ b/lib/wallets/isar/models/spark_coin.dart @@ -17,13 +17,7 @@ enum SparkCoinType { class SparkCoin { Id id = Isar.autoIncrement; - @Index( - unique: true, - replace: true, - composite: [ - CompositeIndex("lTagHash"), - ], - ) + @Index(unique: true, replace: true, composite: [CompositeIndex("lTagHash")]) final String walletId; @enumerated @@ -55,6 +49,10 @@ class SparkCoin { final String? serializedCoinB64; final String? contextB64; + // prefix name with zzz to ensure serialization order remains unchanged + @Name("zzzIsLocked") + final bool? isLocked; + @ignore BigInt get value => BigInt.parse(valueIntString); @@ -66,10 +64,7 @@ class SparkCoin { return max(0, currentChainHeight - (height! - 1)); } - bool isConfirmed( - int currentChainHeight, - int minimumConfirms, - ) { + bool isConfirmed(int currentChainHeight, int minimumConfirms) { final confirmations = getConfirmations(currentChainHeight); return confirmations >= minimumConfirms; } @@ -93,6 +88,7 @@ class SparkCoin { this.height, this.serializedCoinB64, this.contextB64, + this.isLocked, }); SparkCoin copyWith({ @@ -113,6 +109,7 @@ class SparkCoin { int? height, String? serializedCoinB64, String? contextB64, + bool? isLocked, }) { return SparkCoin( walletId: walletId, @@ -134,6 +131,7 @@ class SparkCoin { height: height ?? this.height, serializedCoinB64: serializedCoinB64 ?? this.serializedCoinB64, contextB64: contextB64 ?? this.contextB64, + isLocked: isLocked ?? this.isLocked, ); } @@ -158,6 +156,7 @@ class SparkCoin { ', height: $height' ', serializedCoinB64: $serializedCoinB64' ', contextB64: $contextB64' + ', isLocked: $isLocked' ')'; } } diff --git a/lib/wallets/isar/models/spark_coin.g.dart b/lib/wallets/isar/models/spark_coin.g.dart index 717d1a2c6..c84e0db40 100644 --- a/lib/wallets/isar/models/spark_coin.g.dart +++ b/lib/wallets/isar/models/spark_coin.g.dart @@ -107,6 +107,11 @@ const SparkCoinSchema = CollectionSchema( id: 17, name: r'walletId', type: IsarType.string, + ), + r'zzzIsLocked': PropertySchema( + id: 18, + name: r'zzzIsLocked', + type: IsarType.bool, ) }, estimateSize: _sparkCoinEstimateSize, @@ -229,6 +234,7 @@ void _sparkCoinSerialize( writer.writeByte(offsets[15], object.type.index); writer.writeString(offsets[16], object.valueIntString); writer.writeString(offsets[17], object.walletId); + writer.writeBool(offsets[18], object.isLocked); } SparkCoin _sparkCoinDeserialize( @@ -257,6 +263,7 @@ SparkCoin _sparkCoinDeserialize( SparkCoinType.mint, valueIntString: reader.readString(offsets[16]), walletId: reader.readString(offsets[17]), + isLocked: reader.readBoolOrNull(offsets[18]), ); object.id = id; return object; @@ -306,6 +313,8 @@ P _sparkCoinDeserializeProp

      ( return (reader.readString(offset)) as P; case 17: return (reader.readString(offset)) as P; + case 18: + return (reader.readBoolOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } @@ -2867,6 +2876,33 @@ extension SparkCoinQueryFilter )); }); } + + QueryBuilder isLockedIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'zzzIsLocked', + )); + }); + } + + QueryBuilder + isLockedIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'zzzIsLocked', + )); + }); + } + + QueryBuilder isLockedEqualTo( + bool? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'zzzIsLocked', + value: value, + )); + }); + } } extension SparkCoinQueryObject @@ -3034,6 +3070,18 @@ extension SparkCoinQuerySortBy on QueryBuilder { return query.addSortBy(r'walletId', Sort.desc); }); } + + QueryBuilder sortByIsLocked() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zzzIsLocked', Sort.asc); + }); + } + + QueryBuilder sortByIsLockedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zzzIsLocked', Sort.desc); + }); + } } extension SparkCoinQuerySortThenBy @@ -3208,6 +3256,18 @@ extension SparkCoinQuerySortThenBy return query.addSortBy(r'walletId', Sort.desc); }); } + + QueryBuilder thenByIsLocked() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zzzIsLocked', Sort.asc); + }); + } + + QueryBuilder thenByIsLockedDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'zzzIsLocked', Sort.desc); + }); + } } extension SparkCoinQueryWhereDistinct @@ -3332,6 +3392,12 @@ extension SparkCoinQueryWhereDistinct return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); }); } + + QueryBuilder distinctByIsLocked() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'zzzIsLocked'); + }); + } } extension SparkCoinQueryProperty @@ -3453,4 +3519,10 @@ extension SparkCoinQueryProperty return query.addPropertyName(r'walletId'); }); } + + QueryBuilder isLockedProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'zzzIsLocked'); + }); + } } diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index d5d5e756d..af6894676 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -880,7 +880,12 @@ mixin SparkInterface // add checked txids after identification _mempoolTxidsChecked.addAll(checkedTxids); - result.addAll(myCoins); + for (final coin in myCoins) { + final match = sparkDataToCheck.firstWhere( + (e) => e.serialContext.contains(coin.contextB64!), + ); + result.add(coin.copyWith(isLocked: match.isLocked)); + } } return result; From 50c800399bb7143d12e49650031018374f5f34c7 Mon Sep 17 00:00:00 2001 From: Verycutecat <86484809+Verycutecat@users.noreply.github.com> Date: Wed, 16 Jul 2025 18:09:52 +0700 Subject: [PATCH 174/206] Update block explorer in nano.dart Replace NanoLooker (down) with Nanexplorer. (cherry picked from commit 193a0b598399ce97f2ecba1c4aba7263546bd189) --- lib/wallets/crypto_currency/coins/nano.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/crypto_currency/coins/nano.dart b/lib/wallets/crypto_currency/coins/nano.dart index 04622c54d..77fc9e3a7 100644 --- a/lib/wallets/crypto_currency/coins/nano.dart +++ b/lib/wallets/crypto_currency/coins/nano.dart @@ -95,7 +95,7 @@ class Nano extends NanoCurrency { Uri defaultBlockExplorer(String txid) { switch (network) { case CryptoCurrencyNetwork.main: - return Uri.parse("https://www.nanolooker.com/block/$txid"); + return Uri.parse("https://nanexplorer.com/nano/blocks/$txid"); default: throw Exception( "Unsupported network for defaultBlockExplorer(): $network", From dfae25485d1a3b8023d329fea818e8a88f36ef1a Mon Sep 17 00:00:00 2001 From: Verycutecat <86484809+Verycutecat@users.noreply.github.com> Date: Wed, 16 Jul 2025 18:15:34 +0700 Subject: [PATCH 175/206] Update block explorer in banano.dart Replace BananoLooker (down) with official Creeper instance run by Banano team. (cherry picked from commit f5432ab385018d5667c630907fcf09db47578f35) --- lib/wallets/crypto_currency/coins/banano.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/crypto_currency/coins/banano.dart b/lib/wallets/crypto_currency/coins/banano.dart index eccb6fe38..adae4331e 100644 --- a/lib/wallets/crypto_currency/coins/banano.dart +++ b/lib/wallets/crypto_currency/coins/banano.dart @@ -89,7 +89,7 @@ class Banano extends NanoCurrency { Uri defaultBlockExplorer(String txid) { switch (network) { case CryptoCurrencyNetwork.main: - return Uri.parse("https://www.bananolooker.com/block/$txid"); + return Uri.parse("https://creeper.banano.cc/hash/$txid"); default: throw Exception( "Unsupported network for defaultBlockExplorer(): $network", From 899356094f55949d944811267ee0d53eb5276b25 Mon Sep 17 00:00:00 2001 From: Julian Date: Tue, 22 Jul 2025 09:44:07 -0600 Subject: [PATCH 176/206] disable buy/renew button if no address in field --- lib/pages/spark_names/buy_spark_name_view.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/pages/spark_names/buy_spark_name_view.dart b/lib/pages/spark_names/buy_spark_name_view.dart index dafba756a..036a551d3 100644 --- a/lib/pages/spark_names/buy_spark_name_view.dart +++ b/lib/pages/spark_names/buy_spark_name_view.dart @@ -60,6 +60,7 @@ class _BuySparkNameViewState extends ConsumerState { String get _title => isRenewal ? "Renew name" : "Buy name"; int _years = 1; + late bool _buttonEnabled; bool _lockAddressFill = false; Future _fillCurrentReceiving() async { @@ -185,10 +186,19 @@ class _BuySparkNameViewState extends ConsumerState { @override void initState() { super.initState(); + if (isRenewal) { additionalInfoController.text = widget.nameToRenew!.additionalInfo ?? ""; addressController.text = widget.nameToRenew!.address; } + _buttonEnabled = addressController.text.isNotEmpty; + addressController.addListener(() { + if (mounted) { + setState(() { + _buttonEnabled = addressController.text.isNotEmpty; + }); + } + }); } @override @@ -527,7 +537,8 @@ class _BuySparkNameViewState extends ConsumerState { PrimaryButton( label: isRenewal ? "Renew" : "Buy", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, - onPressed: _prepareNameTx, + enabled: _buttonEnabled, + onPressed: _buttonEnabled ? _prepareNameTx : null, ), SizedBox(height: Util.isDesktop ? 32 : 16), ], From ba893652efceb7a3c4af6094136eb9251ad6ea10 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Jul 2025 10:12:05 -0600 Subject: [PATCH 177/206] temp eth sync "fix" --- lib/wallets/wallet/impl/ethereum_wallet.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index 35e0bc174..efb19bcbc 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -338,7 +338,14 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final Amount txFee = element.gasCost; final transactionAmount = element.value; final addressFrom = checksumEthereumAddress(element.from); - final addressTo = checksumEthereumAddress(element.to); + final String addressTo; + try { + addressTo = checksumEthereumAddress(element.to); + } catch (e, s) { + Logging.instance.w("Ignoring eth transaction:\n$e\n$s"); + // temp "fix" + continue; + } bool isIncoming; bool txFailed = false; From 394f469069a2a69889c0ceddc11c35b427957b42 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Jul 2025 10:55:12 -0600 Subject: [PATCH 178/206] fix (bandaid?) xelis open-close-open wallet quickly bug --- .../wallet/intermediate/lib_xelis_wallet.dart | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart index 901223469..2415af7bd 100644 --- a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart @@ -327,6 +327,10 @@ abstract class LibXelisWallet @override Future open() async { + while (exitInProgress) { + await Future.delayed(const Duration(milliseconds: 500)); + } + try { await connect(); } catch (e) { @@ -339,18 +343,25 @@ abstract class LibXelisWallet unawaited(refresh()); } + bool exitInProgress = false; + @override Future exit() async { - await refreshMutex.protect(() async { - timer?.cancel(); - timer = null; - - await _eventSubscription?.cancel(); - _eventSubscription = null; - - await libXelisWallet?.offlineMode(); - await super.exit(); - }); + exitInProgress = true; + try { + await refreshMutex.protect(() async { + timer?.cancel(); + timer = null; + + await _eventSubscription?.cancel(); + _eventSubscription = null; + + await libXelisWallet?.offlineMode(); + await super.exit(); + }); + } finally { + exitInProgress = false; + } } void invalidSeedLengthCheck(int length) { From 801b504c9891068dafeb64484f618c09bbcd00e1 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 09:33:57 -0600 Subject: [PATCH 179/206] disable/remove majestic bank --- lib/models/isar/exchange_cache/currency.dart | 4 +- lib/pages/exchange_view/exchange_form.dart | 2 - .../exchange_provider_options.dart | 24 +- .../exchange_view/trade_details_view.dart | 151 ++-- lib/services/exchange/exchange.dart | 6 +- .../exchange_data_loading_service.dart | 47 +- .../majestic_bank/majestic_bank_api.dart | 770 +++++++++--------- .../majestic_bank/majestic_bank_exchange.dart | 692 ++++++++-------- lib/services/notifications_service.dart | 68 +- lib/utilities/assets.dart | 9 +- 10 files changed, 863 insertions(+), 910 deletions(-) diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index 04c510186..f719f5a3c 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -13,7 +13,6 @@ import 'package:isar/isar.dart'; import '../../../app_config.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../../services/exchange/trocador/trocador_exchange.dart'; import 'pair.dart'; @@ -82,8 +81,7 @@ class Currency { // case const (SimpleSwapExchange): // currently a hardcoded of coins so we can just - const (MajesticBankExchange) => ticker.toLowerCase(), - + // const (MajesticBankExchange) => ticker.toLowerCase(), const (TrocadorExchange) => (network == "Mainnet" ? ticker.toLowerCase() : network), diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 93e15c4bb..675cd30cd 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -30,7 +30,6 @@ import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; import '../../services/exchange/exchange_response.dart'; -import '../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../services/exchange/trocador/trocador_exchange.dart'; import '../../themes/stack_colors.dart'; @@ -80,7 +79,6 @@ class _ExchangeFormState extends ConsumerState { return Exchange.exchangesWithTorSupport; } else { return [ - MajesticBankExchange.instance, ChangeNowExchange.instance, TrocadorExchange.instance, NanswapExchange.instance, diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart index 6bc4b5c04..a2ef39305 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart @@ -15,7 +15,6 @@ import '../../../models/exchange/aggregate_currency.dart'; import '../../../providers/providers.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; @@ -82,11 +81,6 @@ class _ExchangeProviderOptionsState sendCurrency: sendCurrency, receiveCurrency: receivingCurrency, ); - final showMajesticBank = exchangeSupported( - exchangeName: MajesticBankExchange.exchangeName, - sendCurrency: sendCurrency, - receiveCurrency: receivingCurrency, - ); final showTrocador = exchangeSupported( exchangeName: TrocadorExchange.exchangeName, sendCurrency: sendCurrency, @@ -112,20 +106,7 @@ class _ExchangeProviderOptionsState fixedRate: widget.fixedRate, reversed: widget.reversed, ), - if (showChangeNow && showMajesticBank) - isDesktop - ? Container( - height: 1, - color: Theme.of(context).extension()!.background, - ) - : const SizedBox(height: 16), - if (showMajesticBank) - ExchangeOption( - exchange: MajesticBankExchange.instance, - fixedRate: widget.fixedRate, - reversed: widget.reversed, - ), - if ((showChangeNow || showMajesticBank) && showTrocador) + if (showChangeNow && showTrocador) isDesktop ? Container( height: 1, @@ -138,8 +119,7 @@ class _ExchangeProviderOptionsState reversed: widget.reversed, exchange: TrocadorExchange.instance, ), - if ((showChangeNow || showMajesticBank || showTrocador) && - showNanswap) + if ((showChangeNow || showTrocador) && showNanswap) isDesktop ? Container( height: 1, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index a0ccd79a5..329f1d572 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -29,7 +29,6 @@ import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange.dart'; -import '../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../services/exchange/simpleswap/simpleswap_exchange.dart'; import '../../services/exchange/trocador/trocador_exchange.dart'; @@ -101,7 +100,7 @@ class _TradeDetailsViewState extends ConsumerState { .trades .firstWhere((e) => e.tradeId == tradeId); - if (mounted) { + if (mounted && trade.exchangeName != "Majestic Bank") { final exchange = Exchange.fromName(trade.exchangeName); final response = await exchange.updateTrade(trade); @@ -435,36 +434,6 @@ class _TradeDetailsViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Status", style: STextStyles.itemSubtitle(context)), - if (trade.exchangeName == - MajesticBankExchange.exchangeName && - trade.status == "Completed") - Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: () { - showDialog( - context: context, - builder: - (context) => const StackOkDialog( - title: "Trade Info", - message: - "Majestic Bank does not store order data indefinitely", - ), - ); - }, - child: SvgPicture.asset( - Assets.svg.circleInfo, - height: 20, - width: 20, - color: - Theme.of( - context, - ).extension()!.infoItemIcons, - ), - ), - ], - ), ], ), const SizedBox(height: 4), @@ -1202,68 +1171,66 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop ? const _Divider() : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Tracking", style: STextStyles.itemSubtitle(context)), - const SizedBox(height: 4), - Builder( - builder: (context) { - late final String url; - switch (trade.exchangeName) { - case ChangeNowExchange.exchangeName: - url = - "https://changenow.io/exchange/txs/${trade.tradeId}"; - break; - case SimpleSwapExchange.exchangeName: - url = - "https://simpleswap.io/exchange?id=${trade.tradeId}"; - break; - case MajesticBankExchange.exchangeName: - url = - "https://majesticbank.sc/track?trx=${trade.tradeId}"; - break; - case NanswapExchange.exchangeName: - url = - "https://nanswap.com/transaction/${trade.tradeId}"; - break; - - default: - if (trade.exchangeName.startsWith( - TrocadorExchange.exchangeName, - )) { + if (trade.exchangeName != "Majestic Bank") + isDesktop ? const _Divider() : const SizedBox(height: 12), + if (trade.exchangeName != "Majestic Bank") + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Tracking", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 4), + Builder( + builder: (context) { + late final String url; + switch (trade.exchangeName) { + case ChangeNowExchange.exchangeName: url = - "https://trocador.app/en/checkout/${trade.tradeId}"; - } - } - return ConditionalParent( - condition: isDesktop, - builder: - (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), - child: GestureDetector( - onTap: () { - launchUrl( - Uri.parse(url), - mode: LaunchMode.externalApplication, - ); - }, - child: Text(url, style: STextStyles.link2(context)), - ), - ); - }, - ), - ], + "https://changenow.io/exchange/txs/${trade.tradeId}"; + break; + case SimpleSwapExchange.exchangeName: + url = + "https://simpleswap.io/exchange?id=${trade.tradeId}"; + break; + case NanswapExchange.exchangeName: + url = + "https://nanswap.com/transaction/${trade.tradeId}"; + break; + + default: + if (trade.exchangeName.startsWith( + TrocadorExchange.exchangeName, + )) { + url = + "https://trocador.app/en/checkout/${trade.tradeId}"; + } + } + return ConditionalParent( + condition: isDesktop, + builder: + (child) => MouseRegion( + cursor: SystemMouseCursors.click, + child: child, + ), + child: GestureDetector( + onTap: () { + launchUrl( + Uri.parse(url), + mode: LaunchMode.externalApplication, + ); + }, + child: Text(url, style: STextStyles.link2(context)), + ), + ); + }, + ), + ], + ), ), - ), if (!isDesktop) const SizedBox(height: 12), if (!isDesktop && showSendFromStackButton) SecondaryButton( diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index f25bddc77..05ca33e87 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -30,8 +30,8 @@ abstract class Exchange { return ChangeNowExchange.instance; case SimpleSwapExchange.exchangeName: return SimpleSwapExchange.instance; - case MajesticBankExchange.exchangeName: - return MajesticBankExchange.instance; + // case MajesticBankExchange.exchangeName: + // return MajesticBankExchange.instance; case TrocadorExchange.exchangeName: return TrocadorExchange.instance; case NanswapExchange.exchangeName: @@ -106,7 +106,7 @@ abstract class Exchange { /// /// Add to this list when adding a new exchange which supports Tor. static List get exchangesWithTorSupport => [ - MajesticBankExchange.instance, + // MajesticBankExchange.instance, TrocadorExchange.instance, NanswapExchange.instance, // Maybe?? ]; diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index f1a181104..78fb0117f 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -23,7 +23,6 @@ import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../utilities/stack_file_system.dart'; import 'change_now/change_now_exchange.dart'; -import 'majestic_bank/majestic_bank_exchange.dart'; import 'nanswap/nanswap_exchange.dart'; import 'trocador/trocador_exchange.dart'; @@ -194,7 +193,7 @@ class ExchangeDataLoadingService { // Exchanges which support Tor just get treated normally. final futures = [ - loadMajesticBankCurrencies(), + // loadMajesticBankCurrencies(), loadTrocadorCurrencies(), loadNanswapCurrencies(), ]; @@ -359,28 +358,28 @@ class ExchangeDataLoadingService { // } // } - Future loadMajesticBankCurrencies() async { - if (_isar == null) { - await initDB(); - } - final exchange = MajesticBankExchange.instance; - final responseCurrencies = await exchange.getAllCurrencies(false); - - if (responseCurrencies.value != null) { - await isar.writeTxn(() async { - final idsToDelete = - await isar.currencies - .where() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .idProperty() - .findAll(); - await isar.currencies.deleteAll(idsToDelete); - await isar.currencies.putAll(responseCurrencies.value!); - }); - } else { - Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); - } - } + // Future loadMajesticBankCurrencies() async { + // if (_isar == null) { + // await initDB(); + // } + // final exchange = MajesticBankExchange.instance; + // final responseCurrencies = await exchange.getAllCurrencies(false); + // + // if (responseCurrencies.value != null) { + // await isar.writeTxn(() async { + // final idsToDelete = + // await isar.currencies + // .where() + // .exchangeNameEqualTo(MajesticBankExchange.exchangeName) + // .idProperty() + // .findAll(); + // await isar.currencies.deleteAll(idsToDelete); + // await isar.currencies.putAll(responseCurrencies.value!); + // }); + // } else { + // Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); + // } + // } Future loadTrocadorCurrencies() async { if (_isar == null) { diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index ee87bf159..7d713d6d6 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -1,385 +1,385 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'dart:convert'; - -import 'package:decimal/decimal.dart'; - -import '../../../exceptions/exchange/exchange_exception.dart'; -import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; -import '../../../exceptions/exchange/pair_unavailable_exception.dart'; -import '../../../models/exchange/majestic_bank/mb_limit.dart'; -import '../../../models/exchange/majestic_bank/mb_order.dart'; -import '../../../models/exchange/majestic_bank/mb_order_calculation.dart'; -import '../../../models/exchange/majestic_bank/mb_order_status.dart'; -import '../../../models/exchange/majestic_bank/mb_rate.dart'; -import '../../../networking/http.dart'; -import '../../../utilities/logger.dart'; -import '../../../utilities/prefs.dart'; -import '../../tor_service.dart'; -import '../exchange_response.dart'; - -class MajesticBankAPI { - static const String scheme = "https"; - static const String authority = "majesticbank.sc"; - static const String version = "v1"; - static const kMajesticBankRefCode = "rjWugM"; - - MajesticBankAPI._(); - - static final MajesticBankAPI _instance = MajesticBankAPI._(); - - static MajesticBankAPI get instance => _instance; - - HTTP client = HTTP(); - - Uri _buildUri({required String endpoint, Map? params}) { - return Uri.https(authority, "/api/$version/$endpoint", params); - } - - Future _makeGetRequest(Uri uri) async { - // final client = this.client ?? http.Client(); - int code = -1; - try { - final response = await client.get( - url: uri, - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - code = response.code; - - final parsed = jsonDecode(response.body); - - return parsed; - } catch (e, s) { - Logging.instance.e( - "_makeRequest($uri) HTTP:$code threw: ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - Future>> getRates() async { - final uri = _buildUri(endpoint: "rates"); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.from(jsonObject as Map); - final List rates = []; - for (final key in map.keys) { - final currencies = key.split("-"); - if (currencies.length == 2) { - final rate = MBRate( - fromCurrency: currencies.first, - toCurrency: currencies.last, - rate: Decimal.parse(map[key].toString()), - ); - rates.add(rate); - } - } - return ExchangeResponse(value: rates); - } catch (e, s) { - Logging.instance.e("getRates exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> getLimit({ - required String fromCurrency, - }) async { - final uri = _buildUri( - endpoint: "limits", - params: {"from_currency": fromCurrency}, - ); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.from(jsonObject as Map); - - final limit = MBLimit( - currency: fromCurrency, - min: Decimal.parse(map["min"].toString()), - max: Decimal.parse(map["max"].toString()), - ); - - return ExchangeResponse(value: limit); - } catch (e, s) { - Logging.instance.e("getLimits exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future>> getLimits() async { - final uri = _buildUri( - endpoint: - "rates", // limits are included in the rates call for some reason??? - ); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.from(jsonObject as Map)["limits"] as Map; - final List limits = []; - for (final key in map.keys) { - final limit = MBLimit( - currency: key as String, - min: Decimal.parse(map[key]["min"].toString()), - max: Decimal.parse(map[key]["max"].toString()), - ); - limits.add(limit); - } - - return ExchangeResponse(value: limits); - } catch (e, s) { - Logging.instance.e("getLimits exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// If [reversed] then the amount is the expected receive_amount, otherwise - /// the amount is assumed to be the from_amount. - Future> calculateOrder({ - required String amount, - required bool reversed, - required String fromCurrency, - required String receiveCurrency, - }) async { - final params = { - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - }; - - if (reversed) { - params["receive_amount"] = amount; - } else { - params["from_amount"] = amount; - } - - final uri = _buildUri(endpoint: "calculate", params: params); - - try { - final jsonObject = await _makeGetRequest(uri); - final map = Map.from(jsonObject as Map); - - if (map["error"] != null) { - final errorMessage = map["extra"] as String?; - if (errorMessage != null && - errorMessage.startsWith("Bad") && - errorMessage.endsWith("currency symbol")) { - return ExchangeResponse( - exception: PairUnavailableException( - errorMessage, - ExchangeExceptionType.generic, - ), - ); - } else { - return ExchangeResponse( - exception: ExchangeException( - errorMessage ?? "Error: ${map["error"]}", - ExchangeExceptionType.generic, - ), - ); - } - } - - final result = MBOrderCalculation( - fromCurrency: map["from_currency"] as String, - fromAmount: Decimal.parse(map["from_amount"].toString()), - receiveCurrency: map["receive_currency"] as String, - receiveAmount: Decimal.parse(map["receive_amount"].toString()), - ); - - return ExchangeResponse(value: result); - } catch (e, s) { - Logging.instance.e( - "calculateOrder $fromCurrency-$receiveCurrency exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> createOrder({ - required String fromAmount, - required String fromCurrency, - required String receiveCurrency, - required String receiveAddress, - }) async { - final params = { - "from_amount": fromAmount, - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - "receive_address": receiveAddress, - "referral_code": kMajesticBankRefCode, - }; - - final uri = _buildUri(endpoint: "exchange", params: params); - - try { - final now = DateTime.now(); - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - final order = MBOrder( - orderId: json["trx"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - orderType: MBOrderType.floating, - expiration: json["expiration"] as int, - createdAt: now, - ); - - return ExchangeResponse(value: order); - } catch (e, s) { - Logging.instance.e("createOrder exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// Fixed rate for 10 minutes, useful for payments. - /// If [reversed] then the amount is the expected receive_amount, otherwise - /// the amount is assumed to be the from_amount. - Future> createFixedRateOrder({ - required String amount, - required String fromCurrency, - required String receiveCurrency, - required String receiveAddress, - required bool reversed, - }) async { - final params = { - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - "receive_address": receiveAddress, - "referral_code": kMajesticBankRefCode, - }; - - if (reversed) { - params["receive_amount"] = amount; - } else { - params["from_amount"] = amount; - } - - final uri = _buildUri(endpoint: "pay", params: params); - - try { - final now = DateTime.now(); - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - final order = MBOrder( - orderId: json["trx"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - orderType: MBOrderType.fixed, - expiration: json["expiration"] as int, - createdAt: now, - ); - - return ExchangeResponse(value: order); - } catch (e, s) { - Logging.instance.e( - "createFixedRateOrder exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> trackOrder({ - required String orderId, - }) async { - final uri = _buildUri(endpoint: "track", params: {"trx": orderId}); - - try { - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - if (json.length == 2) { - return ExchangeResponse( - exception: MBException( - json["status"] as String, - ExchangeExceptionType.orderNotFound, - ), - ); - } - - final status = MBOrderStatus( - orderId: json["trx"] as String, - status: json["status"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - received: Decimal.parse(json["received"].toString()), - confirmed: Decimal.parse(json["confirmed"].toString()), - ); - - return ExchangeResponse(value: status); - } catch (e, s) { - Logging.instance.e( - "trackOrder exception when trying to parse $json: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'dart:convert'; +// +// import 'package:decimal/decimal.dart'; +// +// import '../../../exceptions/exchange/exchange_exception.dart'; +// import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; +// import '../../../exceptions/exchange/pair_unavailable_exception.dart'; +// import '../../../models/exchange/majestic_bank/mb_limit.dart'; +// import '../../../models/exchange/majestic_bank/mb_order.dart'; +// import '../../../models/exchange/majestic_bank/mb_order_calculation.dart'; +// import '../../../models/exchange/majestic_bank/mb_order_status.dart'; +// import '../../../models/exchange/majestic_bank/mb_rate.dart'; +// import '../../../networking/http.dart'; +// import '../../../utilities/logger.dart'; +// import '../../../utilities/prefs.dart'; +// import '../../tor_service.dart'; +// import '../exchange_response.dart'; +// +// class MajesticBankAPI { +// static const String scheme = "https"; +// static const String authority = "majesticbank.sc"; +// static const String version = "v1"; +// static const kMajesticBankRefCode = "rjWugM"; +// +// MajesticBankAPI._(); +// +// static final MajesticBankAPI _instance = MajesticBankAPI._(); +// +// static MajesticBankAPI get instance => _instance; +// +// HTTP client = HTTP(); +// +// Uri _buildUri({required String endpoint, Map? params}) { +// return Uri.https(authority, "/api/$version/$endpoint", params); +// } +// +// Future _makeGetRequest(Uri uri) async { +// // final client = this.client ?? http.Client(); +// int code = -1; +// try { +// final response = await client.get( +// url: uri, +// proxyInfo: +// Prefs.instance.useTor +// ? TorService.sharedInstance.getProxyInfo() +// : null, +// ); +// +// code = response.code; +// +// final parsed = jsonDecode(response.body); +// +// return parsed; +// } catch (e, s) { +// Logging.instance.e( +// "_makeRequest($uri) HTTP:$code threw: ", +// error: e, +// stackTrace: s, +// ); +// rethrow; +// } +// } +// +// Future>> getRates() async { +// final uri = _buildUri(endpoint: "rates"); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.from(jsonObject as Map); +// final List rates = []; +// for (final key in map.keys) { +// final currencies = key.split("-"); +// if (currencies.length == 2) { +// final rate = MBRate( +// fromCurrency: currencies.first, +// toCurrency: currencies.last, +// rate: Decimal.parse(map[key].toString()), +// ); +// rates.add(rate); +// } +// } +// return ExchangeResponse(value: rates); +// } catch (e, s) { +// Logging.instance.e("getRates exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> getLimit({ +// required String fromCurrency, +// }) async { +// final uri = _buildUri( +// endpoint: "limits", +// params: {"from_currency": fromCurrency}, +// ); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.from(jsonObject as Map); +// +// final limit = MBLimit( +// currency: fromCurrency, +// min: Decimal.parse(map["min"].toString()), +// max: Decimal.parse(map["max"].toString()), +// ); +// +// return ExchangeResponse(value: limit); +// } catch (e, s) { +// Logging.instance.e("getLimits exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future>> getLimits() async { +// final uri = _buildUri( +// endpoint: +// "rates", // limits are included in the rates call for some reason??? +// ); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.from(jsonObject as Map)["limits"] as Map; +// final List limits = []; +// for (final key in map.keys) { +// final limit = MBLimit( +// currency: key as String, +// min: Decimal.parse(map[key]["min"].toString()), +// max: Decimal.parse(map[key]["max"].toString()), +// ); +// limits.add(limit); +// } +// +// return ExchangeResponse(value: limits); +// } catch (e, s) { +// Logging.instance.e("getLimits exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// /// If [reversed] then the amount is the expected receive_amount, otherwise +// /// the amount is assumed to be the from_amount. +// Future> calculateOrder({ +// required String amount, +// required bool reversed, +// required String fromCurrency, +// required String receiveCurrency, +// }) async { +// final params = { +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// }; +// +// if (reversed) { +// params["receive_amount"] = amount; +// } else { +// params["from_amount"] = amount; +// } +// +// final uri = _buildUri(endpoint: "calculate", params: params); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// final map = Map.from(jsonObject as Map); +// +// if (map["error"] != null) { +// final errorMessage = map["extra"] as String?; +// if (errorMessage != null && +// errorMessage.startsWith("Bad") && +// errorMessage.endsWith("currency symbol")) { +// return ExchangeResponse( +// exception: PairUnavailableException( +// errorMessage, +// ExchangeExceptionType.generic, +// ), +// ); +// } else { +// return ExchangeResponse( +// exception: ExchangeException( +// errorMessage ?? "Error: ${map["error"]}", +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// final result = MBOrderCalculation( +// fromCurrency: map["from_currency"] as String, +// fromAmount: Decimal.parse(map["from_amount"].toString()), +// receiveCurrency: map["receive_currency"] as String, +// receiveAmount: Decimal.parse(map["receive_amount"].toString()), +// ); +// +// return ExchangeResponse(value: result); +// } catch (e, s) { +// Logging.instance.e( +// "calculateOrder $fromCurrency-$receiveCurrency exception: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> createOrder({ +// required String fromAmount, +// required String fromCurrency, +// required String receiveCurrency, +// required String receiveAddress, +// }) async { +// final params = { +// "from_amount": fromAmount, +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// "receive_address": receiveAddress, +// "referral_code": kMajesticBankRefCode, +// }; +// +// final uri = _buildUri(endpoint: "exchange", params: params); +// +// try { +// final now = DateTime.now(); +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// final order = MBOrder( +// orderId: json["trx"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// orderType: MBOrderType.floating, +// expiration: json["expiration"] as int, +// createdAt: now, +// ); +// +// return ExchangeResponse(value: order); +// } catch (e, s) { +// Logging.instance.e("createOrder exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// /// Fixed rate for 10 minutes, useful for payments. +// /// If [reversed] then the amount is the expected receive_amount, otherwise +// /// the amount is assumed to be the from_amount. +// Future> createFixedRateOrder({ +// required String amount, +// required String fromCurrency, +// required String receiveCurrency, +// required String receiveAddress, +// required bool reversed, +// }) async { +// final params = { +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// "receive_address": receiveAddress, +// "referral_code": kMajesticBankRefCode, +// }; +// +// if (reversed) { +// params["receive_amount"] = amount; +// } else { +// params["from_amount"] = amount; +// } +// +// final uri = _buildUri(endpoint: "pay", params: params); +// +// try { +// final now = DateTime.now(); +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// final order = MBOrder( +// orderId: json["trx"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// orderType: MBOrderType.fixed, +// expiration: json["expiration"] as int, +// createdAt: now, +// ); +// +// return ExchangeResponse(value: order); +// } catch (e, s) { +// Logging.instance.e( +// "createFixedRateOrder exception: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> trackOrder({ +// required String orderId, +// }) async { +// final uri = _buildUri(endpoint: "track", params: {"trx": orderId}); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// if (json.length == 2) { +// return ExchangeResponse( +// exception: MBException( +// json["status"] as String, +// ExchangeExceptionType.orderNotFound, +// ), +// ); +// } +// +// final status = MBOrderStatus( +// orderId: json["trx"] as String, +// status: json["status"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// received: Decimal.parse(json["received"].toString()), +// confirmed: Decimal.parse(json["confirmed"].toString()), +// ); +// +// return ExchangeResponse(value: status); +// } catch (e, s) { +// Logging.instance.e( +// "trackOrder exception when trying to parse $json: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// } diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart index b1f8be150..aacceb587 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart @@ -1,346 +1,346 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:decimal/decimal.dart'; -import 'package:uuid/uuid.dart'; - -import '../../../app_config.dart'; -import '../../../exceptions/exchange/exchange_exception.dart'; -import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; -import '../../../models/exchange/majestic_bank/mb_order.dart'; -import '../../../models/exchange/response_objects/estimate.dart'; -import '../../../models/exchange/response_objects/range.dart'; -import '../../../models/exchange/response_objects/trade.dart'; -import '../../../models/isar/exchange_cache/currency.dart'; -import '../../../models/isar/exchange_cache/pair.dart'; -import '../exchange.dart'; -import '../exchange_response.dart'; -import 'majestic_bank_api.dart'; - -class MajesticBankExchange extends Exchange { - MajesticBankExchange._(); - - static MajesticBankExchange? _instance; - static MajesticBankExchange get instance => - _instance ??= MajesticBankExchange._(); - - static const exchangeName = "Majestic Bank"; - - static const kMajesticBankCurrencyNames = { - "BCH": "Bitcoin Cash", - "BTC": "Bitcoin", - "DOGE": "Dogecoin", - "EPIC": "Epic Cash", - "FIRO": "Firo", - "LTC": "Litecoin", - "NMC": "Namecoin", - "PART": "Particl", - "WOW": "Wownero", - "XMR": "Monero", - }; - - @override - bool get supportsRefundAddress => false; - - @override - Future> createTrade({ - required String from, - required String to, - required String? fromNetwork, - required String? toNetwork, - required bool fixedRate, - required Decimal amount, - required String addressTo, - String? extraId, - required String addressRefund, - required String refundExtraId, - Estimate? estimate, - required bool reversed, - }) async { - ExchangeResponse? response; - - if (fixedRate) { - response = await MajesticBankAPI.instance.createFixedRateOrder( - amount: amount.toString(), - fromCurrency: from, - receiveCurrency: to, - receiveAddress: addressTo, - reversed: reversed, - ); - } else { - if (reversed) { - return ExchangeResponse( - exception: MBException( - "Reversed trade not available", - ExchangeExceptionType.generic, - ), - ); - } - response = await MajesticBankAPI.instance.createOrder( - fromAmount: amount.toString(), - fromCurrency: from, - receiveCurrency: to, - receiveAddress: addressTo, - ); - } - - if (response.value != null) { - final order = response.value!; - final trade = Trade( - uuid: const Uuid().v1(), - tradeId: order.orderId, - rateType: fixedRate ? "fixed" : "floating", - direction: reversed ? "reversed" : "direct", - timestamp: order.createdAt, - updatedAt: order.createdAt, - payInCurrency: order.fromCurrency, - payInAmount: order.fromAmount.toString(), - payInAddress: order.address, - payInNetwork: "", - payInExtraId: "", - payInTxid: "", - payOutCurrency: order.receiveCurrency, - payOutAmount: order.receiveAmount.toString(), - payOutAddress: addressTo, - payOutNetwork: "", - payOutExtraId: "", - payOutTxid: "", - refundAddress: addressRefund, - refundExtraId: refundExtraId, - status: "Waiting", - exchangeName: exchangeName, - ); - - return ExchangeResponse(value: trade); - } else { - return ExchangeResponse(exception: response.exception!); - } - } - - @override - Future>> getAllCurrencies( - bool fixedRate, - ) async { - final response = await MajesticBankAPI.instance.getLimits(); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final List currencies = []; - final limits = response.value!; - - for (final limit in limits) { - final currency = Currency( - exchangeName: MajesticBankExchange.exchangeName, - ticker: limit.currency, - name: - kMajesticBankCurrencyNames[limit.currency] ?? - limit.currency, // todo: add more names if MB adds more - network: "", - image: "", - isFiat: false, - rateType: SupportedRateType.both, - isAvailable: true, - isStackCoin: AppConfig.isStackCoin(limit.currency), - tokenContract: null, - ); - currencies.add(currency); - } - - return ExchangeResponse(value: currencies); - } - - // @override - // Future>> getPairedCurrencies( - // String forCurrency, - // bool fixedRate, - // ) { - // // TODO: change this if the api changes to allow getting by paired currency - // return getAllCurrencies(fixedRate); - // } - // - // @override - // Future>> getAllPairs(bool fixedRate) async { - // final response = await MajesticBankAPI.instance.getRates(); - // if (response.value == null) { - // return ExchangeResponse(exception: response.exception); - // } - // - // final List pairs = []; - // final rates = response.value!; - // - // for (final rate in rates) { - // final pair = Pair( - // exchangeName: MajesticBankExchange.exchangeName, - // from: rate.fromCurrency, - // to: rate.toCurrency, - // rateType: SupportedRateType.both, - // ); - // pairs.add(pair); - // } - // - // return ExchangeResponse(value: pairs); - // } - - @override - Future>> getEstimates( - String from, - String? fromNetwork, - String to, - String? toNetwork, - Decimal amount, - bool fixedRate, - bool reversed, - ) async { - final response = await MajesticBankAPI.instance.calculateOrder( - amount: amount.toString(), - reversed: reversed, - fromCurrency: from, - receiveCurrency: to, - ); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final calc = response.value!; - final estimate = Estimate( - estimatedAmount: reversed ? calc.fromAmount : calc.receiveAmount, - fixedRate: fixedRate, - reversed: reversed, - exchangeProvider: MajesticBankExchange.exchangeName, - ); - return ExchangeResponse(value: [estimate]); - } - - // @override - // Future>> getPairsFor( - // String currency, - // bool fixedRate, - // ) async { - // final response = await getAllPairs(fixedRate); - // if (response.value == null) { - // return ExchangeResponse(exception: response.exception); - // } - // - // final pairs = response.value!.where( - // (e) => - // e.from.toUpperCase() == currency.toUpperCase() || - // e.to.toUpperCase() == currency.toUpperCase(), - // ); - // - // return ExchangeResponse(value: pairs.toList()); - // } - - @override - Future> getRange( - String from, - String? fromNetwork, - String to, - String? toNetwork, - bool fixedRate, - ) async { - final response = await MajesticBankAPI.instance.getLimit( - fromCurrency: from, - ); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final limit = response.value!; - final range = Range(min: limit.min, max: limit.max); - - return ExchangeResponse(value: range); - } - - @override - Future> getTrade(String tradeId) async { - // TODO: implement getTrade - throw UnimplementedError(); - } - - @override - Future>> getTrades() async { - // TODO: implement getTrades - throw UnimplementedError(); - } - - @override - String get name => exchangeName; - - @override - Future> updateTrade(Trade trade) async { - final response = await MajesticBankAPI.instance.trackOrder( - orderId: trade.tradeId, - ); - - if (response.value != null) { - final status = response.value!; - final updatedTrade = Trade( - uuid: trade.uuid, - tradeId: status.orderId, - rateType: trade.rateType, - direction: trade.direction, - timestamp: trade.timestamp, - updatedAt: DateTime.now(), - payInCurrency: status.fromCurrency, - payInAmount: status.fromAmount.toString(), - payInAddress: status.address, - payInNetwork: trade.payInNetwork, - payInExtraId: trade.payInExtraId, - payInTxid: trade.payInTxid, - payOutCurrency: status.receiveCurrency, - payOutAmount: status.receiveAmount.toString(), - payOutAddress: trade.payOutAddress, - payOutNetwork: trade.payOutNetwork, - payOutExtraId: trade.payOutExtraId, - payOutTxid: trade.payOutTxid, - refundAddress: trade.refundAddress, - refundExtraId: trade.refundExtraId, - status: status.status, - exchangeName: exchangeName, - ); - - return ExchangeResponse(value: updatedTrade); - } else { - if (response.exception?.type == ExchangeExceptionType.orderNotFound) { - final updatedTrade = Trade( - uuid: trade.uuid, - tradeId: trade.tradeId, - rateType: trade.rateType, - direction: trade.direction, - timestamp: trade.timestamp, - updatedAt: DateTime.now(), - payInCurrency: trade.payInCurrency, - payInAmount: trade.payInAmount, - payInAddress: trade.payInAddress, - payInNetwork: trade.payInNetwork, - payInExtraId: trade.payInExtraId, - payInTxid: trade.payInTxid, - payOutCurrency: trade.payOutCurrency, - payOutAmount: trade.payOutAmount, - payOutAddress: trade.payOutAddress, - payOutNetwork: trade.payOutNetwork, - payOutExtraId: trade.payOutExtraId, - payOutTxid: trade.payOutTxid, - refundAddress: trade.refundAddress, - refundExtraId: trade.refundExtraId, - status: "Completed", - exchangeName: exchangeName, - ); - return ExchangeResponse(value: updatedTrade); - } - return ExchangeResponse(exception: response.exception); - } - } - - // Majestic Bank supports tor. - @override - bool get supportsTor => true; -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'package:decimal/decimal.dart'; +// import 'package:uuid/uuid.dart'; +// +// import '../../../app_config.dart'; +// import '../../../exceptions/exchange/exchange_exception.dart'; +// import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; +// import '../../../models/exchange/majestic_bank/mb_order.dart'; +// import '../../../models/exchange/response_objects/estimate.dart'; +// import '../../../models/exchange/response_objects/range.dart'; +// import '../../../models/exchange/response_objects/trade.dart'; +// import '../../../models/isar/exchange_cache/currency.dart'; +// import '../../../models/isar/exchange_cache/pair.dart'; +// import '../exchange.dart'; +// import '../exchange_response.dart'; +// import 'majestic_bank_api.dart'; +// +// class MajesticBankExchange /*extends Exchange*/ { +// MajesticBankExchange._(); +// +// static MajesticBankExchange? _instance; +// static MajesticBankExchange get instance => +// _instance ??= MajesticBankExchange._(); +// +// static const exchangeName = "Majestic Bank"; +// +// static const kMajesticBankCurrencyNames = { +// "BCH": "Bitcoin Cash", +// "BTC": "Bitcoin", +// "DOGE": "Dogecoin", +// "EPIC": "Epic Cash", +// "FIRO": "Firo", +// "LTC": "Litecoin", +// "NMC": "Namecoin", +// "PART": "Particl", +// "WOW": "Wownero", +// "XMR": "Monero", +// }; +// +// @override +// bool get supportsRefundAddress => false; +// +// @override +// Future> createTrade({ +// required String from, +// required String to, +// required String? fromNetwork, +// required String? toNetwork, +// required bool fixedRate, +// required Decimal amount, +// required String addressTo, +// String? extraId, +// required String addressRefund, +// required String refundExtraId, +// Estimate? estimate, +// required bool reversed, +// }) async { +// ExchangeResponse? response; +// +// if (fixedRate) { +// response = await MajesticBankAPI.instance.createFixedRateOrder( +// amount: amount.toString(), +// fromCurrency: from, +// receiveCurrency: to, +// receiveAddress: addressTo, +// reversed: reversed, +// ); +// } else { +// if (reversed) { +// return ExchangeResponse( +// exception: MBException( +// "Reversed trade not available", +// ExchangeExceptionType.generic, +// ), +// ); +// } +// response = await MajesticBankAPI.instance.createOrder( +// fromAmount: amount.toString(), +// fromCurrency: from, +// receiveCurrency: to, +// receiveAddress: addressTo, +// ); +// } +// +// if (response.value != null) { +// final order = response.value!; +// final trade = Trade( +// uuid: const Uuid().v1(), +// tradeId: order.orderId, +// rateType: fixedRate ? "fixed" : "floating", +// direction: reversed ? "reversed" : "direct", +// timestamp: order.createdAt, +// updatedAt: order.createdAt, +// payInCurrency: order.fromCurrency, +// payInAmount: order.fromAmount.toString(), +// payInAddress: order.address, +// payInNetwork: "", +// payInExtraId: "", +// payInTxid: "", +// payOutCurrency: order.receiveCurrency, +// payOutAmount: order.receiveAmount.toString(), +// payOutAddress: addressTo, +// payOutNetwork: "", +// payOutExtraId: "", +// payOutTxid: "", +// refundAddress: addressRefund, +// refundExtraId: refundExtraId, +// status: "Waiting", +// exchangeName: exchangeName, +// ); +// +// return ExchangeResponse(value: trade); +// } else { +// return ExchangeResponse(exception: response.exception!); +// } +// } +// +// @override +// Future>> getAllCurrencies( +// bool fixedRate, +// ) async { +// final response = await MajesticBankAPI.instance.getLimits(); +// if (response.value == null) { +// return ExchangeResponse(exception: response.exception); +// } +// +// final List currencies = []; +// final limits = response.value!; +// +// for (final limit in limits) { +// final currency = Currency( +// exchangeName: MajesticBankExchange.exchangeName, +// ticker: limit.currency, +// name: +// kMajesticBankCurrencyNames[limit.currency] ?? +// limit.currency, // todo: add more names if MB adds more +// network: "", +// image: "", +// isFiat: false, +// rateType: SupportedRateType.both, +// isAvailable: true, +// isStackCoin: AppConfig.isStackCoin(limit.currency), +// tokenContract: null, +// ); +// currencies.add(currency); +// } +// +// return ExchangeResponse(value: currencies); +// } +// +// // @override +// // Future>> getPairedCurrencies( +// // String forCurrency, +// // bool fixedRate, +// // ) { +// // // TODO: change this if the api changes to allow getting by paired currency +// // return getAllCurrencies(fixedRate); +// // } +// // +// // @override +// // Future>> getAllPairs(bool fixedRate) async { +// // final response = await MajesticBankAPI.instance.getRates(); +// // if (response.value == null) { +// // return ExchangeResponse(exception: response.exception); +// // } +// // +// // final List pairs = []; +// // final rates = response.value!; +// // +// // for (final rate in rates) { +// // final pair = Pair( +// // exchangeName: MajesticBankExchange.exchangeName, +// // from: rate.fromCurrency, +// // to: rate.toCurrency, +// // rateType: SupportedRateType.both, +// // ); +// // pairs.add(pair); +// // } +// // +// // return ExchangeResponse(value: pairs); +// // } +// +// @override +// Future>> getEstimates( +// String from, +// String? fromNetwork, +// String to, +// String? toNetwork, +// Decimal amount, +// bool fixedRate, +// bool reversed, +// ) async { +// final response = await MajesticBankAPI.instance.calculateOrder( +// amount: amount.toString(), +// reversed: reversed, +// fromCurrency: from, +// receiveCurrency: to, +// ); +// if (response.value == null) { +// return ExchangeResponse(exception: response.exception); +// } +// +// final calc = response.value!; +// final estimate = Estimate( +// estimatedAmount: reversed ? calc.fromAmount : calc.receiveAmount, +// fixedRate: fixedRate, +// reversed: reversed, +// exchangeProvider: MajesticBankExchange.exchangeName, +// ); +// return ExchangeResponse(value: [estimate]); +// } +// +// // @override +// // Future>> getPairsFor( +// // String currency, +// // bool fixedRate, +// // ) async { +// // final response = await getAllPairs(fixedRate); +// // if (response.value == null) { +// // return ExchangeResponse(exception: response.exception); +// // } +// // +// // final pairs = response.value!.where( +// // (e) => +// // e.from.toUpperCase() == currency.toUpperCase() || +// // e.to.toUpperCase() == currency.toUpperCase(), +// // ); +// // +// // return ExchangeResponse(value: pairs.toList()); +// // } +// +// @override +// Future> getRange( +// String from, +// String? fromNetwork, +// String to, +// String? toNetwork, +// bool fixedRate, +// ) async { +// final response = await MajesticBankAPI.instance.getLimit( +// fromCurrency: from, +// ); +// if (response.value == null) { +// return ExchangeResponse(exception: response.exception); +// } +// +// final limit = response.value!; +// final range = Range(min: limit.min, max: limit.max); +// +// return ExchangeResponse(value: range); +// } +// +// @override +// Future> getTrade(String tradeId) async { +// // TODO: implement getTrade +// throw UnimplementedError(); +// } +// +// @override +// Future>> getTrades() async { +// // TODO: implement getTrades +// throw UnimplementedError(); +// } +// +// @override +// String get name => exchangeName; +// +// @override +// Future> updateTrade(Trade trade) async { +// final response = await MajesticBankAPI.instance.trackOrder( +// orderId: trade.tradeId, +// ); +// +// if (response.value != null) { +// final status = response.value!; +// final updatedTrade = Trade( +// uuid: trade.uuid, +// tradeId: status.orderId, +// rateType: trade.rateType, +// direction: trade.direction, +// timestamp: trade.timestamp, +// updatedAt: DateTime.now(), +// payInCurrency: status.fromCurrency, +// payInAmount: status.fromAmount.toString(), +// payInAddress: status.address, +// payInNetwork: trade.payInNetwork, +// payInExtraId: trade.payInExtraId, +// payInTxid: trade.payInTxid, +// payOutCurrency: status.receiveCurrency, +// payOutAmount: status.receiveAmount.toString(), +// payOutAddress: trade.payOutAddress, +// payOutNetwork: trade.payOutNetwork, +// payOutExtraId: trade.payOutExtraId, +// payOutTxid: trade.payOutTxid, +// refundAddress: trade.refundAddress, +// refundExtraId: trade.refundExtraId, +// status: status.status, +// exchangeName: exchangeName, +// ); +// +// return ExchangeResponse(value: updatedTrade); +// } else { +// if (response.exception?.type == ExchangeExceptionType.orderNotFound) { +// final updatedTrade = Trade( +// uuid: trade.uuid, +// tradeId: trade.tradeId, +// rateType: trade.rateType, +// direction: trade.direction, +// timestamp: trade.timestamp, +// updatedAt: DateTime.now(), +// payInCurrency: trade.payInCurrency, +// payInAmount: trade.payInAmount, +// payInAddress: trade.payInAddress, +// payInNetwork: trade.payInNetwork, +// payInExtraId: trade.payInExtraId, +// payInTxid: trade.payInTxid, +// payOutCurrency: trade.payOutCurrency, +// payOutAmount: trade.payOutAmount, +// payOutAddress: trade.payOutAddress, +// payOutNetwork: trade.payOutNetwork, +// payOutExtraId: trade.payOutExtraId, +// payOutTxid: trade.payOutTxid, +// refundAddress: trade.refundAddress, +// refundExtraId: trade.refundExtraId, +// status: "Completed", +// exchangeName: exchangeName, +// ); +// return ExchangeResponse(value: updatedTrade); +// } +// return ExchangeResponse(exception: response.exception); +// } +// } +// +// // Majestic Bank supports tor. +// @override +// bool get supportsTor => true; +// } diff --git a/lib/services/notifications_service.dart b/lib/services/notifications_service.dart index 93e09aceb..4eca542e0 100644 --- a/lib/services/notifications_service.dart +++ b/lib/services/notifications_service.dart @@ -50,8 +50,9 @@ class NotificationsService extends ChangeNotifier { // watched transactions List get _watchedTransactionNotifications { - return DB.instance - .values(boxName: DB.boxNameWatchedTransactions); + return DB.instance.values( + boxName: DB.boxNameWatchedTransactions, + ); } Future _addWatchedTxNotification(NotificationModel notification) async { @@ -73,8 +74,9 @@ class NotificationsService extends ChangeNotifier { // watched trades List get _watchedChangeNowTradeNotifications { - return DB.instance - .values(boxName: DB.boxNameWatchedTrades); + return DB.instance.values( + boxName: DB.boxNameWatchedTrades, + ); } Future _addWatchedTradeNotification( @@ -127,8 +129,9 @@ class NotificationsService extends ChangeNotifier { void _checkTransactions() async { for (final notification in _watchedTransactionNotifications) { try { - final CryptoCurrency coin = - AppConfig.getCryptoCurrencyByPrettyName(notification.coinName); + final CryptoCurrency coin = AppConfig.getCryptoCurrencyByPrettyName( + notification.coinName, + ); final txid = notification.txid!; final wallet = Wallets.sharedInstance.getWallet(notification.walletId); @@ -156,20 +159,21 @@ class NotificationsService extends ChangeNotifier { torEnabled: node.torEnabled, clearnetEnabled: node.clearnetEnabled, ); - final failovers = nodeService - .failoverNodesFor(currency: coin) - .map( - (e) => ElectrumXNode( - address: e.host, - port: e.port, - name: e.name, - id: e.id, - useSSL: e.useSSL, - torEnabled: node.torEnabled, - clearnetEnabled: node.clearnetEnabled, - ), - ) - .toList(); + final failovers = + nodeService + .failoverNodesFor(currency: coin) + .map( + (e) => ElectrumXNode( + address: e.host, + port: e.port, + name: e.name, + id: e.id, + useSSL: e.useSSL, + torEnabled: node.torEnabled, + clearnetEnabled: node.clearnetEnabled, + ), + ) + .toList(); final client = ElectrumXClient.from( node: eNode, @@ -193,13 +197,16 @@ class NotificationsService extends ChangeNotifier { // grab confirms string to compare final String newConfirms = "($confirmations/${wallet.cryptoCurrency.minConfirms})"; - final String oldConfirms = notification.title - .substring(notification.title.lastIndexOf("(")); + final String oldConfirms = notification.title.substring( + notification.title.lastIndexOf("("), + ); // only update if they don't match if (oldConfirms != newConfirms) { - final String newTitle = - notification.title.replaceFirst(oldConfirms, newConfirms); + final String newTitle = notification.title.replaceFirst( + oldConfirms, + newConfirms, + ); final updatedNotification = notification.copyWith( title: newTitle, @@ -230,8 +237,10 @@ class NotificationsService extends ChangeNotifier { for (final notification in _watchedChangeNowTradeNotifications) { final id = notification.changeNowId!; - final trades = - tradesService.trades.where((element) => element.tradeId == id); + final trades = tradesService.trades.where( + (element) => + element.tradeId == id && element.exchangeName != "Majestic Bank", + ); if (trades.isEmpty) { return; @@ -362,8 +371,11 @@ class NotificationsService extends ChangeNotifier { } Future markAsRead(int id, bool shouldNotifyListeners) async { - final model = DB.instance - .get(boxName: DB.boxNameNotifications, key: id)!; + final model = + DB.instance.get( + boxName: DB.boxNameNotifications, + key: id, + )!; await DB.instance.put( boxName: DB.boxNameNotifications, key: model.id, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index c12f215c0..679187c5c 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -11,7 +11,6 @@ import 'package:flutter/material.dart'; import '../services/exchange/change_now/change_now_exchange.dart'; -import '../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../services/exchange/nanswap/nanswap_exchange.dart'; import '../services/exchange/simpleswap/simpleswap_exchange.dart'; import '../services/exchange/trocador/trocador_exchange.dart'; @@ -44,8 +43,8 @@ class _EXCHANGE { String get changeNow => "${_path}change_now_logo_1.svg"; String get simpleSwap => "${_path}simpleswap-icon.svg"; - String get majesticBankBlue => "${_path}mb_blue.svg"; - String get majesticBankGreen => "${_path}mb_green.svg"; + // String get majesticBankBlue => "${_path}mb_blue.svg"; + // String get majesticBankGreen => "${_path}mb_green.svg"; String get trocador => "${_path}trocador.svg"; String get nanswap => "${_path}nanswap.svg"; @@ -55,8 +54,8 @@ class _EXCHANGE { return simpleSwap; case ChangeNowExchange.exchangeName: return changeNow; - case MajesticBankExchange.exchangeName: - return majesticBankBlue; + // case MajesticBankExchange.exchangeName: + // return majesticBankBlue; case TrocadorExchange.exchangeName: return trocador; case NanswapExchange.exchangeName: From 33eea8ece46b9ad59e05d6ee7d35afed38fb18a4 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 11:01:35 -0600 Subject: [PATCH 180/206] fix mwebd proxy address formatting --- lib/services/mwebd_service.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index f8b3a6a32..89f2bee37 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -83,7 +83,7 @@ final class MwebdService { final proxy = proxyInfo == null ? "" - : "${proxyInfo.host.address}:${proxyInfo.port}"; + : "socks5://${proxyInfo.host.address}:${proxyInfo.port}"; final nets = _map.keys; for (final net in nets) { final old = _map.remove(net)!; @@ -158,7 +158,7 @@ final class MwebdService { final String proxy; if (Prefs.instance.useTor) { final proxyInfo = TorService.sharedInstance.getProxyInfo(); - proxy = "${proxyInfo.host.address}:${proxyInfo.port}"; + proxy = "socks5://${proxyInfo.host.address}:${proxyInfo.port}"; } else { proxy = ""; } From 949df69b86eede20cfd95ae8827aed68b2e96a8a Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 12:42:46 -0600 Subject: [PATCH 181/206] temp hack for legacy currencies in db --- lib/models/isar/exchange_cache/currency.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index f719f5a3c..67a7f4098 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -71,6 +71,11 @@ class Currency { @ignore String? _fuzzyCache; String getFuzzyNet() { + // hack for legacy support + if (exchangeName == "Majestic Bank") { + return ticker.toLowerCase(); + } + return _fuzzyCache ??= switch (Exchange.fromName( exchangeName, ).runtimeType) { From 4f5797f4c9c44f6466ce6b4c2cf32ce7f83a6f92 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 12:43:53 -0600 Subject: [PATCH 182/206] tezos bandaid fixes --- lib/wallets/wallet/impl/tezos_wallet.dart | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index 2843d4a1a..54302a027 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:isar/isar.dart'; @@ -128,6 +129,7 @@ class TezosWallet extends Bip39Wallet { // customFee: customFee?.raw.toInt(), // customGasLimit: customGasLimit, // reveal: false, + customGasLimit: 10600, ); // if (reveal) { @@ -286,8 +288,38 @@ class TezosWallet extends Bip39Wallet { @override Future confirmSend({required TxData txData}) async { _hackedCheckTorNodePrefs(); + + final completer = Completer(); + final sub = mainDB.isar.transactions + .where() + .walletIdEqualTo(walletId) + .watch(fireImmediately: true) + .listen((event) { + if (!completer.isCompleted && + event + .where((e) => e.txid == txData.tezosOperationsList!.result.id) + .isNotEmpty) { + completer.complete(); + } + }); + await txData.tezosOperationsList!.inject(); - await txData.tezosOperationsList!.monitor(); + + final completerFuture = completer.future.timeout( + const Duration(minutes: 2), + onTimeout: () { + throw Exception("Tezos confirm send timeout"); + }, + ); + + while (!completer.isCompleted) { + await updateTransactions(); + await Future.delayed(const Duration(seconds: 3)); + } + + await completerFuture; + + unawaited(sub.cancel()); return txData.copyWith(txid: txData.tezosOperationsList!.result.id); } From f3898cd505f4d26beef7da9e6db75030b83dc420 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 24 Jul 2025 08:17:19 -0600 Subject: [PATCH 183/206] ltc pub spend with mweb disabled insuff. bal fix --- lib/pages/send_view/send_view.dart | 1 + .../my_stack_view/wallet_view/sub_widgets/desktop_send.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 76aebaf33..d610c0aa1 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -814,6 +814,7 @@ class _SendViewState extends ConsumerState { break; } } else if (wallet is MwebInterface && + ref.read(pWalletInfo(walletId)).isMwebEnabled && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { txDataFuture = wallet.prepareSendMweb( txData: TxData( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index dd3a70f9d..b4e259f6c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -409,6 +409,7 @@ class _DesktopSendState extends ConsumerState { break; } } else if (wallet is MwebInterface && + ref.read(pWalletInfo(walletId)).isMwebEnabled && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { txDataFuture = wallet.prepareSendMweb( txData: TxData( From 927e4dc5d74219a5b5fe2d0e368265d3bbada9f3 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Jul 2025 10:49:51 -0600 Subject: [PATCH 184/206] reset custom fee slider value --- lib/pages/send_view/send_view.dart | 5 ++++- .../my_stack_view/wallet_view/sub_widgets/desktop_send.dart | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index d610c0aa1..cfaa41f64 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1087,7 +1087,10 @@ class _SendViewState extends ConsumerState { ref.refresh(pIsExchangeAddress); }); isCustomFee.addListener(() { - if (!isCustomFee.value) ethFee = null; + if (!isCustomFee.value) { + customFeeRate = 1; + ethFee = null; + } }); hasFees = coin is! Epiccash && coin is! NanoCurrency && coin is! Tezos; _currentFee = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index b4e259f6c..b4c183c43 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -1666,6 +1666,7 @@ class _DesktopSendState extends ConsumerState { onCustomFeeSliderChanged: (value) => customFeeRate = value, onCustomFeeOptionChanged: (value) { isCustomFee = value; + customFeeRate = 1; ethFee = null; }, onCustomEip1559FeeOptionChanged: (value) => ethFee = value, From 4fff2705c11628889af770876c9bfd7d8bfa0ae4 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Jul 2025 11:11:51 -0600 Subject: [PATCH 185/206] macos mwebd linking issue fix that affected some mac systems --- pubspec.lock | 4 ++-- scripts/app_config/templates/pubspec.template | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 39d500ae1..ab6a39710 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -985,10 +985,10 @@ packages: dependency: "direct main" description: name: flutter_mwebd - sha256: f6daecf6a4e10dde0a2fbfe026d801cd41864c6464923d9a26a92c613c893173 + sha256: "73b35b6eaccb6e1be7eb37e04bcc94f091244fa31b8aedc17e4119c580a7a747" url: "https://pub.dev" source: hosted - version: "0.0.1-pre.6" + version: "0.0.1-pre.7" flutter_native_splash: dependency: "direct main" description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index ae6032744..ef0f72984 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -224,7 +224,7 @@ dependencies: path: ^1.9.1 cs_salvium: ^1.2.1 cs_salvium_flutter_libs: ^1.0.4 - flutter_mwebd: ^0.0.1-pre.6 + flutter_mwebd: ^0.0.1-pre.7 mweb_client: ^0.2.0 fixnum: ^1.1.1 From 08ed0fc250c379354f51702a9d294f5616e536f6 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Jul 2025 11:53:34 -0600 Subject: [PATCH 186/206] fix list type cast --- lib/wallets/wallet/impl/particl_wallet.dart | 32 ++++++++++--------- .../bcash_interface.dart | 29 ++++++++--------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/lib/wallets/wallet/impl/particl_wallet.dart b/lib/wallets/wallet/impl/particl_wallet.dart index 08e27cc18..4725110af 100644 --- a/lib/wallets/wallet/impl/particl_wallet.dart +++ b/lib/wallets/wallet/impl/particl_wallet.dart @@ -352,8 +352,10 @@ class ParticlWallet @override Future buildTransaction({ required TxData txData, - required covariant List inputsWithKeys, + required List inputsWithKeys, }) async { + final insAndKeys = inputsWithKeys.cast(); + Logging.instance.d("Starting Particl buildTransaction ----------"); // TODO: use coinlib (For this we need coinlib to support particl) @@ -371,8 +373,8 @@ class ParticlWallet ); final List<({Uint8List? output, Uint8List? redeem})> extraData = []; - for (int i = 0; i < inputsWithKeys.length; i++) { - final sd = inputsWithKeys[i]; + for (int i = 0; i < insAndKeys.length; i++) { + final sd = insAndKeys[i]; final pubKey = sd.key!.publicKey.data; final bitcoindart.PaymentData? data; @@ -448,11 +450,11 @@ class ParticlWallet final List tempOutputs = []; // Add inputs. - for (var i = 0; i < inputsWithKeys.length; i++) { - final txid = inputsWithKeys[i].utxo.txid; + for (var i = 0; i < insAndKeys.length; i++) { + final txid = insAndKeys[i].utxo.txid; txb.addInput( txid, - inputsWithKeys[i].utxo.vout, + insAndKeys[i].utxo.vout, null, extraData[i].output!, cryptoCurrency.networkParams.bech32Hrp, @@ -464,14 +466,14 @@ class ParticlWallet scriptSigAsm: null, sequence: 0xffffffff - 1, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: inputsWithKeys[i].utxo.txid, - vout: inputsWithKeys[i].utxo.vout, + txid: insAndKeys[i].utxo.txid, + vout: insAndKeys[i].utxo.vout, ), addresses: - inputsWithKeys[i].utxo.address == null + insAndKeys[i].utxo.address == null ? [] - : [inputsWithKeys[i].utxo.address!], - valueStringSats: inputsWithKeys[i].utxo.value.toString(), + : [insAndKeys[i].utxo.address!], + valueStringSats: insAndKeys[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -508,15 +510,15 @@ class ParticlWallet // Sign. try { - for (var i = 0; i < inputsWithKeys.length; i++) { + for (var i = 0; i < insAndKeys.length; i++) { txb.sign( vin: i, keyPair: bitcoindart.ECPair.fromPrivateKey( - inputsWithKeys[i].key!.privateKey!.data, + insAndKeys[i].key!.privateKey!.data, network: convertedNetwork, - compressed: inputsWithKeys[i].key!.privateKey!.compressed, + compressed: insAndKeys[i].key!.privateKey!.compressed, ), - witnessValue: inputsWithKeys[i].utxo.value, + witnessValue: insAndKeys[i].utxo.value, redeemScript: extraData[i].redeem, overridePrefix: cryptoCurrency.networkParams.bech32Hrp, ); diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart index 410f11d2e..0f428ec89 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart @@ -18,8 +18,10 @@ mixin BCashInterface @override Future buildTransaction({ required TxData txData, - required covariant List inputsWithKeys, + required List inputsWithKeys, }) async { + final insAndKeys = inputsWithKeys.cast(); + Logging.instance.d("Starting buildTransaction ----------"); // TODO: use coinlib @@ -35,11 +37,8 @@ mixin BCashInterface final List tempOutputs = []; // Add transaction inputs - for (int i = 0; i < inputsWithKeys.length; i++) { - builder.addInput( - inputsWithKeys[i].utxo.txid, - inputsWithKeys[i].utxo.vout, - ); + for (int i = 0; i < insAndKeys.length; i++) { + builder.addInput(insAndKeys[i].utxo.txid, insAndKeys[i].utxo.vout); tempInputs.add( InputV2.isarCantDoRequiredInDefaultConstructor( @@ -47,14 +46,14 @@ mixin BCashInterface scriptSigAsm: null, sequence: 0xffffffff - 1, outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor( - txid: inputsWithKeys[i].utxo.txid, - vout: inputsWithKeys[i].utxo.vout, + txid: insAndKeys[i].utxo.txid, + vout: insAndKeys[i].utxo.vout, ), addresses: - inputsWithKeys[i].utxo.address == null + insAndKeys[i].utxo.address == null ? [] - : [inputsWithKeys[i].utxo.address!], - valueStringSats: inputsWithKeys[i].utxo.value.toString(), + : [insAndKeys[i].utxo.address!], + valueStringSats: insAndKeys[i].utxo.value.toString(), witness: null, innerRedeemScriptAsm: null, coinbase: null, @@ -92,9 +91,9 @@ mixin BCashInterface try { // Sign the transaction accordingly - for (int i = 0; i < inputsWithKeys.length; i++) { + for (int i = 0; i < insAndKeys.length; i++) { final bitboxEC = bitbox.ECPair.fromPrivateKey( - inputsWithKeys[i].key!.privateKey!.data, + insAndKeys[i].key!.privateKey!.data, network: bitbox_utils.Network( cryptoCurrency.networkParams.privHDPrefix, cryptoCurrency.networkParams.pubHDPrefix, @@ -103,10 +102,10 @@ mixin BCashInterface cryptoCurrency.networkParams.wifPrefix, cryptoCurrency.networkParams.p2pkhPrefix, ), - compressed: inputsWithKeys[i].key!.privateKey!.compressed, + compressed: insAndKeys[i].key!.privateKey!.compressed, ); - builder.sign(i, bitboxEC, inputsWithKeys[i].utxo.value); + builder.sign(i, bitboxEC, insAndKeys[i].utxo.value); } } catch (e, s) { Logging.instance.e( From be380b97d4c855596a2446833840f4085761bad0 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Jul 2025 11:54:40 -0600 Subject: [PATCH 187/206] fix p2sh address detection --- .../electrumx_currency_interface.dart | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart index 9cc01cf64..70929af41 100644 --- a/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart +++ b/lib/wallets/crypto_currency/interfaces/electrumx_currency_interface.dart @@ -1,6 +1,8 @@ import 'package:coinlib_flutter/coinlib_flutter.dart' as cl; +import 'package:flutter/foundation.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; +import '../../../utilities/logger.dart'; import '../intermediate/bip39_hd_currency.dart'; mixin ElectrumXCurrencyInterface on Bip39HDCurrency { @@ -14,15 +16,29 @@ mixin ElectrumXCurrencyInterface on Bip39HDCurrency { try { final clAddress = cl.Address.fromString(address, networkParams); + Logging.instance.t( + "getAddressType($address) type is ${clAddress.runtimeType}", + ); + return switch (clAddress) { cl.P2PKHAddress() => AddressType.p2pkh, - cl.P2WSHAddress() => AddressType.p2sh, + cl.P2SHAddress() => AddressType.p2sh, cl.P2WPKHAddress() => AddressType.p2wpkh, cl.P2TRAddress() => AddressType.p2tr, cl.MwebAddress() => AddressType.mweb, _ => null, }; - } catch (_) { + } catch (e, s) { + if (kDebugMode) { + Logging.instance.e( + "getAddressType($address) failed", + error: e, + stackTrace: s, + ); + } else { + Logging.instance.t("getAddressType($address) failed"); + } + return null; } } From aea8847a4af36a24882dab235ab25f65be2abe6f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 25 Jul 2025 11:55:02 -0600 Subject: [PATCH 188/206] fix address detection for cashaddrs --- lib/wallets/crypto_currency/coins/bitcoincash.dart | 14 ++++++++++++-- lib/wallets/crypto_currency/coins/ecash.dart | 11 +++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/wallets/crypto_currency/coins/bitcoincash.dart b/lib/wallets/crypto_currency/coins/bitcoincash.dart index 6ea2a8c3e..d236b21a4 100644 --- a/lib/wallets/crypto_currency/coins/bitcoincash.dart +++ b/lib/wallets/crypto_currency/coins/bitcoincash.dart @@ -1,9 +1,8 @@ -import 'dart:typed_data'; - import 'package:bech32/bech32.dart'; import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bs58check/bs58check.dart' as bs58check; import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; +import 'package:flutter/foundation.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/node_model.dart'; @@ -231,6 +230,17 @@ class Bitcoincash extends Bip39HDCurrency with ElectrumXCurrencyInterface { // Do not validate "p" (P2SH) addresses. } + @override + AddressType? getAddressType(String address) { + final format = bitbox.Address.detectFormat(address); + + return super.getAddressType( + format == bitbox.Address.formatCashAddr + ? bitbox.Address.toLegacyAddress(address) + : address, + ); + } + @override DerivePathType addressType({required String address}) { Uint8List? decodeBase58; diff --git a/lib/wallets/crypto_currency/coins/ecash.dart b/lib/wallets/crypto_currency/coins/ecash.dart index a41a47394..c7d99b2d5 100644 --- a/lib/wallets/crypto_currency/coins/ecash.dart +++ b/lib/wallets/crypto_currency/coins/ecash.dart @@ -222,6 +222,17 @@ class Ecash extends Bip39HDCurrency with ElectrumXCurrencyInterface { // Do not validate "p" (P2SH) addresses. } + @override + AddressType? getAddressType(String address) { + final format = bitbox.Address.detectFormat(address); + + return super.getAddressType( + format == bitbox.Address.formatCashAddr + ? bitbox.Address.toLegacyAddress(address) + : address, + ); + } + @override DerivePathType addressType({required String address}) { Uint8List? decodeBase58; From e55df92cfc1710ae9b25396598769e01ff2daf2c Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 26 Jul 2025 09:25:51 -0600 Subject: [PATCH 189/206] remove remove reuse address toggle for single address type wallets --- .../sub_widgets/desktop_wallet_features.dart | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 71cd7f196..e5b05270f 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -45,6 +45,7 @@ import '../../../../wallets/wallet/intermediate/lib_salvium_wallet.dart'; import '../../../../wallets/wallet/wallet.dart' show Wallet; import '../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; @@ -481,10 +482,20 @@ class _DesktopWalletFeaturesState extends ConsumerState { final isViewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly; - final isViewOnlyNoAddressGen = - wallet is ViewOnlyOptionInterface && - wallet.isViewOnly && - wallet.viewOnlyType == ViewOnlyWalletType.addressOnly; + final bool canGen; + if (isViewOnly && wallet.viewOnlyType == ViewOnlyWalletType.addressOnly) { + canGen = false; + } else { + final supportsMweb = + wallet is MwebInterface && + !wallet.info.isViewOnly && + wallet.info.isMwebEnabled; + + canGen = + (wallet is MultiAddressInterface || + wallet is SparkInterface || + supportsMweb); + } final showMwebOption = wallet is MwebInterface && !wallet.isViewOnly; @@ -494,8 +505,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { if (wallet is RbfInterface) (WalletFeature.rbf, Assets.svg.key, () => ()), - if (!isViewOnlyNoAddressGen) - (WalletFeature.reuseAddress, Assets.svg.key, () => ()), + if (canGen) (WalletFeature.reuseAddress, Assets.svg.key, () => ()), if (showMwebOption) (WalletFeature.enableMweb, Assets.svg.key, () => ()), ]; From 61904c7432e05852e65d000cb84c737293ea9d4b Mon Sep 17 00:00:00 2001 From: julian Date: Sat, 26 Jul 2025 10:36:49 -0600 Subject: [PATCH 190/206] add public support channels scam warning pop up --- .../global_settings_view/support_view.dart | 203 +++++++++++++++++- 1 file changed, 201 insertions(+), 2 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/support_view.dart b/lib/pages/settings_views/global_settings_view/support_view.dart index fcfc6ee18..fb7f6b512 100644 --- a/lib/pages/settings_views/global_settings_view/support_view.dart +++ b/lib/pages/settings_views/global_settings_view/support_view.dart @@ -21,6 +21,8 @@ import '../../../utilities/util.dart'; import '../../../widgets/background.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/dialogs/s_dialog.dart'; import '../../../widgets/rounded_white_container.dart'; class SupportView extends StatelessWidget { @@ -140,8 +142,26 @@ class AboutItem extends StatelessWidget { Constants.size.circularBorderRadius, ), ), - onPressed: () { - launchUrl(Uri.parse(linkUrl), mode: LaunchMode.externalApplication); + onPressed: () async { + if (label == "Email") { + await launchUrl( + Uri.parse(linkUrl), + mode: LaunchMode.externalApplication, + ); + } else { + await showDialog( + context: context, + builder: + (_) => ScamWarningDialog( + channel: label, + onUnderstandPressed: + () => launchUrl( + Uri.parse(linkUrl), + mode: LaunchMode.externalApplication, + ), + ), + ); + } }, child: Padding( padding: @@ -207,3 +227,182 @@ class AboutItem extends StatelessWidget { ); } } + +class ScamWarningDialog extends StatelessWidget { + const ScamWarningDialog({ + super.key, + required this.onUnderstandPressed, + required this.channel, + }); + + final String channel; + final VoidCallback onUnderstandPressed; + + @override + Widget build(BuildContext context) { + return SDialog( + padding: EdgeInsets.all(Util.isDesktop ? 32 : 16), + child: ConditionalParent( + condition: Util.isDesktop, + builder: (child) => IntrinsicWidth(child: child), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + RichText( + text: TextSpan( + style: + Util.isDesktop + ? STextStyles.w500_16(context) + : STextStyles.w500_14(context), + children: [ + TextSpan( + text: "Important: Protect Yourself from Scammers!\n\n", + style: + Util.isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH2(context), + ), + const TextSpan( + text: "All official support for ", + style: TextStyle(fontWeight: FontWeight.normal), + ), + const TextSpan( + text: AppConfig.appName, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan( + text: " in ", + style: TextStyle(fontWeight: FontWeight.normal), + ), + TextSpan( + text: channel, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan( + text: " is provided ", + style: TextStyle(fontWeight: FontWeight.normal), + ), + const TextSpan( + text: "ONLY", + style: TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan( + text: " in public channels.\n\n", + style: TextStyle(fontWeight: FontWeight.normal), + ), + ], + ), + ), + const _Bullet( + text: + "Never trust direct messages (DMs) from anyone" + " claiming to be support staff.\n", + ), + const _Bullet( + text: + "Do not share personal information," + " wallet details, or private keys.\n", + ), + const _Bullet( + text: + "If someone asks you to send them money or crypto," + " they are a scammer.\n\n", + ), + RichText( + text: TextSpan( + style: + Util.isDesktop + ? STextStyles.w500_16(context) + : STextStyles.w500_14(context), + children: const [ + TextSpan( + text: "Our support staff will ", + style: TextStyle(fontWeight: FontWeight.normal), + ), + TextSpan( + text: "*never*", + style: TextStyle( + fontStyle: FontStyle.italic, + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: + " contact you privately first. " + "They will only help you in the public chat.", + style: TextStyle(fontWeight: FontWeight.normal), + ), + ], + ), + ), + SizedBox(height: Util.isDesktop ? 40 : 32), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (!Util.isDesktop) const Spacer(), + ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => Expanded(child: child), + child: PrimaryButton( + width: Util.isDesktop ? 240 : null, + buttonHeight: Util.isDesktop ? ButtonHeight.l : null, + label: "I UNDERSTAND", + onPressed: onUnderstandPressed, + ), + ), + ], + ), + ], + ), + ), + ); + } +} + +class _Bullet extends StatelessWidget { + const _Bullet({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + style: + Util.isDesktop + ? STextStyles.w500_16(context) + : STextStyles.w500_14(context), + children: const [ + TextSpan( + text: " • ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => Expanded(child: child), + child: RichText( + text: TextSpan( + style: + Util.isDesktop + ? STextStyles.w500_16(context) + : STextStyles.w500_14(context), + children: [ + TextSpan( + text: text, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + ), + ], + ); + } +} From b67a067b7ab87404f6fe3377dfdaae2e5ee08f75 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 27 Jul 2025 13:22:51 -0600 Subject: [PATCH 191/206] don't use taproot address in buy flow when selecting receiving wallet from stack --- lib/pages/buy_view/buy_form.dart | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/pages/buy_view/buy_form.dart b/lib/pages/buy_view/buy_form.dart index c194ec9ee..64a7ba40f 100644 --- a/lib/pages/buy_view/buy_form.dart +++ b/lib/pages/buy_view/buy_form.dart @@ -16,12 +16,14 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:intl/intl.dart'; +import 'package:isar/isar.dart'; import '../../app_config.dart'; import '../../models/buy/response_objects/crypto.dart'; import '../../models/buy/response_objects/fiat.dart'; import '../../models/buy/response_objects/quote.dart'; import '../../models/contact_address_entry.dart'; +import '../../models/isar/models/blockchain_data/address.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart'; import '../../providers/providers.dart'; @@ -33,10 +35,12 @@ import '../../utilities/assets.dart'; import '../../utilities/barcode_scanner_interface.dart'; import '../../utilities/clipboard_interface.dart'; import '../../utilities/constants.dart'; +import '../../utilities/enums/derive_path_type_enum.dart'; import '../../utilities/logger.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; +import '../../wallets/wallet/intermediate/bip39_hd_wallet.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/blue_text_button.dart'; import '../../widgets/custom_loading_overlay.dart'; @@ -1204,9 +1208,34 @@ class _BuyFormState extends ConsumerState { // _toController.text = manager.walletName; // model.recipientAddress = // await manager.currentReceivingAddress; - _receiveAddressController.text = - (await wallet.getCurrentReceivingAddress())! - .value; + + final address = + await wallet.getCurrentReceivingAddress(); + + if (address!.type == AddressType.p2tr && + wallet is Bip39HDWallet) { + // lets assume any wallet that has taproot also has segwit. WCGW + final address = + await ref + .read(mainDBProvider) + .isar + .addresses + .where() + .walletIdEqualTo(wallet.walletId) + .filter() + .typeEqualTo(AddressType.p2wpkh) + .sortByDerivationIndexDesc() + .findFirst() ?? + await wallet.generateNextReceivingAddress( + derivePathType: DerivePathType.bip84, + ); + + _receiveAddressController.text = + address.value; + } else { + _receiveAddressController.text = + address.value; + } setState(() { _addressToggleFlag = From 81c1f8bdc64c05483f27a48f2d3f3a7a0e79fe00 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 28 Jul 2025 07:33:25 -0600 Subject: [PATCH 192/206] fix spark -> transparent fee calc --- lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart index af6894676..671c79770 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart @@ -497,7 +497,7 @@ mixin SparkInterface subtractFeeFromAmount: true, serializedCoins: serializedCoins, privateRecipientsCount: (txData.sparkRecipients?.length ?? 0), - utxoNum: 0, // ?? + utxoNum: recipientCount, additionalTxSize: 0, // name script size ); estimatedFee = BigInt.from(estFee); From 4017533922abeb57e33c250e46392a9296bce4c3 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 28 Jul 2025 11:33:08 -0600 Subject: [PATCH 193/206] display instant lock tag on pending firo transactions --- .../blockchain_data/v2/transaction_v2.dart | 5 ++++ .../tx_v2/transaction_v2_card.dart | 27 ++++++++++++++++--- lib/wallets/wallet/impl/firo_wallet.dart | 17 ++++++------ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart index 378e93d0f..3a2026785 100644 --- a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart +++ b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart @@ -329,6 +329,10 @@ class TransactionV2 { bool isCoinbase() => type == TransactionType.incoming && inputs.any((e) => e.coinbase != null); + @ignore + bool get isInstantLock => + _getFromOtherData(key: TxV2OdKeys.isInstantLock) == true; + @override String toString() { return 'TransactionV2(\n' @@ -362,4 +366,5 @@ abstract final class TxV2OdKeys { static const moneroAmount = "moneroAmount"; static const moneroAccountIndex = "moneroAccountIndex"; static const isMoneroTransaction = "isMoneroTransaction"; + static const isInstantLock = "isInstantLock"; } diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart index 9af007aef..3fb0aaaab 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart @@ -21,6 +21,8 @@ import '../../../../utilities/util.dart'; import '../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; +import '../../../../widgets/coin_ticker_tag.dart'; +import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../sub_widgets/tx_icon.dart'; import 'transaction_v2_details_view.dart'; @@ -235,9 +237,28 @@ class _TransactionCardStateV2 extends ConsumerState { Flexible( child: FittedBox( fit: BoxFit.scaleDown, - child: Text( - whatIsIt(coin, currentHeight), - style: STextStyles.itemSubtitle12(context), + child: ConditionalParent( + condition: + coin is Firo && + _transaction.isInstantLock && + !_transaction.isConfirmed( + currentHeight, + coin.minConfirms, + coin.minCoinbaseConfirms, + ), + builder: + (child) => Row( + children: [ + child, + + const SizedBox(width: 10), + const CoinTickerTag(ticker: "INSTANT"), + ], + ), + child: Text( + whatIsIt(coin, currentHeight), + style: STextStyles.itemSubtitle12(context), + ), ), ), ), diff --git a/lib/wallets/wallet/impl/firo_wallet.dart b/lib/wallets/wallet/impl/firo_wallet.dart index 233bfd344..a6f000e0a 100644 --- a/lib/wallets/wallet/impl/firo_wallet.dart +++ b/lib/wallets/wallet/impl/firo_wallet.dart @@ -563,9 +563,14 @@ class FiroWallet extends Bip39HDWallet continue; } - String? otherData; + final isInstantLock = txData["instantlock"] as bool? ?? false; + + final otherData = { + TxV2OdKeys.isInstantLock: isInstantLock, + }; + if (anonFees != null) { - otherData = jsonEncode({"overrideFee": anonFees!.toJsonString()}); + otherData[TxV2OdKeys.overrideFee] = anonFees!.toJsonString(); } final tx = TransactionV2( @@ -582,7 +587,7 @@ class FiroWallet extends Bip39HDWallet outputs: List.unmodifiable(outputs), type: type, subType: subType, - otherData: otherData, + otherData: jsonEncode(otherData), ); if (_unconfirmedTxids.contains(tx.txid)) { @@ -591,14 +596,10 @@ class FiroWallet extends Bip39HDWallet cryptoCurrency.minConfirms, cryptoCurrency.minCoinbaseConfirms, )) { - txns.add(tx); _unconfirmedTxids.removeWhere((e) => e == tx.txid); - } else { - // don't update in db until confirmed } - } else { - txns.add(tx); } + txns.add(tx); } await mainDB.updateOrPutTransactionV2s(txns); From 4a68a403f420b6342b2cf17f7d9421b1c048d1be Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 28 Jul 2025 12:26:36 -0600 Subject: [PATCH 194/206] fix monKey image filename --- lib/pages/monkey/monkey_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/monkey/monkey_view.dart b/lib/pages/monkey/monkey_view.dart index 79cadf9a0..49329cc98 100644 --- a/lib/pages/monkey/monkey_view.dart +++ b/lib/pages/monkey/monkey_view.dart @@ -80,7 +80,7 @@ class _MonkeyViewState extends ConsumerState { .read(pWallets) .getWallet(walletId) .getCurrentReceivingAddress(); - String filePath = path.join(dir.path, "monkey_$address"); + String filePath = path.join(dir.path, "monkey_${address?.value}"); filePath += isPNG ? ".png" : ".svg"; From 5e57e8c6bdc6f1d83c8bb227bd7da233b9022917 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 28 Jul 2025 14:46:37 -0600 Subject: [PATCH 195/206] twitter -> x --- asset_sources/svg/campfire/socials/twitter-brands.svg | 1 - asset_sources/svg/campfire/socials/x.svg | 1 + asset_sources/svg/stack_duo/socials/twitter-brands.svg | 1 - asset_sources/svg/stack_duo/socials/x.svg | 1 + asset_sources/svg/stack_wallet/socials/twitter-brands.svg | 1 - asset_sources/svg/stack_wallet/socials/x.svg | 1 + .../settings_views/global_settings_view/support_view.dart | 4 ++-- lib/utilities/assets.dart | 2 +- 8 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 asset_sources/svg/campfire/socials/twitter-brands.svg create mode 100644 asset_sources/svg/campfire/socials/x.svg delete mode 100644 asset_sources/svg/stack_duo/socials/twitter-brands.svg create mode 100644 asset_sources/svg/stack_duo/socials/x.svg delete mode 100644 asset_sources/svg/stack_wallet/socials/twitter-brands.svg create mode 100644 asset_sources/svg/stack_wallet/socials/x.svg diff --git a/asset_sources/svg/campfire/socials/twitter-brands.svg b/asset_sources/svg/campfire/socials/twitter-brands.svg deleted file mode 100644 index 96464c99f..000000000 --- a/asset_sources/svg/campfire/socials/twitter-brands.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/asset_sources/svg/campfire/socials/x.svg b/asset_sources/svg/campfire/socials/x.svg new file mode 100644 index 000000000..114491669 --- /dev/null +++ b/asset_sources/svg/campfire/socials/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/asset_sources/svg/stack_duo/socials/twitter-brands.svg b/asset_sources/svg/stack_duo/socials/twitter-brands.svg deleted file mode 100644 index 96464c99f..000000000 --- a/asset_sources/svg/stack_duo/socials/twitter-brands.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/asset_sources/svg/stack_duo/socials/x.svg b/asset_sources/svg/stack_duo/socials/x.svg new file mode 100644 index 000000000..114491669 --- /dev/null +++ b/asset_sources/svg/stack_duo/socials/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/asset_sources/svg/stack_wallet/socials/twitter-brands.svg b/asset_sources/svg/stack_wallet/socials/twitter-brands.svg deleted file mode 100644 index 96464c99f..000000000 --- a/asset_sources/svg/stack_wallet/socials/twitter-brands.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/asset_sources/svg/stack_wallet/socials/x.svg b/asset_sources/svg/stack_wallet/socials/x.svg new file mode 100644 index 000000000..114491669 --- /dev/null +++ b/asset_sources/svg/stack_wallet/socials/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/pages/settings_views/global_settings_view/support_view.dart b/lib/pages/settings_views/global_settings_view/support_view.dart index fb7f6b512..a88e47099 100644 --- a/lib/pages/settings_views/global_settings_view/support_view.dart +++ b/lib/pages/settings_views/global_settings_view/support_view.dart @@ -92,8 +92,8 @@ class SupportView extends StatelessWidget { ), const SizedBox(height: 8), AboutItem( - linkUrl: "https://twitter.com/stack_wallet", - label: "Twitter", + linkUrl: "https://x.com/stack_wallet", + label: "X", buttonText: "@stack_wallet", iconAsset: Assets.socials.twitter, isDesktop: isDesktop, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index 679187c5c..d14cdc38c 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -32,7 +32,7 @@ class _SOCIALS { String get discord => "${_path}discord.svg"; String get reddit => "${_path}reddit-alien-brands.svg"; - String get twitter => "${_path}twitter-brands.svg"; + String get twitter => "${_path}x.svg"; String get telegram => "${_path}telegram-brands.svg"; } From 62c167c7266743722d26f0d578b5bc2a5e00a7d9 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 29 Jul 2025 16:13:21 -0500 Subject: [PATCH 196/206] fix(macos): close mwebd on app close --- lib/main.dart | 32 ++++++++ lib/services/mwebd_service.dart | 136 ++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 3ffda4012..e05610a6d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -615,6 +615,38 @@ class _MaterialAppWithThemeState extends ConsumerState // } break; case AppLifecycleState.detached: + // Clean shutdown of mwebd service with aggressive timeout for macOS. + if (Platform.isMacOS) { + // On macOS, use very short timeout since native StopServer is skipped. + try { + debugPrint("App detached on macOS, quick shutdown..."); + await ref.read(pMwebService).shutdown().timeout( + const Duration(seconds: 2), + onTimeout: () { + debugPrint("MwebdService shutdown timed out after 2 seconds on macOS"); + exit(0); + }, + ); + debugPrint("MwebdService shutdown completed on macOS"); + } catch (e, s) { + debugPrint("Error during MwebdService shutdown on macOS: $e\n$s"); + exit(0); + } + } else { + // Non-macOS platforms can use longer timeout. + try { + debugPrint("App detached, shutting down MwebdService..."); + await ref.read(pMwebService).shutdown().timeout( + const Duration(seconds: 5), + onTimeout: () { + debugPrint("MwebdService shutdown timed out after 5 seconds"); + }, + ); + debugPrint("MwebdService shutdown completed successfully"); + } catch (e, s) { + debugPrint("Error during MwebdService shutdown: $e\n$s"); + } + } break; case AppLifecycleState.hidden: break; diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index 89f2bee37..2d6e8604b 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -34,6 +34,9 @@ final class MwebdService { final Mutex _torConnectingLock = Mutex(); + // Track active log stream controllers for cleanup during shutdown. + final Set> _activeLogControllers = {}; + static final instance = MwebdService._(); MwebdService._() { @@ -204,6 +207,9 @@ final class MwebdService { String leftover = ''; Timer? timer; + // Track this controller for cleanup during shutdown. + _activeLogControllers.add(controller); + final path = "${(await StackFileSystem.applicationMwebdDirectory(net == CryptoCurrencyNetwork.main ? "mainnet" : "testnet")).path}" "${Platform.pathSeparator}logs" @@ -237,11 +243,141 @@ final class MwebdService { controller.onCancel = () { timer?.cancel(); + _activeLogControllers.remove(controller); controller.close(); }; return controller.stream; } + + /// Shutdown all mwebd servers and clean up resources. + /// + /// This method should be called when the app is terminating to prevent hanging. + Future shutdown() async { + final stopwatch = Stopwatch()..start(); + Logging.instance.i("MwebdService shutdown() started"); + + await _updateLock.protect(() async { + // Cancel stream subscriptions to prevent further events. + try { + await _torStatusListener.cancel(); + Logging.instance.i("Canceled tor status listener"); + } catch (e, s) { + Logging.instance.w( + "Error canceling tor status listener", + error: e, + stackTrace: s, + ); + } + + try { + await _torPreferenceListener.cancel(); + Logging.instance.i("Canceled tor preference listener"); + } catch (e, s) { + Logging.instance.w( + "Error canceling tor preference listener", + error: e, + stackTrace: s, + ); + } + + // Cancel all active log stream controllers and their timers. + final logControllers = List.from(_activeLogControllers); + for (final controller in logControllers) { + try { + await controller.close(); + Logging.instance.i("Closed log stream controller"); + } catch (e, s) { + Logging.instance.w( + "Error closing log stream controller", + error: e, + stackTrace: s, + ); + } + } + _activeLogControllers.clear(); + + // Stop all servers and clean up clients with timeout protection. + final stopFutures = []; + for (final entry in _map.values) { + stopFutures.add(_shutdownServerSafely(entry)); + } + + // Wait for all shutdowns with overall timeout. + try { + await Future.wait(stopFutures).timeout( + const Duration(seconds: 10), + onTimeout: () { + Logging.instance.w("Timeout waiting for mwebd servers to stop"); + return []; // Return a dummy list. + }, + ); + } catch (e, s) { + Logging.instance.w( + "Error during mwebd servers shutdown", + error: e, + stackTrace: s, + ); + } + + _map.clear(); + + final elapsedMs = stopwatch.elapsedMilliseconds; + Logging.instance.i("MwebdService shutdown() completed in ${elapsedMs}ms"); + + // Warn if shutdown took too long (could indicate hanging). + if (elapsedMs > 3000) { + Logging.instance.w("MwebdService shutdown took ${elapsedMs}ms - longer than expected"); + } + }); + } + + /// Safely shutdown a server/client pair with timeout protection. + Future _shutdownServerSafely( + ({MwebdServer server, MwebClient client}) entry, + ) async { + final serverStopwatch = Stopwatch()..start(); + Logging.instance.i("Starting shutdown of mwebd server/client pair"); + + try { + // Clean up client first. + final clientStopwatch = Stopwatch()..start(); + await entry.client.cleanup().timeout( + const Duration(seconds: 3), + onTimeout: () { + Logging.instance.w("Timeout cleaning up mweb client after 3s"); + }, + ); + Logging.instance.i("Client cleanup completed in ${clientStopwatch.elapsedMilliseconds}ms"); + } catch (e, s) { + Logging.instance.w( + "Error cleaning up mweb client", + error: e, + stackTrace: s, + ); + } + + try { + // Stop server with timeout protection. + final serverShutdownStopwatch = Stopwatch()..start(); + await entry.server.stopServer().timeout( + const Duration(seconds: 5), + onTimeout: () { + Logging.instance.w("Timeout stopping mwebd server after 5s"); + }, + ); + Logging.instance.i("Server stop completed in ${serverShutdownStopwatch.elapsedMilliseconds}ms"); + } catch (e, s) { + Logging.instance.w( + "Error stopping mwebd server", + error: e, + stackTrace: s, + ); + } + + final totalMs = serverStopwatch.elapsedMilliseconds; + Logging.instance.i("Server/client pair shutdown completed in ${totalMs}ms"); + } } // ============================================================================ From 32ccd5cffc9f081b700088a81b04d1b378a910a6 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 10:59:10 -0600 Subject: [PATCH 197/206] feat: auto lock screen after idle timeout setting --- lib/pages/home_view/home_view.dart | 63 ++ .../auto_lock_timeout_settings_view.dart | 229 ++++++ .../security_views/security_view.dart | 51 ++ .../desktop_home_view.dart | 96 ++- .../password/desktop_unlock_app_dialog.dart | 206 +++++ ...ktop_autolock_timeout_settings_dialog.dart | 41 + .../settings_menu/security_settings.dart | 757 ++++++++++-------- lib/route_generator.dart | 8 + lib/utilities/idle_monitor.dart | 73 ++ lib/utilities/prefs.dart | 36 + 10 files changed, 1193 insertions(+), 367 deletions(-) create mode 100644 lib/pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart create mode 100644 lib/pages_desktop_specific/password/desktop_unlock_app_dialog.dart create mode 100644 lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_autolock_timeout_settings_dialog.dart create mode 100644 lib/utilities/idle_monitor.dart diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index d937ac4a7..126a16bfb 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -20,11 +20,14 @@ import '../../providers/global/notifications_provider.dart'; import '../../providers/global/prefs_provider.dart'; import '../../providers/ui/home_view_index_provider.dart'; import '../../providers/ui/unread_notifications_provider.dart'; +import '../../route_generator.dart'; import '../../services/event_bus/events/global/tor_connection_status_changed_event.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; +import '../../utilities/idle_monitor.dart'; +import '../../utilities/prefs.dart'; import '../../utilities/text_styles.dart'; import '../../widgets/animated_widgets/rotate_icon.dart'; import '../../widgets/app_icon.dart'; @@ -35,6 +38,7 @@ import '../../widgets/stack_dialog.dart'; import '../buy_view/buy_view.dart'; import '../exchange_view/exchange_view.dart'; import '../notification_views/notifications_view.dart'; +import '../pinpad_views/lock_screen_view.dart'; import '../settings_views/global_settings_view/global_settings_view.dart'; import '../settings_views/global_settings_view/hidden_settings.dart'; import '../wallets_view/wallets_view.dart'; @@ -63,6 +67,51 @@ class _HomeViewState extends ConsumerState { late TorConnectionStatus _currentSyncStatus; + IdleMonitor? _idleMonitor; + + void _onIdle() async { + final context = _key.currentContext; + if (context != null) { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: false, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to unlock ${AppConfig.appName}", + biometricsAuthenticationTitle: "Unlock ${AppConfig.appName}", + ), + settings: const RouteSettings(name: "/unlockTimedOutAppScreen"), + ), + ); + } + } + + late AutoLockInfo _autoLockInfo; + void _prefsTimeoutListener() { + final prefs = ref.read(prefsChangeNotifierProvider); + if (mounted && prefs.autoLockInfo != _autoLockInfo) { + _autoLockInfo = prefs.autoLockInfo; + if (_autoLockInfo.enabled) { + _idleMonitor?.detach(); + _idleMonitor = IdleMonitor( + timeout: Duration(minutes: _autoLockInfo.minutes), + onIdle: _onIdle, + ); + _idleMonitor!.attach(); + } else { + _idleMonitor?.detach(); + _idleMonitor = null; + } + } + } + // final _buyDataLoadingService = BuyDataLoadingService(); Future _onWillPop() async { @@ -124,6 +173,14 @@ class _HomeViewState extends ConsumerState { @override void initState() { + _autoLockInfo = ref.read(prefsChangeNotifierProvider).autoLockInfo; + if (_autoLockInfo.enabled) { + _idleMonitor = IdleMonitor( + timeout: Duration(minutes: _autoLockInfo.minutes), + onIdle: _onIdle, + ); + } + _pageController = PageController(); _rotateIconController = RotateIconController(); _children = [ @@ -140,11 +197,17 @@ class _HomeViewState extends ConsumerState { // showOneTimeTorHasBeenAddedDialogIfRequired(context); // }); + _idleMonitor?.attach(); + + ref.read(prefsChangeNotifierProvider).addListener(_prefsTimeoutListener); + super.initState(); } @override dispose() { + ref.read(prefsChangeNotifierProvider).removeListener(_prefsTimeoutListener); + _idleMonitor?.detach(); _pageController.dispose(); _rotateIconController.forward = null; _rotateIconController.reverse = null; diff --git a/lib/pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart b/lib/pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart new file mode 100644 index 000000000..924b39189 --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart @@ -0,0 +1,229 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../providers/providers.dart'; +import '../../../../themes/stack_colors.dart'; +import '../../../../utilities/constants.dart'; +import '../../../../utilities/text_styles.dart'; +import '../../../../utilities/util.dart'; +import '../../../../widgets/background.dart'; +import '../../../../widgets/conditional_parent.dart'; +import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; +import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/rounded_white_container.dart'; + +class AutoLockTimeoutSettingsView extends ConsumerStatefulWidget { + const AutoLockTimeoutSettingsView({super.key}); + + static const routeName = "/autoLockTimeoutSettingsView"; + + @override + ConsumerState createState() => + _AutoLockTimeoutSettingsViewState(); +} + +class _AutoLockTimeoutSettingsViewState + extends ConsumerState { + final isDesktop = Util.isDesktop; + final TextEditingController _timeController = TextEditingController(); + late bool _enabled; + bool _lock = false; + + Future _save() async { + if (_lock) return; + _lock = true; + + try { + final minutes = int.tryParse(_timeController.text); + + if (minutes == null) { + // this should not hit unless logic in validating text field input is + // wrong + return; + } + + ref.read(prefsChangeNotifierProvider).autoLockInfo = ( + enabled: _enabled, + minutes: minutes, + ); + + Navigator.of(context, rootNavigator: isDesktop).pop(); + } finally { + _lock = false; + } + } + + int _minutesCache = 1; + + int _clampMinutes(int input) { + if (input > 60) return 60; + if (input < 1) return 1; + return input; + } + + @override + void initState() { + super.initState(); + _enabled = ref.read(prefsChangeNotifierProvider).autoLockInfo.enabled; + _minutesCache = _clampMinutes( + ref.read(prefsChangeNotifierProvider).autoLockInfo.minutes, + ); + _timeController.text = _minutesCache.toString(); + } + + @override + void dispose() { + _timeController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ConditionalParent( + condition: !isDesktop, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 70), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ), + ); + }, + ), + ), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: RawMaterialButton( + splashColor: + Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Toggle auto lock", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: _enabled, + onValueChanged: (newValue) { + _enabled = newValue; + }, + ), + ), + ], + ), + ), + ), + ), + SizedBox(height: isDesktop ? 24 : 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + Text("Minutes", style: STextStyles.titleBold12(context)), + const SizedBox(width: 16), + Flexible( + child: TextField( + controller: _timeController, + autocorrect: false, + enableSuggestions: false, + style: STextStyles.field(context), + inputFormatters: [ + TextInputFormatter.withFunction( + (oldValue, newValue) => + RegExp(r'^([0-9]*)$').hasMatch(newValue.text) + ? newValue + : oldValue, + ), + ], + onChanged: (value) { + final number = int.tryParse(value); + if (number == null || number < 1 || number > 60) { + _timeController.text = _minutesCache.toString(); + return; + } + + _minutesCache = _clampMinutes(number); + }, + keyboardType: const TextInputType.numberWithOptions( + signed: false, + decimal: false, + ), + decoration: InputDecoration( + hintText: "Minutes", + hintStyle: STextStyles.fieldLabel(context), + ), + ), + ), + ], + ), + ), + SizedBox(height: isDesktop ? 40 : 16), + if (!isDesktop) const Spacer(), + ConditionalParent( + condition: isDesktop, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [child], + ), + child: PrimaryButton( + buttonHeight: isDesktop ? ButtonHeight.l : null, + width: isDesktop ? 200 : null, + label: "Save", + onPressed: _save, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart index 5412189ec..76331b0bb 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart @@ -27,6 +27,7 @@ import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/rounded_white_container.dart'; import '../../../../widgets/stack_dialog.dart'; import '../../../pinpad_views/lock_screen_view.dart'; +import 'auto_lock_timeout_settings_view.dart'; import 'change_pin_view/change_pin_view.dart'; import 'create_duress_pin_view.dart'; @@ -519,6 +520,56 @@ class _SecurityViewState extends ConsumerState { }, ), ), + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: + AutoLockTimeoutSettingsView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to change auto lock settings", + biometricsAuthenticationTitle: + "Auto lock settings", + ), + settings: const RouteSettings( + name: "/autoLockTimeoutSettingsLockScreen", + ), + ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Auto lock settings", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), + ), + ), + ), ], ), ), diff --git a/lib/pages_desktop_specific/desktop_home_view.dart b/lib/pages_desktop_specific/desktop_home_view.dart index 980b563a0..d29aeb4bc 100644 --- a/lib/pages_desktop_specific/desktop_home_view.dart +++ b/lib/pages_desktop_specific/desktop_home_view.dart @@ -8,6 +8,8 @@ * */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -22,6 +24,8 @@ import '../providers/ui/unread_notifications_provider.dart'; import '../route_generator.dart'; import '../themes/stack_colors.dart'; import '../utilities/enums/backup_frequency_type.dart'; +import '../utilities/idle_monitor.dart'; +import '../utilities/prefs.dart'; import '../widgets/background.dart'; import 'address_book_view/desktop_address_book.dart'; import 'desktop_buy/desktop_buy_view.dart'; @@ -29,6 +33,7 @@ import 'desktop_exchange/desktop_exchange_view.dart'; import 'desktop_menu.dart'; import 'my_stack_view/my_stack_view.dart'; import 'notifications/desktop_notifications_view.dart'; +import 'password/desktop_unlock_app_dialog.dart'; import 'settings/desktop_settings_view.dart'; import 'settings/settings_menu/desktop_about_view.dart'; import 'settings/settings_menu/desktop_support_view.dart'; @@ -45,14 +50,60 @@ class DesktopHomeView extends ConsumerStatefulWidget { class _DesktopHomeViewState extends ConsumerState { final GlobalKey myStackViewNavKey = GlobalKey(); late final Navigator myStackViewNav; + IdleMonitor? _idleMonitor; + + void _onIdle() async { + final context = myStackViewNavKey.currentContext; + if (context != null) { + await showDialog( + barrierDismissible: false, + context: context, + useSafeArea: false, + builder: + (context) => const Background( + child: Center(child: DesktopUnlockAppDialog()), + ), + ); + } + } + + late AutoLockInfo _autoLockInfo; + void _prefsTimeoutListener() { + final prefs = ref.read(prefsChangeNotifierProvider); + if (mounted && prefs.autoLockInfo != _autoLockInfo) { + _autoLockInfo = prefs.autoLockInfo; + if (_autoLockInfo.enabled) { + _idleMonitor?.detach(); + _idleMonitor = IdleMonitor( + timeout: Duration(minutes: _autoLockInfo.minutes), + onIdle: _onIdle, + ); + _idleMonitor!.attach(); + } else { + _idleMonitor?.detach(); + _idleMonitor = null; + } + } + } @override void initState() { + _autoLockInfo = ref.read(prefsChangeNotifierProvider).autoLockInfo; + if (_autoLockInfo.enabled) { + _idleMonitor = IdleMonitor( + timeout: Duration(minutes: _autoLockInfo.minutes), + onIdle: _onIdle, + ); + } + myStackViewNav = Navigator( key: myStackViewNavKey, onGenerateRoute: RouteGenerator.generateRoute, initialRoute: MyStackView.routeName, ); + _idleMonitor?.attach(); + + ref.read(prefsChangeNotifierProvider).addListener(_prefsTimeoutListener); // WidgetsBinding.instance.addPostFrameCallback((timeStamp) { // showOneTimeTorHasBeenAddedDialogIfRequired(context); @@ -61,12 +112,19 @@ class _DesktopHomeViewState extends ConsumerState { super.initState(); } + @override + dispose() { + ref.read(prefsChangeNotifierProvider).removeListener(_prefsTimeoutListener); + _idleMonitor?.detach(); + super.dispose(); + } + final Map contentViews = { DesktopMenuItemId.myStack: Container( - // key: Key("desktopStackHomeKey"), - // onGenerateRoute: RouteGenerator.generateRoute, - // initialRoute: MyStackView.routeName, - ), + // key: Key("desktopStackHomeKey"), + // onGenerateRoute: RouteGenerator.generateRoute, + // initialRoute: MyStackView.routeName, + ), DesktopMenuItemId.exchange: const Navigator( key: Key("desktopExchangeHomeKey"), onGenerateRoute: RouteGenerator.generateRoute, @@ -109,11 +167,13 @@ class _DesktopHomeViewState extends ConsumerState { if (ref.read(prevDesktopMenuItemProvider.state).state == DesktopMenuItemId.myStack && ref.read(prevDesktopMenuItemProvider.state).state == newKey) { - Navigator.of(myStackViewNavKey.currentContext!) - .popUntil(ModalRoute.withName(MyStackView.routeName)); + Navigator.of( + myStackViewNavKey.currentContext!, + ).popUntil(ModalRoute.withName(MyStackView.routeName)); if (ref.read(currentWalletIdProvider.state).state != null) { - final wallet = - ref.read(pWallets).getWallet(ref.read(currentWalletIdProvider)!); + final wallet = ref + .read(pWallets) + .getWallet(ref.read(currentWalletIdProvider)!); if (wallet.shouldAutoSync) { wallet.shouldAutoSync = false; @@ -182,17 +242,19 @@ class _DesktopHomeViewState extends ConsumerState { ), Expanded( child: IndexedStack( - index: ref - .watch(currentDesktopMenuItemProvider.state) - .state - .index > - 0 - ? 1 - : 0, + index: + ref + .watch(currentDesktopMenuItemProvider.state) + .state + .index > + 0 + ? 1 + : 0, children: [ myStackViewNav, - contentViews[ - ref.watch(currentDesktopMenuItemProvider.state).state]!, + contentViews[ref + .watch(currentDesktopMenuItemProvider.state) + .state]!, ], ), ), diff --git a/lib/pages_desktop_specific/password/desktop_unlock_app_dialog.dart b/lib/pages_desktop_specific/password/desktop_unlock_app_dialog.dart new file mode 100644 index 000000000..46f3218f5 --- /dev/null +++ b/lib/pages_desktop_specific/password/desktop_unlock_app_dialog.dart @@ -0,0 +1,206 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../../../../providers/desktop/storage_crypto_handler_provider.dart'; +import '../../../../themes/stack_colors.dart'; +import '../../../../utilities/assets.dart'; +import '../../../../utilities/constants.dart'; +import '../../../../utilities/text_styles.dart'; +import '../../../../widgets/desktop/primary_button.dart'; +import '../../../../widgets/stack_text_field.dart'; +import '../../app_config.dart'; +import '../../notifications/show_flush_bar.dart'; +import '../../utilities/show_loading.dart'; +import '../../widgets/desktop/desktop_dialog.dart'; + +class DesktopUnlockAppDialog extends ConsumerStatefulWidget { + const DesktopUnlockAppDialog({super.key}); + + @override + ConsumerState createState() => + _DesktopUnlockAppDialogState(); +} + +class _DesktopUnlockAppDialogState + extends ConsumerState { + late final TextEditingController passwordController; + late final FocusNode passwordFocusNode; + + bool hidePassword = true; + + bool _confirmEnabled = false; + bool _lock = false; + + Future _confirmPressed() async { + if (_lock) { + return; + } + _lock = true; + + try { + final passwordIsValid = await showLoading( + whileFuture: ref + .read(storageCryptoHandlerProvider) + .verifyPassphrase(passwordController.text), + context: context, + message: "Verifying password...", + delay: const Duration(seconds: 1), + ); + + if (mounted) { + if (passwordIsValid == true) { + Navigator.of(context, rootNavigator: true).pop(); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Invalid password!", + context: context, + ), + ); + } + } + } finally { + _lock = false; + } + } + + @override + void initState() { + passwordController = TextEditingController(); + passwordFocusNode = FocusNode(); + + super.initState(); + } + + @override + void dispose() { + passwordController.dispose(); + passwordFocusNode.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return DesktopDialog( + maxWidth: 579, + maxHeight: double.infinity, + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset(Assets.svg.keys, width: 100), + const SizedBox(height: 56), + Text( + "Unlock ${AppConfig.appName}", + style: STextStyles.desktopH3(context), + ), + const SizedBox(height: 16), + Text( + "Enter your wallet password to unlock ${AppConfig.appName}", + style: STextStyles.desktopTextMedium(context).copyWith( + color: Theme.of(context).extension()!.textDark3, + ), + ), + const SizedBox(height: 24), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("desktopUnlockAppPasswordFieldKey"), + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + autofocus: true, + onSubmitted: (_) { + if (_confirmEnabled) { + _confirmPressed(); + } + }, + decoration: standardInputDecoration( + "Enter password", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: SizedBox( + height: 70, + child: Row( + children: [ + const SizedBox(width: 24), + GestureDetector( + key: const Key( + "desktopUnlockAppPasswordFieldShowPasswordButtonKey", + ), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of( + context, + ).extension()!.textDark3, + width: 24, + height: 24, + ), + ), + const SizedBox(width: 12), + ], + ), + ), + ), + ), + onChanged: (newValue) { + setState(() { + _confirmEnabled = passwordController.text.isNotEmpty; + }); + }, + ), + ), + const SizedBox(height: 48), + Row( + children: [ + const Spacer(), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + enabled: _confirmEnabled, + label: "Unlock", + buttonHeight: ButtonHeight.l, + onPressed: _confirmPressed, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_autolock_timeout_settings_dialog.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_autolock_timeout_settings_dialog.dart new file mode 100644 index 000000000..2ebd3c85b --- /dev/null +++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_autolock_timeout_settings_dialog.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; + +import '../../../../pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart'; +import '../../../../utilities/text_styles.dart'; +import '../../../../widgets/desktop/desktop_dialog.dart'; +import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; + +class DesktopAutolockTimeoutSettingsDialog extends StatelessWidget { + const DesktopAutolockTimeoutSettingsDialog({super.key}); + + @override + Widget build(BuildContext context) { + return DesktopDialog( + maxHeight: double.infinity, + maxWidth: 480, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: Text( + "Auto lock timeout", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + + const Padding( + padding: EdgeInsets.only(left: 32, right: 32, bottom: 32, top: 20), + child: AutoLockTimeoutSettingsView(), + ), + ], + ), + ); + } +} diff --git a/lib/pages_desktop_specific/settings/settings_menu/security_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/security_settings.dart index 3b227f1d3..bb0ed0fda 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/security_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/security_settings.dart @@ -18,6 +18,7 @@ import 'package:zxcvbn/zxcvbn.dart'; import '../../../app_config.dart'; import '../../../notifications/show_flush_bar.dart'; import '../../../providers/desktop/storage_crypto_handler_provider.dart'; +import '../../../providers/global/prefs_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; @@ -27,6 +28,7 @@ import '../../../widgets/desktop/primary_button.dart'; import '../../../widgets/progress_bar.dart'; import '../../../widgets/rounded_white_container.dart'; import '../../../widgets/stack_text_field.dart'; +import 'advanced_settings/desktop_autolock_timeout_settings_dialog.dart'; class SecuritySettings extends ConsumerStatefulWidget { const SecuritySettings({super.key}); @@ -69,8 +71,9 @@ class _SecuritySettings extends ConsumerState { final String pwNew = passwordController.text; final String pwNewRepeat = passwordRepeatController.text; - final verified = - await ref.read(storageCryptoHandlerProvider).verifyPassphrase(pw); + final verified = await ref + .read(storageCryptoHandlerProvider) + .verifyPassphrase(pw); if (verified) { if (pwNew != pwNewRepeat) { @@ -78,11 +81,9 @@ class _SecuritySettings extends ConsumerState { return (false, FlushBarType.warning, "New passphrase does not match!"); } else { - final success = - await ref.read(storageCryptoHandlerProvider).changePassphrase( - pw, - pwNew, - ); + final success = await ref + .read(storageCryptoHandlerProvider) + .changePassphrase(pw, pwNew); if (success) { await Future.delayed(const Duration(seconds: 1)); @@ -90,7 +91,7 @@ class _SecuritySettings extends ConsumerState { return ( true, FlushBarType.success, - "Passphrase successfully changed" + "Passphrase successfully changed", ); } else { await Future.delayed(const Duration(seconds: 1)); @@ -137,9 +138,7 @@ class _SecuritySettings extends ConsumerState { return Column( children: [ Padding( - padding: const EdgeInsets.only( - right: 30, - ), + padding: const EdgeInsets.only(right: 30), child: RoundedWhiteContainer( radiusMultiplier: 2, child: Column( @@ -162,392 +161,450 @@ class _SecuritySettings extends ConsumerState { "Change Password", style: STextStyles.desktopTextSmall(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Text( "Protect your ${AppConfig.appName} with a strong password. ${AppConfig.appName} does not store " "your password, and is therefore NOT able to restore it. Keep your password safe and secure.", style: STextStyles.desktopTextExtraExtraSmall(context), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), changePassword ? SizedBox( - width: 512, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Current password", - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - textAlign: TextAlign.left, + width: 512, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Current password", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, ), - const SizedBox(height: 10), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + textAlign: TextAlign.left, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "desktopSecurityRestoreFromFilePasswordFieldKey", ), - child: TextField( - key: const Key( - "desktopSecurityRestoreFromFilePasswordFieldKey", - ), - focusNode: passwordCurrentFocusNode, - controller: passwordCurrentController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Enter current password", - passwordCurrentFocusNode, + focusNode: passwordCurrentFocusNode, + controller: passwordCurrentController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Enter current password", + passwordCurrentFocusNode, + context, + ).copyWith( + labelStyle: STextStyles.fieldLabel( context, - ).copyWith( - labelStyle: - STextStyles.fieldLabel(context), - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "desktopSecurityRestoreFromFilePasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = - !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, - ), + ), + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "desktopSecurityRestoreFromFilePasswordFieldShowPasswordButtonKey", ), - const SizedBox( - width: 12, + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark3, + width: 16, + height: 16, ), - ], - ), + ), + const SizedBox(width: 12), + ], ), ), - onChanged: (newValue) { - setState(() {}); - }, ), + onChanged: (newValue) { + setState(() {}); + }, ), - const SizedBox(height: 16), - Text( - "New password", - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - textAlign: TextAlign.left, + ), + const SizedBox(height: 16), + Text( + "New password", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + textAlign: TextAlign.left, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - const SizedBox(height: 10), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + child: TextField( + key: const Key( + "desktopSecurityCreateNewPasswordFieldKey1", ), - child: TextField( - key: const Key( - "desktopSecurityCreateNewPasswordFieldKey1", - ), - focusNode: passwordFocusNode, - controller: passwordController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Enter new password", - passwordFocusNode, + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Enter new password", + passwordFocusNode, + context, + ).copyWith( + labelStyle: STextStyles.fieldLabel( context, - ).copyWith( - labelStyle: - STextStyles.fieldLabel(context), - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "desktopSecurityCreateNewPasswordButtonKey1", - ), - onTap: () async { - setState(() { - hidePassword = - !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, - ), + ), + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "desktopSecurityCreateNewPasswordButtonKey1", ), - const SizedBox( - width: 12, + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark3, + width: 16, + height: 16, ), - ], - ), + ), + const SizedBox(width: 12), + ], ), ), - onChanged: (newValue) { - if (newValue.isEmpty) { - setState(() { - passwordFeedback = ""; - }); - return; - } - final result = - zxcvbn.evaluate(newValue); - String suggestionsAndTips = ""; - for (final sug in result - .feedback.suggestions! - .toSet()) { - suggestionsAndTips += "$sug\n"; - } - suggestionsAndTips += - result.feedback.warning!; - String feedback = - // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" - suggestionsAndTips; - - passwordStrength = result.score! / 4; - - // hack fix to format back string returned from zxcvbn - if (feedback - .contains("phrasesNo need")) { - feedback = feedback.replaceFirst( - "phrasesNo need", - "phrases\nNo need", - ); - } - - if (feedback.endsWith("\n")) { - feedback = feedback.substring( - 0, - feedback.length - 2, - ); - } - + ), + onChanged: (newValue) { + if (newValue.isEmpty) { setState(() { - passwordFeedback = feedback; + passwordFeedback = ""; }); - }, - ), + return; + } + final result = zxcvbn.evaluate(newValue); + String suggestionsAndTips = ""; + for (final sug + in result.feedback.suggestions! + .toSet()) { + suggestionsAndTips += "$sug\n"; + } + suggestionsAndTips += + result.feedback.warning!; + String feedback = + // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" + suggestionsAndTips; + + passwordStrength = result.score! / 4; + + // hack fix to format back string returned from zxcvbn + if (feedback.contains("phrasesNo need")) { + feedback = feedback.replaceFirst( + "phrasesNo need", + "phrases\nNo need", + ); + } + + if (feedback.endsWith("\n")) { + feedback = feedback.substring( + 0, + feedback.length - 2, + ); + } + + setState(() { + passwordFeedback = feedback; + }); + }, ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: EdgeInsets.only( - left: 12, - right: 12, - top: - passwordFeedback.isNotEmpty ? 4 : 0, - ), - child: passwordFeedback.isNotEmpty - ? Text( + ), + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: EdgeInsets.only( + left: 12, + right: 12, + top: passwordFeedback.isNotEmpty ? 4 : 0, + ), + child: + passwordFeedback.isNotEmpty + ? Text( passwordFeedback, style: STextStyles.infoSmall( context, ), ) - : null, + : null, + ), + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: const EdgeInsets.only( + left: 12, + right: 12, + top: 10, ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), - child: ProgressBar( - key: const Key( - "desktopSecurityCreateStackBackUpProgressBar", - ), - width: 450, - height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context) - .extension()! - .accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, - percent: passwordStrength < 0.25 - ? 0.03 - : passwordStrength, + child: ProgressBar( + key: const Key( + "desktopSecurityCreateStackBackUpProgressBar", ), + width: 450, + height: 5, + fillColor: + passwordStrength < 0.51 + ? Theme.of(context) + .extension()! + .accentColorRed + : passwordStrength < 1 + ? Theme.of(context) + .extension()! + .accentColorYellow + : Theme.of(context) + .extension()! + .accentColorGreen, + backgroundColor: + Theme.of(context) + .extension()! + .buttonBackSecondary, + percent: + passwordStrength < 0.25 + ? 0.03 + : passwordStrength, ), - const SizedBox(height: 16), - Text( - "Confirm new password", - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - textAlign: TextAlign.left, ), - const SizedBox(height: 10), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 16), + Text( + "Confirm new password", + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + textAlign: TextAlign.left, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "desktopSecurityCreateNewPasswordFieldKey2", ), - child: TextField( - key: const Key( - "desktopSecurityCreateNewPasswordFieldKey2", - ), - focusNode: passwordRepeatFocusNode, - controller: passwordRepeatController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Confirm new password", - passwordRepeatFocusNode, + focusNode: passwordRepeatFocusNode, + controller: passwordRepeatController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Confirm new password", + passwordRepeatFocusNode, + context, + ).copyWith( + labelStyle: STextStyles.fieldLabel( context, - ).copyWith( - labelStyle: - STextStyles.fieldLabel(context), - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "desktopSecurityCreateNewPasswordButtonKey2", - ), - onTap: () async { - setState(() { - hidePassword = - !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, - ), + ), + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "desktopSecurityCreateNewPasswordButtonKey2", ), - const SizedBox( - width: 12, + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark3, + width: 16, + height: 16, ), - ], - ), + ), + const SizedBox(width: 12), + ], ), ), - onChanged: (newValue) { - setState(() {}); - }, ), + onChanged: (newValue) { + setState(() {}); + }, ), - const SizedBox(height: 20), - PrimaryButton( - width: 160, - buttonHeight: ButtonHeight.l, - enabled: shouldEnableSave, - label: "Save changes", - onPressed: () async { - if (_changePWLock) { - return; + ), + const SizedBox(height: 20), + PrimaryButton( + width: 160, + buttonHeight: ButtonHeight.l, + enabled: shouldEnableSave, + label: "Save changes", + onPressed: () async { + if (_changePWLock) { + return; + } + _changePWLock = true; + + try { + final (didChangePW, type, message) = + (await showLoading( + whileFuture: _attemptChangePW(), + context: context, + message: "Updating...", + rootNavigator: true, + ))!; + + if (mounted) { + unawaited( + showFloatingFlushBar( + type: type, + message: message, + context: context, + ), + ); } - _changePWLock = true; - - try { - final (didChangePW, type, message) = - (await showLoading( - whileFuture: _attemptChangePW(), - context: context, - message: "Updating...", - rootNavigator: true, - ))!; - - if (mounted) { - unawaited( - showFloatingFlushBar( - type: type, - message: message, - context: context, - ), - ); - } - - if (didChangePW == true) { - setState(() { - changePassword = false; - }); - } - } finally { - _changePWLock = false; + + if (didChangePW == true) { + setState(() { + changePassword = false; + }); } - }, - ), - ], - ), - ) + } finally { + _changePWLock = false; + } + }, + ), + ], + ), + ) : PrimaryButton( - width: 210, - buttonHeight: ButtonHeight.m, - enabled: true, - label: "Set up new password", - onPressed: () { - setState(() { - changePassword = true; - }); - }, + width: 210, + buttonHeight: ButtonHeight.m, + enabled: true, + label: "Set up new password", + onPressed: () { + setState(() { + changePassword = true; + }); + }, + ), + + const Padding( + padding: EdgeInsets.all(10.0), + child: Divider(thickness: 0.5), + ), + + Consumer( + builder: (_, ref, __) { + final autoLockInfo = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.autoLockInfo, ), + ); + return Padding( + padding: const EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Auto lock timeout", + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ), + textAlign: TextAlign.left, + ), + Text( + autoLockInfo.enabled + ? "${autoLockInfo.minutes} minutes" + : "Disabled", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + ], + ), + PrimaryButton( + buttonHeight: ButtonHeight.xs, + label: "Edit", + width: 101, + onPressed: () async { + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const DesktopAutolockTimeoutSettingsDialog(); + }, + ); + }, + ), + ], + ), + ); + }, + ), ], ), ), diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 3266d1273..ee09bdba0 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -113,6 +113,7 @@ import 'pages/settings_views/global_settings_view/manage_nodes_views/add_edit_no import 'pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart'; import 'pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart'; import 'pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart'; +import 'pages/settings_views/global_settings_view/security_views/auto_lock_timeout_settings_view.dart'; import 'pages/settings_views/global_settings_view/security_views/change_pin_view/change_pin_view.dart'; import 'pages/settings_views/global_settings_view/security_views/create_duress_pin_view.dart'; import 'pages/settings_views/global_settings_view/security_views/security_view.dart'; @@ -997,6 +998,13 @@ class RouteGenerator { settings: RouteSettings(name: settings.name), ); + case AutoLockTimeoutSettingsView.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const AutoLockTimeoutSettingsView(), + settings: RouteSettings(name: settings.name), + ); + case BaseCurrencySettingsView.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, diff --git a/lib/utilities/idle_monitor.dart b/lib/utilities/idle_monitor.dart new file mode 100644 index 000000000..554f78c2a --- /dev/null +++ b/lib/utilities/idle_monitor.dart @@ -0,0 +1,73 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +class IdleMonitor with WidgetsBindingObserver { + final Duration timeout; + final VoidCallback onIdle; + + final WidgetsBinding binding = WidgetsBinding.instance; + + IdleMonitor({required this.timeout, required this.onIdle}); + + Timer? _idleTimer; + bool _isAttached = false; + void Function(PointerDataPacket)? _prevPointerHandler; + KeyEventCallback? _keyboardHandler; + + void attach() { + if (_isAttached) return; + _isAttached = true; + _resetTimer(); + _prevPointerHandler = binding.platformDispatcher.onPointerDataPacket; + binding.platformDispatcher.onPointerDataPacket = (packet) { + _onUserActivity(); + _prevPointerHandler?.call(packet); + }; + _keyboardHandler = (event) { + _onUserActivity(); + return false; + }; + binding.keyboard.addHandler(_keyboardHandler!); + binding.addObserver(this); + } + + void detach() { + if (!_isAttached) return; + _isAttached = false; + binding.platformDispatcher.onPointerDataPacket = _prevPointerHandler; + if (_keyboardHandler != null) { + binding.keyboard.removeHandler(_keyboardHandler!); + } + binding.removeObserver(this); + _cancelTimer(); + } + + void _onUserActivity() { + _resetTimer(); + } + + void _resetTimer() { + _cancelTimer(); + _idleTimer = Timer(timeout, onIdle); + } + + void _cancelTimer() { + _idleTimer?.cancel(); + _idleTimer = null; + } + + // @override + // void didChangeAppLifecycleState(AppLifecycleState state) { + // if (!_isAttached) return; + // if (state == AppLifecycleState.paused || + // state == AppLifecycleState.inactive || + // state == AppLifecycleState.detached) { + // _cancelTimer(); + // } else if (state == AppLifecycleState.resumed) { + // _resetTimer(); + // } + // } +} diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 087aaa631..09b2bbd97 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -26,6 +26,8 @@ import 'enums/backup_frequency_type.dart'; import 'enums/languages_enum.dart'; import 'enums/sync_type_enum.dart'; +typedef AutoLockInfo = ({bool enabled, int minutes}); + class Prefs extends ChangeNotifier { Prefs._(); static final Prefs _instance = Prefs._(); @@ -78,6 +80,7 @@ class Prefs extends ChangeNotifier { _advancedFiroFeatures = await _getAdvancedFiroFeatures(); _logsPath = await _getLogsPath(); _logLevel = await _getLogLevel(); + _autoLockInfo = await _getAutoLockInfo(); _initialized = true; } @@ -1347,4 +1350,37 @@ class Prefs extends ChangeNotifier { return Level.warning; } } + + // auto lock timeout + + AutoLockInfo _autoLockInfo = (enabled: false, minutes: 10); + + AutoLockInfo get autoLockInfo => _autoLockInfo; + + set autoLockInfo(AutoLockInfo autoLockInfo) { + if (_autoLockInfo != autoLockInfo) { + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "autoLockInfo", + value: { + "enabled": autoLockInfo.enabled, + "minutes": autoLockInfo.minutes, + }, + ); + _autoLockInfo = autoLockInfo; + notifyListeners(); + } + } + + Future _getAutoLockInfo() async { + final map = + await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "autoLockInfo", + ) + as Map? ?? + {"enabled": false, "minutes": 10}; + + return (enabled: map["enabled"] as bool, minutes: map["minutes"] as int); + } } From 7d71187a22723b82afe906bbff30223a1bc9c2c8 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 13:44:19 -0600 Subject: [PATCH 198/206] make desktop trade step 4 address copyable --- .../subwidgets/desktop_step_4.dart | 75 ++++++++-------- .../subwidgets/desktop_step_item.dart | 85 +++++++++++++------ 2 files changed, 101 insertions(+), 59 deletions(-) diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart index dd30adee2..6e18c5086 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart @@ -23,9 +23,7 @@ import '../step_scaffold.dart'; import 'desktop_step_item.dart'; class DesktopStep4 extends ConsumerStatefulWidget { - const DesktopStep4({ - super.key, - }); + const DesktopStep4({super.key}); @override ConsumerState createState() => _DesktopStep4State(); @@ -56,8 +54,9 @@ class _DesktopStep4State extends ConsumerState { return; } - final statusResponse = - await ref.read(efExchangeProvider).updateTrade(trade); + final statusResponse = await ref + .read(efExchangeProvider) + .updateTrade(trade); String status = "Waiting"; if (statusResponse.value != null) { status = statusResponse.value!.status; @@ -99,16 +98,12 @@ class _DesktopStep4State extends ConsumerState { "Send ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker.toUpperCase()))} to the address below", style: STextStyles.desktopTextMedium(context), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Text( "Send ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker.toUpperCase()))} to the address below. Once it is received, ${ref.watch(desktopExchangeModelProvider.select((value) => value!.trade?.exchangeName))} will send the ${ref.watch(desktopExchangeModelProvider.select((value) => value!.receiveTicker.toUpperCase()))} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", style: STextStyles.desktopTextExtraExtraSmall(context), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), RoundedContainer( color: Theme.of(context).extension()!.warningBackground, child: RichText( @@ -116,9 +111,10 @@ class _DesktopStep4State extends ConsumerState { text: "You must send at least ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendAmount.toString()))} ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker))}. ", style: STextStyles.label700(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of( + context, + ).extension()!.warningForeground, fontSize: 14, ), children: [ @@ -126,9 +122,10 @@ class _DesktopStep4State extends ConsumerState { text: "If you send less than ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendAmount.toString()))} ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker))}, your transaction may not be converted and it may not be refunded.", style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of( + context, + ).extension()!.warningForeground, fontSize: 14, ), ), @@ -136,9 +133,7 @@ class _DesktopStep4State extends ConsumerState { ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), RoundedWhiteContainer( borderColor: Theme.of(context).extension()!.background, padding: const EdgeInsets.all(0), @@ -146,11 +141,14 @@ class _DesktopStep4State extends ConsumerState { children: [ DesktopStepItem( vertical: true, + copyableValue: true, label: "Send ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker.toUpperCase()))} to this address", - value: ref.watch( - desktopExchangeModelProvider - .select((value) => value!.trade?.payInAddress), + value: + ref.watch( + desktopExchangeModelProvider.select( + (value) => value!.trade?.payInAddress, + ), ) ?? "Error", ), @@ -159,22 +157,26 @@ class _DesktopStep4State extends ConsumerState { color: Theme.of(context).extension()!.background, ), if (ref.watch( - desktopExchangeModelProvider - .select((value) => value!.trade?.payInExtraId), + desktopExchangeModelProvider.select( + (value) => value!.trade?.payInExtraId, + ), ) != null) DesktopStepItem( vertical: true, label: "Memo", - value: ref.watch( - desktopExchangeModelProvider - .select((value) => value!.trade?.payInExtraId), + value: + ref.watch( + desktopExchangeModelProvider.select( + (value) => value!.trade?.payInExtraId, + ), ) ?? "Error", ), if (ref.watch( - desktopExchangeModelProvider - .select((value) => value!.trade?.payInExtraId), + desktopExchangeModelProvider.select( + (value) => value!.trade?.payInExtraId, + ), ) != null) Container( @@ -192,9 +194,11 @@ class _DesktopStep4State extends ConsumerState { ), DesktopStepItem( label: "Trade ID", - value: ref.watch( - desktopExchangeModelProvider - .select((value) => value!.trade?.tradeId), + value: + ref.watch( + desktopExchangeModelProvider.select( + (value) => value!.trade?.tradeId, + ), ) ?? "Error", ), @@ -213,8 +217,9 @@ class _DesktopStep4State extends ConsumerState { ), Text( _statusString, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context) .extension()! .colorForStatus(_statusString), diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart index 352e353fb..6349350d1 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart @@ -13,6 +13,7 @@ import 'package:flutter/material.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../widgets/conditional_parent.dart'; +import '../../../../widgets/custom_buttons/simple_copy_button.dart'; class DesktopStepItem extends StatelessWidget { const DesktopStepItem({ @@ -21,12 +22,14 @@ class DesktopStepItem extends StatelessWidget { required this.value, this.padding = const EdgeInsets.all(16), this.vertical = false, + this.copyableValue = false, }); final String label; final String value; final EdgeInsets padding; final bool vertical; + final bool copyableValue; @override Widget build(BuildContext context) { @@ -34,35 +37,69 @@ class DesktopStepItem extends StatelessWidget { padding: padding, child: ConditionalParent( condition: vertical, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - const SizedBox( - height: 2, - ), - Text( - value, - style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context).extension()!.textDark, - ), + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: copyableValue, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [child, SimpleCopyButton(data: value)], + ), + child: child, + ), + const SizedBox(height: 2), + copyableValue + ? SelectableText( + value, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + ) + : Text( + value, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + ), + ], ), - ], - ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - label, - style: STextStyles.desktopTextExtraExtraSmall(context), - ), + Text(label, style: STextStyles.desktopTextExtraExtraSmall(context)), if (!vertical) - Text( - value, - style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context).extension()!.textDark, - ), - ), + copyableValue + ? SelectableText( + value, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context).extension()!.textDark, + ), + ) + : Text( + value, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context).extension()!.textDark, + ), + ), ], ), ), From 4b8db603b469f5e8410641d20553988cd6a4d703 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 13:51:42 -0600 Subject: [PATCH 199/206] all firo transactions are instant lock --- lib/wallets/wallet/impl/firo_wallet.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/wallets/wallet/impl/firo_wallet.dart b/lib/wallets/wallet/impl/firo_wallet.dart index a6f000e0a..0bb1b1fed 100644 --- a/lib/wallets/wallet/impl/firo_wallet.dart +++ b/lib/wallets/wallet/impl/firo_wallet.dart @@ -55,6 +55,20 @@ class FiroWallet extends Bip39HDWallet @override Future updateSentCachedTxData({required TxData txData}) async { if (txData.tempTx != null) { + final otherDataString = txData.tempTx!.otherData; + final Map map; + if (otherDataString == null) { + map = {}; + } else { + map = jsonDecode(otherDataString) as Map? ?? {}; + } + + map[TxV2OdKeys.isInstantLock] = true; + + txData = txData.copyWith( + tempTx: txData.tempTx!.copyWith(otherData: jsonEncode(map)), + ); + await mainDB.updateOrPutTransactionV2s([txData.tempTx!]); _unconfirmedTxids.add(txData.tempTx!.txid); Logging.instance.d("Added firo unconfirmed: ${txData.tempTx!.txid}"); From e7737d60beb3559a71f2114f1ea9ed2ba45172b5 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 30 Jul 2025 15:13:02 -0500 Subject: [PATCH 200/206] Revert "fix(macos): close mwebd on app close" This reverts commit 62c167c7266743722d26f0d578b5bc2a5e00a7d9. --- lib/main.dart | 32 -------- lib/services/mwebd_service.dart | 136 -------------------------------- 2 files changed, 168 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e05610a6d..3ffda4012 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -615,38 +615,6 @@ class _MaterialAppWithThemeState extends ConsumerState // } break; case AppLifecycleState.detached: - // Clean shutdown of mwebd service with aggressive timeout for macOS. - if (Platform.isMacOS) { - // On macOS, use very short timeout since native StopServer is skipped. - try { - debugPrint("App detached on macOS, quick shutdown..."); - await ref.read(pMwebService).shutdown().timeout( - const Duration(seconds: 2), - onTimeout: () { - debugPrint("MwebdService shutdown timed out after 2 seconds on macOS"); - exit(0); - }, - ); - debugPrint("MwebdService shutdown completed on macOS"); - } catch (e, s) { - debugPrint("Error during MwebdService shutdown on macOS: $e\n$s"); - exit(0); - } - } else { - // Non-macOS platforms can use longer timeout. - try { - debugPrint("App detached, shutting down MwebdService..."); - await ref.read(pMwebService).shutdown().timeout( - const Duration(seconds: 5), - onTimeout: () { - debugPrint("MwebdService shutdown timed out after 5 seconds"); - }, - ); - debugPrint("MwebdService shutdown completed successfully"); - } catch (e, s) { - debugPrint("Error during MwebdService shutdown: $e\n$s"); - } - } break; case AppLifecycleState.hidden: break; diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index 2d6e8604b..89f2bee37 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -34,9 +34,6 @@ final class MwebdService { final Mutex _torConnectingLock = Mutex(); - // Track active log stream controllers for cleanup during shutdown. - final Set> _activeLogControllers = {}; - static final instance = MwebdService._(); MwebdService._() { @@ -207,9 +204,6 @@ final class MwebdService { String leftover = ''; Timer? timer; - // Track this controller for cleanup during shutdown. - _activeLogControllers.add(controller); - final path = "${(await StackFileSystem.applicationMwebdDirectory(net == CryptoCurrencyNetwork.main ? "mainnet" : "testnet")).path}" "${Platform.pathSeparator}logs" @@ -243,141 +237,11 @@ final class MwebdService { controller.onCancel = () { timer?.cancel(); - _activeLogControllers.remove(controller); controller.close(); }; return controller.stream; } - - /// Shutdown all mwebd servers and clean up resources. - /// - /// This method should be called when the app is terminating to prevent hanging. - Future shutdown() async { - final stopwatch = Stopwatch()..start(); - Logging.instance.i("MwebdService shutdown() started"); - - await _updateLock.protect(() async { - // Cancel stream subscriptions to prevent further events. - try { - await _torStatusListener.cancel(); - Logging.instance.i("Canceled tor status listener"); - } catch (e, s) { - Logging.instance.w( - "Error canceling tor status listener", - error: e, - stackTrace: s, - ); - } - - try { - await _torPreferenceListener.cancel(); - Logging.instance.i("Canceled tor preference listener"); - } catch (e, s) { - Logging.instance.w( - "Error canceling tor preference listener", - error: e, - stackTrace: s, - ); - } - - // Cancel all active log stream controllers and their timers. - final logControllers = List.from(_activeLogControllers); - for (final controller in logControllers) { - try { - await controller.close(); - Logging.instance.i("Closed log stream controller"); - } catch (e, s) { - Logging.instance.w( - "Error closing log stream controller", - error: e, - stackTrace: s, - ); - } - } - _activeLogControllers.clear(); - - // Stop all servers and clean up clients with timeout protection. - final stopFutures = []; - for (final entry in _map.values) { - stopFutures.add(_shutdownServerSafely(entry)); - } - - // Wait for all shutdowns with overall timeout. - try { - await Future.wait(stopFutures).timeout( - const Duration(seconds: 10), - onTimeout: () { - Logging.instance.w("Timeout waiting for mwebd servers to stop"); - return []; // Return a dummy list. - }, - ); - } catch (e, s) { - Logging.instance.w( - "Error during mwebd servers shutdown", - error: e, - stackTrace: s, - ); - } - - _map.clear(); - - final elapsedMs = stopwatch.elapsedMilliseconds; - Logging.instance.i("MwebdService shutdown() completed in ${elapsedMs}ms"); - - // Warn if shutdown took too long (could indicate hanging). - if (elapsedMs > 3000) { - Logging.instance.w("MwebdService shutdown took ${elapsedMs}ms - longer than expected"); - } - }); - } - - /// Safely shutdown a server/client pair with timeout protection. - Future _shutdownServerSafely( - ({MwebdServer server, MwebClient client}) entry, - ) async { - final serverStopwatch = Stopwatch()..start(); - Logging.instance.i("Starting shutdown of mwebd server/client pair"); - - try { - // Clean up client first. - final clientStopwatch = Stopwatch()..start(); - await entry.client.cleanup().timeout( - const Duration(seconds: 3), - onTimeout: () { - Logging.instance.w("Timeout cleaning up mweb client after 3s"); - }, - ); - Logging.instance.i("Client cleanup completed in ${clientStopwatch.elapsedMilliseconds}ms"); - } catch (e, s) { - Logging.instance.w( - "Error cleaning up mweb client", - error: e, - stackTrace: s, - ); - } - - try { - // Stop server with timeout protection. - final serverShutdownStopwatch = Stopwatch()..start(); - await entry.server.stopServer().timeout( - const Duration(seconds: 5), - onTimeout: () { - Logging.instance.w("Timeout stopping mwebd server after 5s"); - }, - ); - Logging.instance.i("Server stop completed in ${serverShutdownStopwatch.elapsedMilliseconds}ms"); - } catch (e, s) { - Logging.instance.w( - "Error stopping mwebd server", - error: e, - stackTrace: s, - ); - } - - final totalMs = serverStopwatch.elapsedMilliseconds; - Logging.instance.i("Server/client pair shutdown completed in ${totalMs}ms"); - } } // ============================================================================ From 99f66cc1f982c78ceb4dd3a14ce33d910755bad8 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 30 Jul 2025 15:15:01 -0500 Subject: [PATCH 201/206] fix(macos): shutdown mwebd and force close app on app close request --- lib/main.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 3ffda4012..0eb4c224c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; +import 'dart:ui'; import 'package:coinlib_flutter/coinlib_flutter.dart'; import 'package:compat/compat.dart' as lib_monero_compat; @@ -621,6 +622,21 @@ class _MaterialAppWithThemeState extends ConsumerState } } + @override + Future didRequestAppExit() async { + debugPrint("didRequestAppExit called"); + if (Platform.isMacOS) { + // On macOS, mwebd fails to shut down, hanging the app on close. + // + // Exiting is a hack fix for this issue. + + // await ref.read(pMwebService).shutdown(); + // Something like the above would probably be prudent to make. + exit(0); + } + return AppExitResponse.exit; + } + /// should only be called on android currently Future getOpenFile() async { // update provider with new file content state From 671c1bb26eab9e0c3e7b31769289b582f8ca979a Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 14:55:48 -0600 Subject: [PATCH 202/206] clean up debug build log spam on startup a bit --- lib/services/mwebd_service.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index 89f2bee37..cc5e6bdc0 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -212,6 +212,11 @@ final class MwebdService { Future poll() async { if (!controller.isClosed) { final file = File(path); + + if (!file.existsSync()) { + return; + } + final length = await file.length(); if (length > offset) { From 1f44387313d73594a4a181cb6dd6845a347d2218 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 15:52:03 -0600 Subject: [PATCH 203/206] hack fix eth token image loading null error in incognito mode using a real fix to handle possible race condition on opening swap currencies db --- .../sub_widgets/add_token_list_element.dart | 47 +++++++---- .../sub_widgets/coin_select_item.dart | 83 ++++++++++++------- .../sub_widgets/expanding_sub_list_item.dart | 31 ++++--- .../exchange_currency_selection_view.dart | 3 +- lib/pages/wallet_view/wallet_view.dart | 5 +- .../exchange_data_loading_service.dart | 49 +++++++---- lib/widgets/icon_widgets/eth_token_icon.dart | 35 ++++++-- .../wallet_info_row_coin_icon.dart | 68 ++++++++++----- 8 files changed, 215 insertions(+), 106 deletions(-) diff --git a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart index 23035dc8e..9137e21f4 100644 --- a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart +++ b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart @@ -46,21 +46,40 @@ class AddTokenListElement extends ConsumerStatefulWidget { class _AddTokenListElementState extends ConsumerState { final bool isDesktop = Util.isDesktop; + Currency? currency; + @override - Widget build(BuildContext context) { - final currency = - ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - widget.data.token.address, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirstSync(); + void initState() { + super.initState(); + + ExchangeDataLoadingService.instance.isar.then((isar) async { + final currency = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + widget.data.token.address, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirst(); + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + this.currency = currency; + }); + } + }); + } + }); + } + + @override + Widget build(BuildContext context) { final String mainLabel = widget.data.token.name; final double iconSize = isDesktop ? 32 : 24; @@ -77,7 +96,7 @@ class _AddTokenListElementState extends ConsumerState { children: [ currency != null ? SvgPicture.network( - currency.image, + currency!.image, width: iconSize, height: iconSize, placeholderBuilder: diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart index 80acac3ed..2506b4195 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart @@ -28,39 +28,61 @@ import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; -class CoinSelectItem extends ConsumerWidget { +class CoinSelectItem extends ConsumerStatefulWidget { const CoinSelectItem({super.key, required this.entity}); final AddWalletListEntity entity; @override - Widget build(BuildContext context, WidgetRef ref) { - debugPrint("BUILD: CoinSelectItem for ${entity.name}"); - final selectedEntity = ref.watch(addWalletSelectedEntityStateProvider); + ConsumerState createState() => _CoinSelectItemState(); +} - final isDesktop = Util.isDesktop; +class _CoinSelectItemState extends ConsumerState { + String? tokenImageUri; - String? tokenImageUri; - if (entity is EthTokenEntity) { - final currency = - ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - (entity as EthTokenEntity).token.address, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirstSync(); - tokenImageUri = currency?.image; + @override + void initState() { + super.initState(); + + if (widget.entity is EthTokenEntity) { + ExchangeDataLoadingService.instance.isar.then((isar) async { + final currency = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + (widget.entity as EthTokenEntity).token.address, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirst(); + + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + tokenImageUri = currency?.image; + }); + } + }); + } + }); } + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: CoinSelectItem for ${widget.entity.name}"); + final selectedEntity = ref.watch(addWalletSelectedEntityStateProvider); + + final isDesktop = Util.isDesktop; return Container( decoration: BoxDecoration( color: - selectedEntity == entity + selectedEntity == widget.entity ? Theme.of(context).extension()!.textFieldActiveBG : Theme.of(context).extension()!.popupBG, borderRadius: BorderRadius.circular( @@ -68,7 +90,9 @@ class CoinSelectItem extends ConsumerWidget { ), ), child: MaterialButton( - key: Key("coinSelectItemButtonKey_${entity.name}${entity.ticker}"), + key: Key( + "coinSelectItemButtonKey_${widget.entity.name}${widget.entity.ticker}", + ), padding: isDesktop ? const EdgeInsets.only(left: 24) @@ -84,15 +108,17 @@ class CoinSelectItem extends ConsumerWidget { child: Row( children: [ tokenImageUri != null - ? SvgPicture.network(tokenImageUri, width: 26, height: 26) + ? SvgPicture.network(tokenImageUri!, width: 26, height: 26) : SvgPicture.file( - File(ref.watch(coinIconProvider(entity.cryptoCurrency))), + File( + ref.watch(coinIconProvider(widget.entity.cryptoCurrency)), + ), width: 26, height: 26, ), SizedBox(width: isDesktop ? 12 : 10), Text( - "${entity.name} (${entity.ticker})", + "${widget.entity.name} (${widget.entity.ticker})", style: isDesktop ? STextStyles.desktopTextMedium(context) @@ -100,8 +126,8 @@ class CoinSelectItem extends ConsumerWidget { context, ).copyWith(fontSize: 14), ), - if (isDesktop && selectedEntity == entity) const Spacer(), - if (isDesktop && selectedEntity == entity) + if (isDesktop && selectedEntity == widget.entity) const Spacer(), + if (isDesktop && selectedEntity == widget.entity) Padding( padding: const EdgeInsets.only(right: 18), child: SizedBox( @@ -120,7 +146,8 @@ class CoinSelectItem extends ConsumerWidget { ), ), onPressed: () { - ref.read(addWalletSelectedEntityStateProvider.state).state = entity; + ref.read(addWalletSelectedEntityStateProvider.state).state = + widget.entity; }, ), ); diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart index d934526b8..db55898d2 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/expanding_sub_list_item.dart @@ -30,7 +30,7 @@ class ExpandingSubListItem extends StatefulWidget { double? animationDurationMultiplier, this.curve = Curves.easeInOutCubicEmphasized, }) : animationDurationMultiplier = - animationDurationMultiplier ?? entities.length * 0.11; + animationDurationMultiplier ?? entities.length * 0.11; final String title; final List entities; @@ -85,23 +85,21 @@ class _ExpandingSubListItemState extends State { header: Container( color: Colors.transparent, child: Padding( - padding: const EdgeInsets.only( - top: 8.0, - bottom: 8.0, - right: 10, - ), + padding: const EdgeInsets.only(top: 8.0, bottom: 8.0, right: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( widget.title, - style: isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), RotateIcon( @@ -109,9 +107,10 @@ class _ExpandingSubListItemState extends State { Assets.svg.chevronDown, width: isDesktop ? 20 : 12, height: isDesktop ? 10 : 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), curve: widget.curve, animationDurationMultiplier: widget.animationDurationMultiplier, diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index ce861d560..edfe6ba19 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -100,8 +100,9 @@ class _ExchangeCurrencySelectionViewState Future> _loadCurrencies() async { await ExchangeDataLoadingService.instance.initDB(); + final isar = await ExchangeDataLoadingService.instance.isar; final currencies = - await ExchangeDataLoadingService.instance.isar.currencies + await isar.currencies .where() .filter() .isFiatEqualTo(false) diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 1bb76d59e..a479ae4eb 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -358,16 +358,17 @@ class _WalletViewState extends ConsumerState { ); } else { Future _future; + final isar = await ExchangeDataLoadingService.instance.isar; try { _future = - ExchangeDataLoadingService.instance.isar.currencies + isar.currencies .where() .tickerEqualToAnyExchangeNameName(coin.ticker) .findFirst(); } catch (_) { _future = ExchangeDataLoadingService.instance.loadAll().then( (_) => - ExchangeDataLoadingService.instance.isar.currencies + isar.currencies .where() .tickerEqualToAnyExchangeNameName(coin.ticker) .findFirst(), diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index 78fb0117f..35a167795 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -8,6 +8,8 @@ * */ +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; @@ -33,7 +35,10 @@ class ExchangeDataLoadingService { static ExchangeDataLoadingService get instance => _instance; Isar? _isar; - Isar get isar => _isar!; + Future get isar async { + if (_isar == null) await initDB(); + return _isar!; + } VoidCallback? onLoadingError; VoidCallback? onLoadingComplete; @@ -56,9 +61,16 @@ class ExchangeDataLoadingService { ); } + Completer? _initCompleter; Future initDB() async { if (_isar != null) return; - await _isar?.close(); + + if (_initCompleter != null) { + return await _initCompleter!.future; + } + + _initCompleter = Completer(); + _isar = await Isar.open( [ CurrencySchema, @@ -70,6 +82,8 @@ class ExchangeDataLoadingService { name: "exchange_cache", maxSizeMiB: 64, ); + + _initCompleter!.complete(); } Future setCurrenciesIfEmpty( @@ -77,7 +91,7 @@ class ExchangeDataLoadingService { ExchangeRateType rateType, ) async { if (pair?.send == null && pair?.receive == null) { - if (await isar.currencies.count() > 0) { + if (await (await isar).currencies.count() > 0) { pair?.setSend( await getAggregateCurrency( AppConfig.swapDefaults.from, @@ -108,9 +122,10 @@ class ExchangeDataLoadingService { String? contract, ) async { final List currencies; + if (contract != null) { currencies = - await ExchangeDataLoadingService.instance.isar.currencies + await (await isar).currencies .filter() .tokenContractEqualTo(contract) .and() @@ -129,7 +144,7 @@ class ExchangeDataLoadingService { .findAll(); } else { currencies = - await ExchangeDataLoadingService.instance.isar.currencies + await (await isar).currencies .filter() .group( (q) => @@ -232,15 +247,15 @@ class ExchangeDataLoadingService { final exchange = ChangeNowExchange.instance; final responseCurrencies = await exchange.getAllCurrencies(false); if (responseCurrencies.value != null) { - await isar.writeTxn(() async { + await (await isar).writeTxn(() async { final idsToDelete = - await isar.currencies + await (await isar).currencies .where() .exchangeNameEqualTo(ChangeNowExchange.exchangeName) .idProperty() .findAll(); - await isar.currencies.deleteAll(idsToDelete); - await isar.currencies.putAll(responseCurrencies.value!); + await (await isar).currencies.deleteAll(idsToDelete); + await (await isar).currencies.putAll(responseCurrencies.value!); }); } else { Logging.instance.w( @@ -389,15 +404,15 @@ class ExchangeDataLoadingService { final responseCurrencies = await exchange.getAllCurrencies(false); if (responseCurrencies.value != null) { - await isar.writeTxn(() async { + await (await isar).writeTxn(() async { final idsToDelete = - await isar.currencies + await (await isar).currencies .where() .exchangeNameEqualTo(TrocadorExchange.exchangeName) .idProperty() .findAll(); - await isar.currencies.deleteAll(idsToDelete); - await isar.currencies.putAll(responseCurrencies.value!); + await (await isar).currencies.deleteAll(idsToDelete); + await (await isar).currencies.putAll(responseCurrencies.value!); }); } else { Logging.instance.w("loadTrocadorCurrencies: $responseCurrencies"); @@ -413,15 +428,15 @@ class ExchangeDataLoadingService { ); if (responseCurrencies.value != null) { - await isar.writeTxn(() async { + await (await isar).writeTxn(() async { final idsToDelete = - await isar.currencies + await (await isar).currencies .where() .exchangeNameEqualTo(NanswapExchange.exchangeName) .idProperty() .findAll(); - await isar.currencies.deleteAll(idsToDelete); - await isar.currencies.putAll(responseCurrencies.value!); + await (await isar).currencies.deleteAll(idsToDelete); + await (await isar).currencies.putAll(responseCurrencies.value!); }); } else { Logging.instance.w("loadNanswapCurrencies: $responseCurrencies"); diff --git a/lib/widgets/icon_widgets/eth_token_icon.dart b/lib/widgets/icon_widgets/eth_token_icon.dart index 5908270f6..b837eeeb7 100644 --- a/lib/widgets/icon_widgets/eth_token_icon.dart +++ b/lib/widgets/icon_widgets/eth_token_icon.dart @@ -12,7 +12,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; + import '../../models/isar/exchange_cache/currency.dart'; +import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; import '../../themes/coin_icon_provider.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; @@ -32,17 +34,36 @@ class EthTokenIcon extends ConsumerStatefulWidget { } class _EthTokenIconState extends ConsumerState { - late final String? imageUrl; + String? imageUrl; @override void initState() { - imageUrl = ExchangeDataLoadingService.instance.isar.currencies - .where() - .filter() - .tokenContractEqualTo(widget.contractAddress, caseSensitive: false) - .findFirstSync() - ?.image; super.initState(); + + ExchangeDataLoadingService.instance.isar.then((isar) async { + final currency = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + widget.contractAddress, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirst(); + + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + imageUrl = currency?.image; + }); + } + }); + } + }); } @override diff --git a/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart b/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart index 74d91b33f..14783eb14 100644 --- a/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart +++ b/lib/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart @@ -23,7 +23,7 @@ import '../../../themes/theme_providers.dart'; import '../../../utilities/constants.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; -class WalletInfoCoinIcon extends ConsumerWidget { +class WalletInfoCoinIcon extends ConsumerStatefulWidget { const WalletInfoCoinIcon({ super.key, required this.coin, @@ -36,36 +36,62 @@ class WalletInfoCoinIcon extends ConsumerWidget { final double size; @override - Widget build(BuildContext context, WidgetRef ref) { - Currency? currency; - if (contractAddress != null) { - currency = - ExchangeDataLoadingService.instance.isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo(contractAddress!, caseSensitive: false) - .and() - .imageIsNotEmpty() - .findFirstSync(); - } + ConsumerState createState() => _WalletInfoCoinIconState(); +} + +class _WalletInfoCoinIconState extends ConsumerState { + String? imageUrl; + + @override + void initState() { + super.initState(); + ExchangeDataLoadingService.instance.isar.then((isar) async { + if (widget.contractAddress != null) { + final currency = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo( + widget.contractAddress!, + caseSensitive: false, + ) + .and() + .imageIsNotEmpty() + .findFirst(); + + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + imageUrl = currency?.image; + }); + } + }); + } + } + }); + } + + @override + Widget build(BuildContext context) { return Container( - width: size, - height: size, + width: widget.size, + height: widget.size, decoration: BoxDecoration( - color: ref.watch(pCoinColor(coin)).withOpacity(0.4), + color: ref.watch(pCoinColor(widget.coin)).withOpacity(0.4), borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), child: Padding( - padding: EdgeInsets.all(size / 5), + padding: EdgeInsets.all(widget.size / 5), child: - currency != null && currency.image.isNotEmpty - ? SvgPicture.network(currency.image, width: 20, height: 20) + imageUrl != null && imageUrl!.isNotEmpty + ? SvgPicture.network(imageUrl!, width: 20, height: 20) : SvgPicture.file( - File(ref.watch(coinIconProvider(coin))), + File(ref.watch(coinIconProvider(widget.coin))), width: 20, height: 20, ), From 7b7eaa801c5174fe76294aced8e614ac2a0271af Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 30 Jul 2025 16:30:47 -0600 Subject: [PATCH 204/206] allow send to cardano enterprise addresses --- .../crypto_currency/coins/cardano.dart | 16 ++++++++++- lib/wallets/wallet/impl/cardano_wallet.dart | 28 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/wallets/crypto_currency/coins/cardano.dart b/lib/wallets/crypto_currency/coins/cardano.dart index a59669eb7..ce7268176 100644 --- a/lib/wallets/crypto_currency/coins/cardano.dart +++ b/lib/wallets/crypto_currency/coins/cardano.dart @@ -1,3 +1,6 @@ +import 'package:blockchain_utils/bip/address/ada/ada.dart'; +import 'package:on_chain/ada/ada.dart'; + import '../../../models/isar/models/blockchain_data/address.dart'; import '../../../models/node_model.dart'; import '../../../utilities/default_nodes.dart'; @@ -123,7 +126,18 @@ class Cardano extends Bip39Currency { bool validateAddress(String address) { switch (network) { case CryptoCurrencyNetwork.main: - return RegExp(r"^addr1[0-9a-zA-Z]{98}$").hasMatch(address); + try { + final adaAddress = ADAAddress.fromAddress( + address, + network: ADANetwork.mainnet, + ); + + return (adaAddress is ADABaseAddress || + adaAddress is ADAEnterpriseAddress); + } catch (_) { + return false; + } + default: throw Exception("Unsupported network: $network"); } diff --git a/lib/wallets/wallet/impl/cardano_wallet.dart b/lib/wallets/wallet/impl/cardano_wallet.dart index 3909c5b4b..5ae2d14a6 100644 --- a/lib/wallets/wallet/impl/cardano_wallet.dart +++ b/lib/wallets/wallet/impl/cardano_wallet.dart @@ -202,6 +202,17 @@ class CardanoWallet extends Bip39Wallet { address: ADABaseAddress((await getCurrentReceivingAddress())!.value), amount: Value(coin: totalBalance - (txData.amount!.raw)), ); + + final outputAddress = ADAAddress.fromAddress( + txData.recipients!.first.address, + ); + if (!(outputAddress is ADABaseAddress || + outputAddress is ADAEnterpriseAddress)) { + throw Exception( + "Address of type ${outputAddress.runtimeType} currently not supported.", + ); + } + final body = TransactionBody( inputs: listOfUtxosToBeUsed @@ -215,7 +226,7 @@ class CardanoWallet extends Bip39Wallet { outputs: [ change, TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), + address: outputAddress, amount: Value(coin: txData.amount!.raw - exampleFee), ), ], @@ -323,11 +334,22 @@ class CardanoWallet extends Bip39Wallet { coin: totalUtxoAmount - (txData.amount!.raw + txData.fee!.raw), ), ); + + final outputAddress = ADAAddress.fromAddress( + txData.recipients!.first.address, + ); + if (!(outputAddress is ADABaseAddress || + outputAddress is ADAEnterpriseAddress)) { + throw Exception( + "Address of type ${outputAddress.runtimeType} currently not supported.", + ); + } + List outputs = []; if (totalBalance == (txData.amount!.raw + txData.fee!.raw)) { outputs = [ TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), + address: outputAddress, amount: Value(coin: txData.amount!.raw), ), ]; @@ -335,7 +357,7 @@ class CardanoWallet extends Bip39Wallet { outputs = [ change, TransactionOutput( - address: ADABaseAddress(txData.recipients!.first.address), + address: outputAddress, amount: Value(coin: txData.amount!.raw), ), ]; From 296581094d0769f306ccc9a92d5d869e5fbb03ea Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 31 Jul 2025 13:16:08 -0600 Subject: [PATCH 205/206] Disable send from stack option for swaps where the wallet is required to be open and/or fully synced. Users will need to manually go into the wallet and send from there. --- .../exchange_step_views/step_4_view.dart | 35 ++++++--- .../exchange_view/trade_details_view.dart | 33 ++++++-- .../exchange_steps/step_scaffold.dart | 76 ++++++++++++++----- 3 files changed, 108 insertions(+), 36 deletions(-) diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index d244ded98..973298bd6 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -21,6 +21,7 @@ import '../../../models/exchange/incomplete_exchange.dart'; import '../../../notifications/show_flush_bar.dart'; import '../../../providers/providers.dart'; import '../../../route_generator.dart'; +import '../../../services/wallets.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount_formatter.dart'; @@ -34,6 +35,8 @@ import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../wallets/models/tx_data.dart'; import '../../../wallets/wallet/impl/firo_wallet.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; +import '../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../widgets/background.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/desktop/secondary_button.dart'; @@ -65,6 +68,7 @@ class Step4View extends ConsumerStatefulWidget { } class _Step4ViewState extends ConsumerState { + late final bool isWalletCoinAndCanSend; late final IncompleteExchangeModel model; late final ClipboardInterface clipboard; @@ -72,13 +76,20 @@ class _Step4ViewState extends ConsumerState { Timer? _statusTimer; - bool _isWalletCoinAndHasWallet(String ticker, WidgetRef ref) { + bool isWalletCoinAndCanSendWithoutWalletOpened( + String ticker, + Wallets walletsInstance, + ) { try { final coin = AppConfig.getCryptoCurrencyForTicker(ticker); - return ref - .read(pWallets) - .wallets - .where((e) => e.info.coin == coin) + return walletsInstance.wallets + .where( + (e) => + e.info.coin == coin && + (e is! ExternalWallet || + e is MwebInterface), // ltc mweb is external but swaps + // should not use mweb, hence the odd logic check here + ) .isNotEmpty; } catch (_) { return false; @@ -111,6 +122,11 @@ class _Step4ViewState extends ConsumerState { model = widget.model; clipboard = widget.clipboard; + isWalletCoinAndCanSend = isWalletCoinAndCanSendWithoutWalletOpened( + model.trade!.payInCurrency, + ref.read(pWallets), + ); + _statusTimer = Timer.periodic(const Duration(seconds: 60), (_) { _updateStatus(); }); @@ -339,10 +355,6 @@ class _Step4ViewState extends ConsumerState { @override Widget build(BuildContext context) { - final bool isWalletCoin = _isWalletCoinAndHasWallet( - model.trade!.payInCurrency, - ref, - ); return WillPopScope( onWillPop: () async { await _close(); @@ -791,8 +803,9 @@ class _Step4ViewState extends ConsumerState { style: STextStyles.button(context), ), ), - if (isWalletCoin) const SizedBox(height: 12), - if (isWalletCoin) + if (isWalletCoinAndCanSend) + const SizedBox(height: 12), + if (isWalletCoinAndCanSend) Builder( builder: (context) { String buttonTitle = diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 329f1d572..6e56e5755 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -32,6 +32,7 @@ import '../../services/exchange/exchange.dart'; import '../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../services/exchange/simpleswap/simpleswap_exchange.dart'; import '../../services/exchange/trocador/trocador_exchange.dart'; +import '../../services/wallets.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; import '../../utilities/amount/amount.dart'; @@ -43,6 +44,8 @@ import '../../utilities/format.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; +import '../../wallets/wallet/intermediate/external_wallet.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -152,6 +155,26 @@ class _TradeDetailsViewState extends ConsumerState { } } + bool isWalletCoinAndCanSendWithoutWalletOpened( + String ticker, + Wallets walletsInstance, + ) { + try { + final coin = AppConfig.getCryptoCurrencyForTicker(ticker); + return walletsInstance.wallets + .where( + (e) => + e.info.coin == coin && + (e is! ExternalWallet || + e is MwebInterface), // ltc mweb is external but swaps + // should not use mweb, hence the odd logic check here + ) + .isNotEmpty; + } catch (_) { + return false; + } + } + @override Widget build(BuildContext context) { final bool sentFromStack = @@ -193,13 +216,11 @@ class _TradeDetailsViewState extends ConsumerState { final showSendFromStackButton = !hasTx && - ![ - "xmr", - "monero", - "wow", - "wownero", - ].contains(trade.payInCurrency.toLowerCase()) && AppConfig.isStackCoin(trade.payInCurrency) && + isWalletCoinAndCanSendWithoutWalletOpened( + trade.payInCurrency, + ref.read(pWallets), + ) && (trade.status == "New" || trade.status == "new" || trade.status == "waiting" || diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart index 606d9fa68..23e925c0c 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart @@ -20,14 +20,18 @@ import '../../../models/exchange/response_objects/trade.dart'; import '../../../pages/exchange_view/send_from_view.dart'; import '../../../providers/exchange/exchange_form_state_provider.dart'; import '../../../providers/global/trades_service_provider.dart'; +import '../../../providers/global/wallets_provider.dart'; import '../../../route_generator.dart'; import '../../../services/exchange/exchange_response.dart'; import '../../../services/notifications_api.dart'; +import '../../../services/wallets.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/enums/exchange_rate_type_enum.dart'; import '../../../utilities/text_styles.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; +import '../../../wallets/wallet/wallet_mixin_interfaces/mweb_interface.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_loading_overlay.dart'; import '../../../widgets/desktop/desktop_dialog.dart'; @@ -241,6 +245,26 @@ class _StepScaffoldState extends ConsumerState { ); } + bool isWalletCoinAndCanSendWithoutWalletOpened( + String ticker, + Wallets walletsInstance, + ) { + try { + final coin = AppConfig.getCryptoCurrencyForTicker(ticker); + return walletsInstance.wallets + .where( + (e) => + e.info.coin == coin && + (e is! ExternalWallet || + e is MwebInterface), // ltc mweb is external but swaps + // should not use mweb, hence the odd logic check here + ) + .isNotEmpty; + } catch (_) { + return false; + } + } + @override void initState() { duration = const Duration(milliseconds: 250); @@ -251,6 +275,18 @@ class _StepScaffoldState extends ConsumerState { @override Widget build(BuildContext context) { final model = ref.watch(desktopExchangeModelProvider); + + final bool canSendFromStack; + if (currentStep != 4) { + // set to true anyways to show back button + canSendFromStack = true; + } else { + canSendFromStack = isWalletCoinAndCanSendWithoutWalletOpened( + model?.sendTicker ?? "", + ref.read(pWallets), + ); + } + return Column( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -307,25 +343,27 @@ class _StepScaffoldState extends ConsumerState { ), child: Row( children: [ - Expanded( - child: AnimatedCrossFade( - duration: const Duration(milliseconds: 250), - crossFadeState: - currentStep == 4 - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, - firstChild: SecondaryButton( - label: "Back", - buttonHeight: ButtonHeight.l, - onPressed: onBack, - ), - secondChild: SecondaryButton( - label: "Send from ${AppConfig.appName}", - buttonHeight: ButtonHeight.l, - onPressed: sendFromStack, - ), - ), - ), + canSendFromStack + ? Expanded( + child: AnimatedCrossFade( + duration: const Duration(milliseconds: 250), + crossFadeState: + currentStep == 4 + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + firstChild: SecondaryButton( + label: "Back", + buttonHeight: ButtonHeight.l, + onPressed: onBack, + ), + secondChild: SecondaryButton( + label: "Send from ${AppConfig.appName}", + buttonHeight: ButtonHeight.l, + onPressed: sendFromStack, + ), + ), + ) + : const Spacer(), const SizedBox(width: 16), Expanded( child: AnimatedCrossFade( From 22c1e04d0127fe9e3addba18fb4be85dd4c657ee Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 31 Jul 2025 13:51:44 -0600 Subject: [PATCH 206/206] Provide option on desktop baddecryption error to still continue with wallet deletion --- .../desktop_attention_delete_wallet.dart | 250 ++++++++++++------ 1 file changed, 167 insertions(+), 83 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart index 16032b36b..032a61bf4 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart @@ -10,12 +10,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stack_wallet_backup/secure_storage.dart'; import 'package:tuple/tuple.dart'; import '../../../../app_config.dart'; import '../../../../pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_view_only_wallet_keys_view.dart'; import '../../../../providers/global/wallets_provider.dart'; +import '../../../../route_generator.dart'; import '../../../../themes/stack_colors.dart'; +import '../../../../utilities/logger.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -24,13 +27,11 @@ import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/rounded_container.dart'; +import '../../../../widgets/rounded_white_container.dart'; import 'delete_wallet_keys_popup.dart'; class DesktopAttentionDeleteWallet extends ConsumerStatefulWidget { - const DesktopAttentionDeleteWallet({ - super.key, - required this.walletId, - }); + const DesktopAttentionDeleteWallet({super.key, required this.walletId}); final String walletId; @@ -55,10 +56,7 @@ class _DesktopAttentionDeleteWallet children: [ DesktopDialogCloseButton( onPressedOverride: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); }, ), ], @@ -67,17 +65,13 @@ class _DesktopAttentionDeleteWallet padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26), child: Column( children: [ - Text( - "Attention!", - style: STextStyles.desktopH2(context), - ), - const SizedBox( - height: 16, - ), + Text("Attention!", style: STextStyles.desktopH2(context)), + const SizedBox(height: 16), RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackError, + color: + Theme.of( + context, + ).extension()!.snackBarBackError, child: Padding( padding: const EdgeInsets.all(10.0), child: Text( @@ -85,11 +79,13 @@ class _DesktopAttentionDeleteWallet "the only way you can have access to your funds is by using your backup key." "\n\n${AppConfig.appName} does not keep nor is able to restore your backup key or your wallet." "\n\nPLEASE SAVE YOUR BACKUP KEY.", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextError, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.snackBarTextError, ), ), ), @@ -103,10 +99,7 @@ class _DesktopAttentionDeleteWallet buttonHeight: ButtonHeight.xl, label: "Cancel", onPressed: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(); + Navigator.of(context, rootNavigator: true).pop(); }, ), const SizedBox(width: 16), @@ -115,71 +108,96 @@ class _DesktopAttentionDeleteWallet buttonHeight: ButtonHeight.xl, label: "View Backup Key", onPressed: () async { - final wallet = - ref.read(pWallets).getWallet(widget.walletId); + try { + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); - if (wallet is ViewOnlyOptionInterface && - wallet.isViewOnly) { - final data = await wallet.getViewOnlyWalletData(); - if (context.mounted) { - await Navigator.of(context).push( - MaterialPageRoute( - builder: (builder) => DesktopDialog( - maxWidth: 614, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, + if (wallet is ViewOnlyOptionInterface && + wallet.isViewOnly) { + final data = await wallet.getViewOnlyWalletData(); + if (context.mounted) { + await Navigator.of(context).push( + MaterialPageRoute( + builder: + (builder) => DesktopDialog( + maxWidth: 614, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.only( + left: 32, + ), + child: Text( + "Wallet keys", + style: + STextStyles.desktopH3( + context, + ), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: () { + Navigator.of( + context, + rootNavigator: true, + ).pop(); + }, + ), + ], ), - child: Text( - "Wallet keys", - style: STextStyles.desktopH3( - context, - ), + Padding( + padding: const EdgeInsets.all(32), + child: + DeleteViewOnlyWalletKeysView( + walletId: widget.walletId, + data: data, + ), ), - ), - DesktopDialogCloseButton( - onPressedOverride: () { - Navigator.of( - context, - rootNavigator: true, - ).pop(); - }, - ), - ], - ), - Padding( - padding: const EdgeInsets.all(32), - child: DeleteViewOnlyWalletKeysView( - walletId: widget.walletId, - data: data, + ], ), ), - ], - ), ), - ), - ); - } - } else + ); + } + } else + // TODO: [prio=med] handle other types wallet deletion + // All wallets currently are mnemonic based + if (wallet is MnemonicInterface) { + final words = await wallet.getMnemonicAsWords(); - // TODO: [prio=med] handle other types wallet deletion - // All wallets currently are mnemonic based - if (wallet is MnemonicInterface) { - final words = await wallet.getMnemonicAsWords(); + if (context.mounted) { + await Navigator.of(context).pushNamed( + DeleteWalletKeysPopup.routeName, + arguments: Tuple2(widget.walletId, words), + ); + } + } + } on BadDecryption catch (e, s) { + Logging.instance.f( + "Desktop wallet delete error. Showing decryption error continue dialog.", + error: e, + stackTrace: s, + ); if (context.mounted) { - await Navigator.of(context).pushNamed( - DeleteWalletKeysPopup.routeName, - arguments: Tuple2( - widget.walletId, - words, + await Navigator.of(context).push( + RouteGenerator.getRoute( + builder: (context) { + return ErrorLoadingKeysDialog( + walletId: widget.walletId, + ); + }, + settings: const RouteSettings( + name: "/desktopErrorLoadingKeysDialog", + ), ), ); } @@ -196,3 +214,69 @@ class _DesktopAttentionDeleteWallet ); } } + +class ErrorLoadingKeysDialog extends StatelessWidget { + const ErrorLoadingKeysDialog({super.key, required this.walletId}); + + final String walletId; + + @override + Widget build(BuildContext context) { + return DesktopDialog( + maxWidth: 614, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Decryption error", + style: STextStyles.desktopH3(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + ), + ], + ), + Padding( + padding: const EdgeInsets.all(32), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Text( + "Could not retrieve wallet keys/mnemonic phrase/seed.\n\n" + "Are you certain you would like to continue with wallet deletion?", + style: STextStyles.label(context).copyWith(fontSize: 16), + ), + ), + const SizedBox(height: 40), + PrimaryButton( + label: "Continue", + onPressed: () async { + await Navigator.of(context).push( + RouteGenerator.getRoute( + builder: (context) { + return ConfirmDelete(walletId: walletId); + }, + settings: const RouteSettings( + name: "/desktopConfirmDelete", + ), + ), + ); + }, + ), + ], + ), + ), + ], + ), + ); + } +}

      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ఞ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%0A{b*LUw17QtfA{1P(88s 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%0DGbAa@f2Oq2<~vE$AdAKm6mq10jlT%ZJB6 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�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.VX~*IfvhrFDG|m>)CW&_3@t;v;Vz!`D0$2 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�O8Dvy4_~Tcv z=vSv7OK_XcvE!5c?mPRe?<}G3-*<|0|H#Z{OlyFY&JHmnzM%?K*sL;s^cIlj6h*_p z_ft|Fk(ZAF>M?sA6)3|FHG6#E#>u0UNezcOtvQ(D&FAtiHZJMmPj1(iyyv)^g8B#` zN}-V)?spz5tL!&XThQ?4LXH4n`+T`QGr(ap>_IQP=ET+`F{QzaGh?}Xp<)uV^QW8J zF8Y~2c->q1{d_K{ev9E*oXruM_k`;GjZS{yr6&qlc3xqh9{5(S&*d(JobX&}&Tv== z%y5rpGguH?f*kAOJ#BI(AM*Z5+8hupV7PQFulbnf)P4f4Uo#G7n<6@>nZ0DVTt z=&QKh`s=|3_DhU|g=O0ZW_$@IE4J%Asq0xkeC|P8k8l;C0Kzks-+R#7*M&zjM2dQ3 zKFunGNIoryW54TbH7w%@xEVwpLdll}#%yqChBx6)t#30lMC zc=8+nOZ#`tY1n7UvTs$NZ`(4nCw(WMMiRG~PgF7hKN@pi!_PMPCyIl*%6_n!hHh(b zq+E}x#)--B6TW#9U(w?CzW+8FS0SJpxAOZG*`{!GqDlmw#Xk@4mIE5*314vUzqjqj zmA1gBLowdAWc5ng@nj9+ZQZ#MCZFN(FH81kBUaTX@4ek2~ z*_&OSw5seQzUph^A3p$nWUE3Mi}dxr$X;C61uL6pJwvXOPx$y&*w|F~h{sPDJCX`R#o za;Y(>>?+U`s4&hX6b)#8I!Ot-f!Ri?Rb2P476H}et?pSY^V7vLS8m(75-$w%q=OG< zg?e&Fdjnk7W?y<|5h`Lv5|aYDPTn1gC-62<-6mUFy5l{LV}2GtGH4N@C`ZF|jx0 ztw07Bsoh1x$+n0l^6Z1w9S=sVV9q;;BE}PO@tbblUtz#9fnoS;v4fa;dDmXU`M?^#CE2TP$j%tc{5|Pf~Cp66r&rQrh@^xe`G#MlC+HvT=&iex3h#; zv0QAk&mGS8W$8BN85U`TbHi|{w3_?YeE80ehkJ~j(3ehSoQ@n)rIU_(ZKp3t7RT{5O& zQ&=qOy`e927WjB^Fd_w^{0iSCshDzsF9%d3-bVW%To?@Ff519N@y%{;GnIjEiS z1bvk~|HGY@Dfq(GaCh*Xl9mPV+RByh)-p2ifgjd+hs>#;2>JeUj5s!XawLYQi?3y9CmPfbv~zm+fjoTx9>wm0SMD->P%DPDYts`MP1qhVF4lz}j(i!5 zSW-N&;;eN+?qP&yE7V?MPgv*Z>~6!zr-_@8|7*l8!R*l;}6>dU#R@`rPh&@PoJ#{_O;f^s0z z`_h`miNF04kuY2(sMq4FwV&rmLNwifualRR$Ql!xcfahzbSg(7@ucq~>EXw_m$;kz zLAe7#B;^RRmuQ)e>OW{R07lUS2=*%M_t(FQoP@;ta*E@>!ksggmR(Ov3rRcA9nY=n z#YeOYWzGkM$f8`{C%iwh=l~+;@$$jtGfuu6-H8wjrc{cg2>~4@T_T$dGzp z>A1;`SrJ#R$3a-$5d^-ld-xQq+aw=a2h5bXO9{Unm!GwEJWfwLEv3gW$uZ5TU!su5 zO%r0)Ev@v`LO?mbelpLc^3*h{o>MBDo`3L3 zebXPBXiAS9Q%pHdRraOq9G69aKTNXn+L!ak_e-39vNa878mZ2SymWgul5SJQps@jZ zxAnFkoaJ1GJR~el(Z3p)%c{6%G^jX@;c7kJ@Ttgxb8cHn955|0n z#26=MlxZd$-TmtU6YjZy=>3?p`jtZ0H9H?awZIE(s-@$}zc_3{wvy0H&-`iI`^H9% z=^bd0vSE)(a_BM%5zsj9KA+nMq2Bi-_}_LC`A_f$*gD*v(wT$ui2AVfAcyZhX@&Z=hHTNOsT zM^xEpd%E=i*Xi;ys!CHr5W^7j_d({LcHT)F@sZ+8)LCi|wGAmrheS=nRadQg>*#6< z@rF0nS%D8866~;T*=GU!y-zKEJAe9_!YqcNO(@_s+nip*8?HW&QJ;?VMT{S@~B`+9q|#ns}tS1TpmdXQW6RjzxR4JjYiTq=+_@6|)T!#@2VwxsJwleNzf zy7rQfzuzQ20?)yGCcdm_6fxC)iMye>IafulVEfAZiFXA?R#MY>Bhr2$|1mW>r?w6A zSvDxX(ljl?GCfdTcmVHwgLn?#vts>aH$A=omBCwd`MzcCH(DMYcU2wGCs3f)=b?NY zK;9@I4ShXL?@flhZ?Ghr^xqnQzRoYk5G{Ggo67oX$m_g);y6y0 zK_IsW1)Sut>Za+Dm&E?QVRhQhJdUWn{0Mh$ci})jU5F*W2u0^`THh~yU&1q{yZwa3 z02g!-qS~6~(0eYoTKTOuhAhk}Ndf-0Xyrt;1AF@SgTY4_)x`Z$3neWZa6aqJ^weDY zp6|Te(Y+HP?JA?Xrg^)Lzl=&ZvgSs!jrFH<=kf@un$g^E@GwR%c<6Oicdl_J7-&Iwe%R}=89%7+{Yds0R zbu@rC-=t$%H_vhDVQefAY^DFayQZqYG@lWi$w+*crS?6Xu2Dy^F-+l}Ub@q81o!1> zkFD{0{q5G}vA=s7dbA4XIX+w&ou`-RDk?BU=fSLl0oIo}5|xO2a^oH%-QmM$on(2dlB9ppaiI~G@jzh53i zdSy!o@&fw=AlAD62H_*NYBhPjDk}F~0=N5YL_HNO&09`w0(Ddao^q*2@Uj)I)^p&! z1@SM2tXHPQR{{-H=5wUz0C0hRJYfB*qR-UzqzUhU|AlKj6qf*MY@OoVu~y`D6z++B zWu6D?1w>Cdc{y;hRTaNZZs1yUrcm^~MhDGovkqiEtl4ZmDv+JK+3)2zFb;IH?H!X? z-*@Mn)KK7m66TA1F#OMBr$}XG(T3~7J#f764_WrqNBS6G_#;V7TE!ER^e>m}=Mok; zj;u_zGKs?O++Zvu9H!wrUev_w6!4i+K~8?p<#X3Ydb$$_@z#FN==l!2;T;5#I%jBn zMC;D;gTAgV^3P#%y!h9Xdhc7xcQ`OdWkizDf3|x(qho;77e_rF59}MWU$>-N(bb36 z6pDg@ioC_@HWfq}7Xi>;Pe}ZXrZ-OrNmm&e4Y51&>?Ymn% zv2WcJTB6pWCbAX|RU}9BXKMM4EFUUH+&PF(SWMg!2dHTFw%Y+MX99}P_U>7gzKOG6 zc^G-K+xcC3@!yM5umpKAi8*>XqPx$w+Xamsp1)idfjPaTil*HB&acTbdm;c@{(#1P zKr+1;zS?vC7=yL3PAo&9M%|x1?QWf-)%Sc(eShF9({XP2T{Kq~R?PUkDGY{JIA?<{ zQZ@5>RoGK}I3|$O%kMY7(|a~gUZ*bp9U)C<^3+$)A<$fHC%E>k)&=7yLk8LdDl_S|#@xVXcf%0VjoD}tgLVt<@!GV0 zycU0g_oN%o9$0perdR>P&l3xxPD%X1LW{p`u<>t{3Jcr4L(i^E0|Wuc`^^g zlKpF!P;FWi71O^u5Kisl8DX{nDvJR(TlBdti)QL+QnE`rfi*BhCL88DZs8;O#RtNC zUlBOPe1LB5EE@CnQ$Ma>|Aad(Q0|?;6>(SBZvOU^^(%XK&hf#!^PQhRmpe{kgp6WX zk{*kl_WD&jzN6;T zyo>*7_^VMsSn#T}>q|7pXUAr|(gObC>WzDa*5EcS_4}n13UtZ`-nOco91*8Hm0^K6 zDuVT8L)k`>)7piP{pG2zTkpA}47;PK=tuB65Bf|^8r3C#Ge2=vzDj|-sUYYD_IdgS zgKZDek_Xd1TX_X4i9utxpB%d2@4Ky5e%psIW*?y_3k>5nluDPMOT;)mviJMR2_Kv% z1rh#ZwY5|)MO%)@;qDVlSo+X4BHM~Vy}?*~&oq4J%{k1StGzx{$EIVMMx6qaN3wpr z@B0;#aa|QW2Q&@MRfGZGOtsj}a zn+-(zhcNs}9L1)_i|ChLmMpL}KRJ&bEFHm>3sH&!t=pO&-OXR%-hMGp;5KxZrpRyT zFW7TJ^v}Dle=DyKvE~0n9Ek8REQ%pkmz{sSeXy(V`#Ga`7Pf=FngfoPk|l}%iB)lk z3<{?6Z4U?h)u_B67>Ad1m7-XgNbh5e-k#*GZ0j22;=7fa`JHubF5GdL5^sC*&eg-o z_qgbzU*}|DlX(KTW5yI9&BLJl9%$>8eB0j5qMv2y2evGz1K{wWlhK5P{GB>}|u65bXG46|lwJE@Y{R;2t50SO2c~!mZ(JepkzC|8t3NQl}z;8hB zSanSFQWS-=w(lz}UjICfhJGB|_N#&Dn+VC81E(()@S1h^T63Xqc>QsrvY+j`$)Z|( z46zpG4!=SXmFIAL}2WAP-|4*aO#Y9&|}10}B| zn#!UO;0mZcvg|E$)ayHc*|M`IL@W;}Y;Y00*MlSLx+ozvFeEySlceY@Lk+b2kOTjESMfSb^Xv*Mw zuLq>|>2F>}x4PSb!~uBA8r_^*4{DL(*Fxn~w{8#Djt5V!si~v1yM5Ot?at^154A4c z+SQSXVOWm~nv<9w?eop+41m=TOi{Hp z^q8;go|(I*eK8vkz55C6ku1;Tji$fTwrw3i_|ysHzdQ(EG4KA+#c#D`S$|eC46F-= z=tLlRnOb`~pU8K7ghY0|97~|diOQ$d<(vhWVI=3C7cP4y`m%DQs$e7>Y;$RPX}SBj zVc>XIlJtxRjr`L<=*Qk*@NAcXh;fx=&kBh5+>xHS!^b8fBeW=Y;Y0|?ZY{_opdCaF zdWc;Ik;#3l^Xfz0dO>GY50YTkbPnKmzTua5!r%Xm^MniO3cpyc0za*~fqjkk)8F~r zDGs3$FouEw#9mf1V{t;`?t5JKMac0_3+9kc zb?@w-&fk7C#J3zc48?UmE>N#mS)|K^X5P}y==TLQi^In7^6J$({XwPjq=#=P*}N$< z1O+>N`2b@6Nl&RgZ;n8%e+FOYl&?yQG9;SLJI;48Po#hqd1lT#pq#VK^kHW+|h*1wLwb! ziyYJZ?aR7&zwFx4`_$)1K?FyJDe)= zcwfMK05zUz)bGg)Zq4Z+U6y5z~X&d2zp5d4c>TwMp>oJMnmY`h%?`yGWP8>+=Fznm%mP| zt<4@8F`&w2Zg)OMwS|WNKX(EpVHm&x6TaG=SP9Nia^ACR1G;7=tZzjAo-kLgRCv!& zEG>lD#o0x~{dKH~)Zz}5R$}+y|L(K*IXeuBqMDTn7QG(->6VllimJ*&KuVisEt^?6 zfO}2_o9&n68oN75D>lD#kut!R+$8_GjAB>wk1(gk1Q=K2@htmy?Y)JA_-&sGhLI{m z$(JSf{u~(7R{rN*D($|y9}Go0SmxOG9kVv&bGa*#f`4!&udpngr0i!-4tZJkMR*@x zQ9aF1pRUx5yneAa6qC9C#J@T{&--u!V4qhc-P)D?ofwQO%H`56ih*a%a@KkM?z-g) zKt13y!J#GVU1HZ;3l6L0nCqBHioqY5byB9Wgs9{;^j!zfy|u+U8NlmdECtm_pxPh* zuu<}Gl2zwX>h60kkH?(iM;>`v@(5R&~YktC|M!>;#y65<2d zC`ppk5dg71M*=Uh6!1EHGL-J=je72`M4uNl~=e6RW(d@0${>LiW(W7e)6pUnBXo zfV1|%-f{`{Ro1~-*d1>3pctxn?`8NT_vDKjjF;T|yF~AP?HG_(*Ne#(6qhIoDfmPh zMW4knGNjQ-2KXSXSZs+xu-{8IYVy+N+~v#S4&L+`1vACw zblpY2$a&G*X60(vRKCkD*j{cs@U?er@fUk|(~%*eCB0$EPr=0*91;JGSKVFG3~SgU zEAE;id)p-|1NIA{9;iXQh@ZLq^jV)sao0KZ!OE%&Q`ZydX8R-vf z$~Z!v7;JVzR!T0!K-&=y}yw+4njm6q55?q9ulizOI1z>A3#Vx>-ULhZBXx70@TMu7P1 z5t~x}RBHh^&_1GWQ_EjJ(X+l~kn(7WchQgE7)x_4jSF(RHN z!o9TSYj@@1amTgGezALP+~RC{NHRM@Psu+%I^gJ3FWvqPZ=buzyvcJv`ml}1xwk+{ zRCkPO%k*pTnq^5fdp;LLi-C#zw+~L_Hgvz{ZNcxr9zI)q>xo3ff{(|J4y)k{_DOoH z5oMpU%YBE+>Y+PF;W0#GXLLZYhO}#o4p$ibT(N3K^+(jRORceM-;FY?1WDY z`0^p11N{(3o4>xUz3MI;S4|1&pWw_Zyn4s|4>(x`d;;#OYX~7E5mG#zB>csnhBzZ# z*_7lPZ;bCusf9A-P|hqFR7{M0m}&H|)3w3)t<}XFc2B|YeiRpggY3O@(A0^w#t*HpjPn@ZJ%%=1nZ7$(yY_ui zMj=E2+tpN*j-W_5>qi7QJ{R{G2VF_}fA_z%O3cfGQdxN=_+X#}Ub0d=4|`favnc=~ zP^u*b?|03(RJyEMJa`j1f3)0==Z--hKG{Be&Jhyi1#}|ytIUnT;W9Jdp*=XGtM}Y4 zLRsFIyAO8d(Bf7U3>*&p%-+78J7)?g9Y#Jbagp&o$ue1}!>_8=(VaeO?2gSV0ynhI zHjnDD0QKJ-3FQpKaC`Ky+<}INDJmHY0q+E$^A+2+ASjpMy~yeP2qU1K2?l<@0X%>E z`#L9BUks|NKi1-bIKqw{_29>|_!q~n+X1@gIAsb;Syyd3Yqi*pp#s6?dIR9$Ty68e znOTzpk--1F=XJGBJEGpr?P-Xw_k8yK!HR&sk|(cES*iAN?dWtRXCy62?l2(7*;XMy z%c$3eGq9Z&W(HwkeHvRLz(ewTxG%AUK~O#=p0-394~d@)YzT4y_Hzh zM|ed|Y$XDgDL!SuYm-D&&H4Cw-)z4L&I2p`{j(VzU z92(u*H_xpW4)$qz$E{UjIR<9a-5qj1_?PO-kr~~^TXv62Hl;nPyzA)P-tl9u@dRT@ zs(L=Vh2Ux){>0n5y7BYrAyTt*28@xN0-2jg(v?r^zhT@<=Q)yu=Oi=?JQ@-qDz048 z_|(nq~ddix%wPW*V@X~(_@N`C%;ekuk2 zig}CR{Ql6|2I7>s${*QpvnQs~x{!`CBL~3CvTIk;)yg zV@fHEDD_43;c2`cQs^S<<|uM&c>V&mrODQLwE;L9_v@NDSxJ%#Ye@L^X^8QIOjbbA z_iuw~n2dE-jg`+Z#2MhDNAROj5r?0E%W3S5o@W~?c`pX~lN5xy_NaYywK{u!kFU<% zzM{1=?ZfoO*WChXJ3UHQUYjRb?L00rtGVUBe5L3|=fvkhY5P+RJ{|F44Z-2OA`b+C zK_uzHTmBM(tx!M-93VKnzx~mh@*K?#AN%`IWlSJ#J5Y;<|0*yvIg*f;xCdw9l7KC(=*ld`l^FZU*`Mi2(R#5j^;nl<1!p&fNh^? z+wy*1!SBJki?L$amaTdT%q32#KP;F%R#kR6B0gZ}KMM+eJNV#LC2P=`TWvN;myzB; zKHisg0Gy&;**0=Q&&YrxBV1lHLsu1icrY&vc3|ilq_aI(>YF3g?{O8FBapiUqpx+_ z-lMweAuXRiCbp70vz_^QZgKg}ccK$$+R+2;Ury^&>`?q3i#>2I#%?V3YmC-{$7?Dj z>bfxOErGM2$K#QGCK`1B28FWzSVA1}&64i+7UQDsqR5vG%gZl_BBbFX2AD?e@oGP{ zqy>5{b8@{+bCk%YICikn04ENQd{wZA54}=6Bb|W@YxId7g0ynDs;}m6w&uvBW~*wMiKs=zDffa?(uv6 z_2&z;L?D$XvEvVSX^EdK4>*l)2m@FrgpQ66cvWh>gpU=Enq&q4kzw+FaBw5Xp3Is# z{#Yx$TdeI2UhGqPU<7&{P>bZNA^7eKc`f;v=O)WB4LJ!GqmPB|Xvy@)*BVAev-C!l z=}nEPQqu)NQOMgGjkSJ{#oeQ-W9O^3dAjtL3)nEGBA&t>@2Mmn!0Jpm4vaj8y!bYd z+p<=ff0&n2qPGh{C&dzOYG2m7vKV;|b@AnR&1L`Xv#THcB}Uso%if7=p$^`8JMnnW zkE`1@Ss$}h(r5FhHk15odd}oO&IS%gi3wSk>qAS=ZuWcS`#)Hvjml9{1b(L2@+j-Vaaq z{hY*wss)3|vbi5{Nb#~x8T?7kx;6e$RyY=SvClt?dF>yv1_J< z=*fN~qyD3RqKDQFE@v8gje#%6l>tCWjA_4T^A`rt(33S+`N3aJxZ|egk7gL;0!Q*o zsUG`dzkF!p8gO0UcRt@aY|#9!S=NIUl2thk6r@Lz0qvTAH!PGa&-m(qjy1n!$oryH zI%f^T9~4FD8KvUB8qJTimi+1*dbUp1pI(43NkZUX+k^ja!d(6D<$+K?qi{CK=<9i zn-f@9aY`A$z@0~5GMP|9D1y*mw<^zl-zl_CQzW^@T6DX;-gs<-G0TKoqBx24H+eqh z4+b)O-{AP60TSkk9#~TTc2Z%0@7{&cf-n8{F;lPptG_Zzu4_fO71Bh(3%+r842Dp~ z^#FB;<_xoOxe=qs?w(u+buNG4`>fNj)8++z&ldRZajUvtzY+n4$jlpE(Rbmk+LCT} zY{e1~lHr>&5!6HulC#3+@453obs?l?piS*tlKo2DHD~424>8?M^oo0;c#>Ucw{27%+R!j%n|Y%p5&4I zUYh?+0K%he-+gCs9MmViwPTK-pXYh^GwUQAxEUh#o}2bdPVe}e#e2tTISN=n+XT_a7nmKK*`f`cBG(y8A!(>(HTo^e)s)`7wlQ4-*|nvAX_isgfK&{Uh4$H^!Rp6iyDOM~#nDsi0oMUAIdU|!u6wAHZI$JD z902DXyr+6IG>`2E@c8sSCmQlybnlo9tMM~A>Y4b=+w9HL;59c-#QZy7uN(_MU%T@> zVGLe!MNPS$bIyV9KA##J)fnrV#v`mwFjY@2146Ked_h0YbbE)f+!P!%Ye=BUCWM|(1(@4L4S zac$mpcj|D2AgOwQ!=YF2u=Y74hsHzYF8jw48=c3vZdhApT0(^GT3&O|ZE0sBAi)<| zvpoDzejN9??!IlAY{p&@_`B=&v-ks6QBHr>Yl*O*v(M>*0t&LG!6Lmv&5nGH?GE<8 zkOUqG5ZLm0=(HH6*?#w=q92|20oabtWYDH2I9LYIxe)U#ntHz5-a58PG#^LRBEMuM zEwA@{cvcYe0-oM4%ThOV`V&hQY`%gQe&>xEQuby$+)5Au?PGn{GsiTf_S(xh~f#u=eHGvgrBh?Im5I;2IJGU){L@n5}F0U#6h2UFH;feb+@6LK)v1VOT@nQEl zKW8hQrp3LE?|9hrUq7>N&?*}T$-jss>%7i+gc%ry!9GlO-1AF?F0?gKtVwpG+@`)` z`GWZo`itg8@33hMHd@G>KBs8Z?Q3Rh-tfK;I#FI)2(_ZPOke+~7dz(AtBWNJm8t3^*>qud5|1^hKpFnFv$S;Q13PmMX zQoUN-EIEpD2K7Frvg;`d6 zw~72vMe3ji;b-ANF!PWecILl(HTeJvyN=om0N}*DW&9B&8R~O|GMx1BoVZ$esuADC z^PKXd#j3aVI4*~dbk%6FiBF%q$wn3adxcy7665lh7>@(e@*106c7n2xRkA3{*-OdE{g}t^3!<{CWcey)0Dj=!WWM6h)-d zFKrqI(Y`2s*OXC{jk+y=0N=XC#qT;cfu~*8_Hi77-tA_fIV*K5mmy7Z%vgb8K;yo8IE)G4~9%F_s$_cqOM(yuBf3;p3@NW z{sBL9BEELqwGd*{KYlHz>1M6anlwz-eGg#G&qm~pCZ6V;Nx~*K^P<3?(f62ap_Xv! z&Ovj_>&E`{<%*4&1KvINzqXc<{giJz6@9bob?00V@B5DQ2Z`|CUFjq19s$9R{P?d2 zXvlKaSs9mrCS5mAy7jxP;9|Z>3qiJO7@-;FA{B%ctJ1dSkB`KnkgF;z%Q9lbqXmpv z9#M3%ZIfGIkKvbNvX~9Sul0$CG7bp;njP_a`%K#Ezn{U0g0b+3s(ohUPU(Arbs>*4 zXn)WEzQY}dAHOfF3M=j2Z|dfGES{P_k1~y6Vh@I3@9`8*u$s1P}FnSX4nB8{*sD#e2Tf282lT2TLyP-0#`g1ajo&8iZ zGNCp4Bkx=%64HfjUlzq}w1?rgrB72&cE|BiXUQpZ+P{2cu>S|zxWD{4f)5Na2!Y%E$z%gp%SUeyLaI!mu)`M9_izMjdpJQ z&`(!*)d9{59laJ}^>t^fJ8&G4)xcLn*5o<zU!_F>@saD!j%^`mOOC!Wtq5JipF?V z)%Vdu#PMD5$6@LDo9UCeSEh-2>C&CY+{sx4)4~*28#cVC3J68)Ah(#lg5mk)Rrx3C z{Jd#MB)_KE-9N@_7?$-N88n^*J%ki~%(kX-(Gd7$*ur#Nq2E6t_$Jw#^2RYDnB_YQ z#Q`X6unn7D|N0~e)q+wbM!$+)?qGlk)=({Z?6!A`_T5v%DtWUw_vhj?{11KB%KGIJ zU)aUgN{5}32ndSeYXP`+JvV2{RJTd?+HB)2e%-f3^JB z=p1rpy+3d3Pb<5zRyi(-uz4eLDu3UxF_{sYSyE4csk-hueVZZklgUfv*B?pD-rnSg zlTQGu^KkUYYj{SkEYx@@3zGIVvFLo#2~H4ALp@iWlitIHY{Fc#yL-3 zYX8{#sqOB!K|ayBMco}wlyOB-KAUON`LRsxQ~m~S0z};b#9=1AW#((YJu=Fm`eC!r z1Akr^5=x2Hk57^B&$s(F1FQDNdtwimqC#_x#Am={;>!on9k;#(D=af&$Fy z>pdy0Tmqx>sEWU|@`9we1{mEQ`Uct}Edgx(^$_||`2=(dpvjU9;pO#sg$^aw`n(hM zk(_f8UbJ3^|C#B4sf|)qcg!mT7*RR{u#^fUE)Ql3#7T55)mxo7iV)LuuDuW3ZTRKg zugH@TMSy^4A;@5VD>+Yl z&4@;7G;%zVJ|wZmaOZW;$Kj3}F&zhjF&0ItPAbyQVZE#vXW=+cwob;U<3{OdAkAcV5(E(7EM5mP!ZK1LOaegq(AL~=FF9R>eo zl4Ctj>Ra#e^98~1`-`Hos5~FV*nR`!dhfYJtE6kua&)70C+ zM6R)ASn=B+k<)W+;z%_s!?Uxsd`krj8H^y4+O z+qk%QKRxjKkGh}I_gmw3f;;MFn>AOty{pCpaydz=RFgn;kz;_}AwE=Qklm0%-kFV+ zYwahhaH6tQMG1KB5r{@bjkkCU&QW{Qc{=%z;?4tw9HOWhHKdmZRZK`c1KDUr(W}>M zfz|r6*ZG!~MZ9#&@^{C7&a?vdpYxf#d*{|xDSQBFme|tbq)A2@MN?>md6ySxs(eY4{~Iu`K05@*rX z4sYi={zV(7Cj|ByUw2JT((*8nV?ThAjf-buDUEmO#EUG=ODq?Z0ckm3Jk;dFrqG!!gCgsZF`WVnO1*3 z+IoH;ly&!%(`ui09{@u!E&+SazjISF8v$Du(P*86RO)z&t>|*QKW6zVFf;IMorQn# zce8GQXCKI*$aSyF=$-G2;^0G9@Fi6D%mPeI{5~NK>BJwFRm3x7s_gR9kc85DGJo*` z+`NCze2KH_Ujz0r3?s@8{18c3#0rxpJ<|rAvdt|<6^p02W^jEoS_%kV6 z@4ga37;Js(-8nbN_5GJ$9I!>A*8aaZ#Nm%ABYu1|p0#GN@ zUF=sv+53&s=&i$ke&GEzyQCa9Fn*D^tKum_z$AS3gpab1C=kc^$ll=Hu;uM$s(*My zHsAf<(npP+Ljt7menGpSyzJQ>0~>AVqOC4&ZyHF`Ki`Ib6R&Oiyyb^UYfp*FZPbHB zme%4s9TK_g@4D_;@+5h(MlOb@rLQ*1;CKpN?Nz&Xe9ANPH5N)%I@I59(YHxET5y)Zg8vA?^^Gr$RpOoS%j%lq#6JRH_-j=wx1wAq^bUPulb%rK#YP!r|b z?TzZd;4na#?}x9xt(`IQ=;q4x?!?7kV#>nPaK991M%034xpj)L++Fp?Nz(|}+m4c_ zf==A{Or`7lMj_~x)0DDtctNOBN)W_%u6mTzq?UAT_0pNL>=Wm6;$7@?F)yH9S~EZX z`S^0J>A3j{K$RwqZWdIC@YqId?^#l3=Uo)HIqWPh18~wwkSc?MWHmT9I#-atSO|$2 z|6Tfw4kaudIL9vV@$S#m{Dp7C(8P1MANN2kWLW9be`Td{G}Nke7^UZ49a%$*Wb)dC zCEq;fb~pEAH6=n8d;V#VOEk~1Xm+hXi-OurUd=(=rr~P({>Gn+_-1};E#M=^#_GF- zC?|ecz8~!z*hG`7?*&7Sd2pC{5qZ)7tJl;m#ret5RAfS4ES~3~A?{fbkq4BjTBJkf-wo0ePx>dFlUH*dA)v11a{RQX@A<$Pw zyMy2S_1}VU?&Bx$p#i6suql>&xbT>;UuKf2NtdS>KLNK(?27Bnaj0vhY>E<>`C0-+ zN1vY$M!c9G+d^Y{an{(XCYnPo%K~W8JW&dY9YJp%ZN=AT^xg2TtL4+4P_`^L`L#QL z&0A-mpC9wY?)v-`vlFI%XlzxdZ43$Be-U*Z%Z@5b@Pk<3-4gGG6A0J|gm*%CzWz05 zUc{Za5qC3#pt~z8v%5NrPaXR9Ywyd4g=sWXB))k7c{GJFdx&~sZO}E@>X!%!XN@!S z=hZEG`p?3YIl+GAK_&2s&K&43WFihBmZ*u^;8Xw?H7h%k*=&u{F^-!0>DlrVP3j-? z#i`vUsN~tx<08DL<>%1|K)658wU?fZ)iNhOa_j0>G>MuyRvG!|crq}B(tMoDQcm8v znT5Q_N}sTzjsv; znuTCOuqwI7?>kpmpD}k~OD%4))M6pce!>W2T(9(P|9+rIZ z-~h7LKjvBQL&sZcs@v`#KSrmZtKIje>=0jY2%SK}@qGgEP*+bc*b5QurzG)ey@`_p zuY12%?Z|RyxB_i~``Q@uRaFWl8)Y|~M;iqp7&=FThDs3|nAWU*cEO|k3xA!*~ zGC?CK)oSZ3x1Nn?{)Se%?=R;?taJVAD~i2keB)(yIIWcGjx4DUd98RU966{iQf>jW#{R1J7P z+gS!gSnb|~rc}}qT@n)}kF>zrOg^*C5yaaJ0S1JtVV4~_eVzrDn(0VrJ6$eN z;$24=q9E@@SgbE7aoS-ftXh111F(R~x;B#Yy*do|gQql(hApjnL*OPLwHm7MAQDCR zl%BIpt5_4c^CoteD^EZM0Y)9)VJx<;Sc8o^KU+k}1CYpJb>~QGbnA84?t2s^6&kzU z@EMeYh5H0)+u?Vcqq|x<9&(+>Ve7j@Qx?Qtv$IudOYFFNC$oYamm?_6q9|h= z@I+5Q*ha$Ti{rmly((rLZ+J5kLM}#!;#?45!4#sldp=XYqR&Nh$RFjOmnQXMZ@Zsu zM;oJNA17V`90!k8Bw6DQva|U`fAm6FIzIu?PPcscjkiN-!ztfP=F#1;6pN7_ggFf4 zC;DWNns!{xuYdmG>}rw5;MC`_FODK6tU%(WbnnR~7l?x)edM2CcD>tR!D+|f3Chtu z!fcex%9}q9Pa*Pj-`k)*7`>nfm9TC0Ymg<+L$V!{9s1Yr`4b|VGFT`&Z*eq!E#N<&|^%{>}}$>1sV|l1kW0ZA};e3&e`nLTsf9&df~u z>+k~T`rqlKQy*>1S-jx%@v&EXJh4{;qb3S9Le^xCJ&j^)RuwI2xa;npKCN2yF!twn zFRkEjk0Nct4PaiCsi~qWhvZ6MQ~?d~Ua7g6 zBX#^5ipkWSeeb`V;Yq!B4LHiv*pK$yx+QAfHnbbtY%qCc^b~voybu_6D}K@eXN zM>XpC?TZLE1Wi*^yZ0Z3yjH4BY5K;*GQ6k_lZ-o&NaW4EX#ZQ z27(+hP{XDq*Q~Tyi2AOHR&L8b$QO5tBFo6Q`C&i@PRXqwUnfByb(g24&|5Zr0eabe zGE0)tc6lIWum#xDyS)K9Q)Y{vDU37oHSeFN`4NS^FmVxHs&&CMQOdow zCCqo?%E%BWQ&S1LHQ+%S;%FU0rEctuS;op09m@x6_ z?HQ6jwHNuCF38zsNhPKa&zvv34$v1X$qZFouc@_qhGrBhY)}<$g~8Y~Swt|9yqV+Atjx1KHZ_|&*|R5;OO+e@~`R|mL$ zZ^rvh(B{K~P_uLee&$aNzI~oH16?H?E=&zJnM;7Ixpd$CA6pS?c3& z!lUHt@xD#fDE|i(Ok>9HhD3O+x!yo~<#_|((eb@E4;~$V@rItpc9mRN`#baM^wxM~ zAXJw@?M9<+CRP#zH{k*;(xjoUg1F{2T>;A{xV4GXCi9QJ_Dj&n>Lhbg+5hm&T z^PttiF^t01yT*d8=PQ%G>MsPjV7_pu)wF|`cxvT*lFiXKn-No;f28r^LX>5bd>&V} zgyvxyo_g;SysWd~zq?*WMpE|c0eGrV{h}||77dcP>y#g&IR5mNbcNxE89FBuF|`^K zKLqpl%n$#I9!J%F@gJp#-rRrc!{1c*@6O;lJc?v>rK7ME8#miie-?MGkmfk=H^nCS z^hL&t?>rc3c*PKQxf_O8@a#I0Wk0X@Ex2eq(%h}h>F3aGD&jsy=DrX9-ANPDIgi-c((K-0d0g;|RNCcmHMI6UORG4vOun5#bGmBnF?|LdQeQSj4#tw0-{ zU)vS=^3qsdT=d`Rr#y=ht*b=N7Pr~ieVR$Br%rh zu@$cS!}K%|M|ZvOP-j^e*fI+y4Z)Fnj|ABrBqD`T26-81biARksq8*Rcu`gcqRbIY zCU=9^FD!~}kWm9oQ7pyRp@z=H8ZdN%?mip_?NU_BXfMtmwFEb7CjayJpYiqUoq(=w zZRt8@3d8gUudB9y{{Y_Q zg`>)kk?QXIB+Kt}w>DGZ4i(&Kc{`m!qX`U;0uYhgq9;k=!HD3wb-GjA~&|rMLJN}iT)F)fQ>Yd5P z_w)I%czE9-SBcPf3q<2wi2vKyL(amv$rm|0n{ja@Q;_TJ6WZ@K3bNY{Vm5p)uVGPC z02*I}O7rxt$JPIF1l=Ov=WQI7Tgn5!i0oni-Sr$LN$goE&3>OLD(k=n%o$fS^s~zep0waf4wwBPC|fTn|ER~W`iDPW2l)xbw(4_3rkD9BcH4oE zJ%ec=r&h;*#!2TZ-|s6iB~8}bGwqi5uIOj5Sy8>-x#YFG)W@#M>tG^$FB+hMG@VCy zB_j2KkzCfi4FQ+=X>AyWv0Hnc1XkepMp4BYF2Fvq6D00 zo|R}8Cjd_}80z?%!+=V(C6dUs()+rJu-G-0^#fx;9D1ba*-Ngm1l_)fil zI9|!U;Yt}u#n)Ur`R|q5JyeLIcsj1zVK2Kh9A}%x{k297!aokPvo7NcvYT(XIzoLy zkl3-8nh;aQjx&9q zL-aTLkoSJ?*vZnC#0d9gA*dhn*iC}rt*pjRnWkUjB0#ww<6{Hpa3ru-!MwC;yd)g) zotxOY&sz8R{nc&63rgpoIk#1B5yac`QTFX!2fy17&^^#TZM$2e5>MwQoj2Jx`=rWSk zWW-jk)FMoLMJF`XY&1mY=I)dFxX%=VPrE`jt_Zs5lHY{DJoBd?_jmaJzGKF?1JO$- zmA%bT0AtehyYtC?X8?7Zk_N*MIk(RRJOAtvf}o?>w^WNFRhIL&s^Zj`58_+HW36zU z2lx)@c)nM?hMC#qQag0<)me{4g5@aDX z7*?F(^o;cEQk5$uIk!{=Fz(M)NE1r#yZfrjz&g)~=gYf~`i`m9E)FjM#ml{J$%MV{ zyWv7U%r1EbczjB|bPzXo1E_Re!4zX^IDDX0Be&Yf_6>dumIjU$9nE?BWlirRQY`K@TBrhktIM6`ZtRV7n?IRgP6Jfv^| z*{LBa3{fii0e$~E0Y$&LmZ(Vp$?!K@@8dIK1l7y$UVlblSF@MJ{9y1Y!8&?*Hq4nFnw6Pf-9$H!wCCK^4H+BOpq? zeuT4~P23*9T6*Uz&8_+J-`!Az^Vc8Tb=_>~7M&>^LlA&^Ps0AGcb~uazs*R@okXK= zuZX0l?(=&tNbXE+-Zq{NVPn%?0D5h0X$m+L>)>~PEd{0Iw_IwTc8d3PC*7A!Jdqy$ zUe+6afZVO9`F*cgH_AngXCO%q$n~t1g+OX#4N9_^Xc7PJ)V!$@d84|R?z=NT;0wct zZEMvfU=WbA{&5zwICW~cy6X#;#+FXq$Cea30!mkUj;8;5Ham9|t&|q!^GxX|4Eq#t z!VF2AQ85zlXCPj(3Os7AFO0s=i7VHT89h11Jqeh}ecO9i-g9&qF{z&Fsy0Vl&Cexk z`<^ZFm_|I3SjT2&f-((%=<$Qf%0DZyS6?54zV%LtU2n(15rn$+@ta?!LD^fo^b@N$ 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� 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%0DM2wjK0%6l8X% z^49Bn%aXWdotf9iDF6QJrTZ`EebjDg402ADS|T(_S(7r~-FD%{)pGZW6BCwy)XP4# zd2WV^hKq4ZqQ2^O3*|jQ;X|(5-!x9hJ6|vF;nc8AHU9ev&9-^&Kj-Xdj4n!etJSJ} z%t@=0+BGcW(e|_#rj@VT%KrCSPgPiP#b{DV<@lZ1!Lq-s*)W!Z%X`N9(yTpSNHTBu)rMCp(2ylD5N&dBPG(wY@%sx^AvE=%pZ zQjR^nrE6Bv)0<427NZ8A0Ky{{j2Z`yCu3lks0`!DFVey~u7iY@V(JG+N&8GaT<`;> z@!NzkV}`gttF|{#mSjEhDFmy=gh3p zs;|2;OHXs&tn#S^>Ss%`v}RwruWe{*Y+7KVuYXL-cv|&z<(#vgcW;L5HP)43 zaqS1awtNMLGwto+6&+3Oo@+{r-{q%9c89&-FXyC2>n`>`ZFDoDIJR(EV}t4N^9JLi zlT6I+Jayom3$HA+@;j`%#`4woQNgXgcl0@jt7IP9MHJWVf(kcvxzVm#8n^G;#W;@o z$z@wZQt0V2)AAR}zOf&V&uD#`w>!LTrLF4l2xrZpsyLe(wXcLWgS^_+Yq|13c7D1!Vpl^ID;3l(c8`6 zi^rWSjwvF{Cw?~PF~sbGXH+!|;{~Nf5L2M{zL41F;xoId+2F1Abq)Zruw%w!utEh4 z<_;@Eas7GWl30{k9l10DLhK+!9fLHCz#yXWz~}jUNH7>g9;|w!-IE7d#n4~0xP+() zsB5E`Jj{b%!BkZ@te6IEeE+Ax(KHrg`ucczhj9G@Jb040Qn^(2pf^N#LS0@}%(M_? z4C5Xe$)(3SzjuaVsG@;O1TcpNIK2453TV+;I2Na2sBb4>D6H24Vb}TidtpGjV$=Xt zqnNrcC+!XU3PUlO|B7D$T z=nu%_x$z?Ar7i%dHv&6N1tWMI!3gNE zlmx_|_|uY05Tph{Q!r3c=76BST}%?z4K?}E8gK+&haY@vDb4!AqPKix^?+Z$L>38I z#2E&y0DlYXuLDPaM+1NsbDQih7&-tzc1d@izCfcV@xB-RAlT+|RAc>axa`T>)C(8gh_mDY#KMqQwE#ko-JeU{iCrM|?o&PY) z;ururk2#F+#vZB-BTELui?DtL+v zhGiXN*y~;vE>@f5YMgHhz$oZYd>^<1r3(f(H-v48Ce&EZ^$x4~^_wg9eS#yjK?(yF zQ_oDL2td3nOG=fHt%Xn8l9SgI0C4#UhY_E=Fp(wzJp#NW+QdE2E11;I1R&*y&$3DM zG@+Y-DrhC~+*#KqL0w9R$H697Iuz3Z*qY89vLBR(5G-`}384qEB(r3uPE3=hBLHcQ z%$XT=l7#dXL)aWObA-_p7qgplo>f-CX);p^o0&q&Nm_xYm^`V3gw$`h!}s9%97Z5$_nO4xLGc|f+qdGG z(D>sHN}T;LNQ&h2YMFhWlJulh;L8z=^kc0~$0SB(JTQ)r0l>DDds!w5uAmP%?& zo=t&&x5_>Mvi5PXbyYxx>>%-YlDbr;HPc-Q#!CKK%vA@d$P)|MwcHpxs=i zR~DmxR(?n&5&N9W^$ZT+he)!0W#z?PKEZ*9QFz#<^Q1&gK&|W=HHfL7L)ax>5n6UT zTj0j0E3vHvl_z;X5G5hhucTl9y} zyEk0Mm78h7sFP%=>*IdLWx6>moE z6i`XwWGY)#Y$g#E8pdZ!djy%tULu;wM3rfAD@&rtOtyl?Od={YiZ6oQ(PScP{aYpy zm6^l`(4pABK#HMf%A}%#e(3BJP-C}|sbUCPGNGu#8V*&9BSXbd4rD@6O|99;k|3a@ zcaWidVVk6f05s1Z@7VZ6GFTh|FVtN69Rf7%9H(x|CR4?EqX4DSt00=Yi?0q2Ib}_P=p#cCJ`0w3R MC@FgeK4AiX03TP&((ref) { }); class ThemeService { - static const _currentDefaultThemeVersion = 17; + static const _currentDefaultThemeVersion = 18; ThemeService._(); static ThemeService? _instance; static ThemeService get instance => _instance ??= ThemeService._(); From aaac3e7688c5cd5e2d0ea22c3542ace9aa045d31 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 28 May 2025 16:46:05 -0600 Subject: [PATCH 099/206] use published salvium --- pubspec.lock | 88 +++++++++++++++++++ scripts/app_config/templates/pubspec.template | 7 +- 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c5baa5ce0..6cb6be1ac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -536,6 +536,94 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0-pre" + cs_salvium: + dependency: "direct main" + description: + name: cs_salvium + sha256: e25976e874dcf6bf4e4330b541b1028cffe8bacfffbcc51ab106f76c6686a56d + url: "https://pub.dev" + source: hosted + version: "1.1.0" + cs_salvium_flutter_libs: + dependency: "direct main" + description: + name: cs_salvium_flutter_libs + sha256: "4ab42fb499de4749e30de5cd4155aaaa44239229ec30a5c4ce661c6a2964ea96" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + cs_salvium_flutter_libs_android: + dependency: transitive + description: + name: cs_salvium_flutter_libs_android + sha256: "63603fc4c94d609e13c8e8064c742ac628ef006d3af9990e2c585489bde9b96d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_android_arm64_v8a: + dependency: transitive + description: + name: cs_salvium_flutter_libs_android_arm64_v8a + sha256: "5ced9fe6d71dd22f90865600b8dff1ed07ce480db6c9de1a8d56e63318000e97" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_android_armeabi_v7a: + dependency: transitive + description: + name: cs_salvium_flutter_libs_android_armeabi_v7a + sha256: "2fb718dff22918e72b138c191dbd887d8d241f03a34add11e8d699c48b657b47" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_android_x86_64: + dependency: transitive + description: + name: cs_salvium_flutter_libs_android_x86_64 + sha256: "85134ab635a4dddec5735fdd8f3971a1c33e3aaa1c8aa88e54f0b3d5e0d0caab" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_ios: + dependency: transitive + description: + name: cs_salvium_flutter_libs_ios + sha256: "6e57590b054f420c79549d7059edfeca55e38cea19e34cf94fcf9fbd3de53d8b" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_linux: + dependency: transitive + description: + name: cs_salvium_flutter_libs_linux + sha256: ed24070da5c4bad5fd2f76c003a45a7378389d382b919cfa1ee88fad25d07fe3 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + cs_salvium_flutter_libs_macos: + dependency: transitive + description: + name: cs_salvium_flutter_libs_macos + sha256: "9df0818299a5ddadd41eb4c94de2cd8e519d1e9f4aa6166657397200397f402f" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_platform_interface: + dependency: transitive + description: + name: cs_salvium_flutter_libs_platform_interface + sha256: "36ef1edd1481b92a95500fbdf397a371c1d624b58401a56638dc315f3c607dc0" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cs_salvium_flutter_libs_windows: + dependency: transitive + description: + name: cs_salvium_flutter_libs_windows + sha256: "3cef0c1320ecc55afecbe5d0a97b9447d033d5994a2ebf93df64d0558e582daf" + url: "https://pub.dev" + source: hosted + version: "1.1.0" csslib: dependency: transitive description: diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template index 2171e8cda..9b007143e 100644 --- a/scripts/app_config/templates/pubspec.template +++ b/scripts/app_config/templates/pubspec.template @@ -221,11 +221,8 @@ dependencies: drift: ^2.22.1 drift_flutter: ^0.2.3 path: ^1.9.1 -# cs_salvium: 1.0.0-pre.1 - cs_salvium: - path: ../cs_salvium/packages/cs_salvium - cs_salvium_flutter_libs: - path: ../cs_salvium/packages/cs_salvium_flutter_libs + cs_salvium: ^1.1.0 + cs_salvium_flutter_libs: ^1.0.1 dev_dependencies: flutter_test: From d8dad7f0b3fc9e82857f10caabcbe17f399dfb38 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 29 May 2025 10:29:56 -0600 Subject: [PATCH 100/206] equality check fix --- lib/db/migrate_wallets_to_isar.dart | 108 ++++++++++++++-------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/db/migrate_wallets_to_isar.dart b/lib/db/migrate_wallets_to_isar.dart index cd54a4063..1b5e98b5a 100644 --- a/lib/db/migrate_wallets_to_isar.dart +++ b/lib/db/migrate_wallets_to_isar.dart @@ -20,14 +20,17 @@ Future migrateWalletsToIsar({ await MainDB.instance.initMainDB(); // ensure fresh - await MainDB.instance.isar - .writeTxn(() async => await MainDB.instance.isar.transactionV2s.clear()); + await MainDB.instance.isar.writeTxn( + () async => await MainDB.instance.isar.transactionV2s.clear(), + ); - final allWalletsBox = - await DB.instance.hive.openBox(DB.boxNameAllWalletsData); + final allWalletsBox = await DB.instance.hive.openBox( + DB.boxNameAllWalletsData, + ); - final names = DB.instance - .get(boxName: DB.boxNameAllWalletsData, key: 'names') as Map?; + final names = + DB.instance.get(boxName: DB.boxNameAllWalletsData, key: 'names') + as Map?; if (names == null) { // no wallets to migrate @@ -37,27 +40,23 @@ Future migrateWalletsToIsar({ // // Parse the old data from the Hive map into a nice list // - final List< - ({ - String coinIdentifier, - String name, - String walletId, - })> oldInfo = Map.from(names).values.map((e) { - final map = e as Map; - return ( - coinIdentifier: map["coin"] as String, - walletId: map["id"] as String, - name: map["name"] as String, - ); - }).toList(); + final List<({String coinIdentifier, String name, String walletId})> oldInfo = + Map.from(names).values.map((e) { + final map = e as Map; + return ( + coinIdentifier: map["coin"] as String, + walletId: map["id"] as String, + name: map["name"] as String, + ); + }).toList(); // // Get current ordered list of favourite wallet Ids // final List favourites = - (await DB.instance.hive.openBox(DB.boxNameFavoriteWallets)) - .values - .toList(); + (await DB.instance.hive.openBox( + DB.boxNameFavoriteWallets, + )).values.toList(); final List<(WalletInfo, WalletInfoMeta)> newInfo = []; final List tokenInfo = []; @@ -72,10 +71,11 @@ Future migrateWalletsToIsar({ // // First handle transaction notes // - final newNoteCount = await MainDB.instance.isar.transactionNotes - .where() - .walletIdEqualTo(old.walletId) - .count(); + final newNoteCount = + await MainDB.instance.isar.transactionNotes + .where() + .walletIdEqualTo(old.walletId) + .count(); if (newNoteCount == 0) { final map = walletBox.get('notes') as Map?; @@ -108,18 +108,18 @@ Future migrateWalletsToIsar({ // final Map otherData = {}; - final List? tokenContractAddresses = walletBox.get( - "ethTokenContracts", - ) as List?; + final List? tokenContractAddresses = + walletBox.get("ethTokenContracts") as List?; if (tokenContractAddresses?.isNotEmpty == true) { otherData[WalletInfoKeys.tokenContractAddresses] = tokenContractAddresses; for (final address in tokenContractAddresses!) { - final contract = await MainDB.instance.isar.ethContracts - .where() - .addressEqualTo(address) - .findFirst(); + final contract = + await MainDB.instance.isar.ethContracts + .where() + .addressEqualTo(address) + .findFirst(); if (contract != null) { tokenInfo.add( TokenWalletInfo( @@ -133,7 +133,7 @@ Future migrateWalletsToIsar({ } // epiccash specifics - if (old.coinIdentifier == Epiccash(CryptoCurrencyNetwork.main)) { + if (old.coinIdentifier == Epiccash(CryptoCurrencyNetwork.main).identifier) { final epicWalletInfo = ExtraEpiccashWalletInfo.fromMap({ "receivingIndex": walletBox.get("receivingIndex") as int? ?? 0, "changeIndex": walletBox.get("changeIndex") as int? ?? 0, @@ -149,8 +149,9 @@ Future migrateWalletsToIsar({ } else if (old.coinIdentifier == Firo(CryptoCurrencyNetwork.main).identifier || old.coinIdentifier == Firo(CryptoCurrencyNetwork.test).identifier) { - otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = walletBox - .get(WalletInfoKeys.lelantusCoinIsarRescanRequired) as bool? ?? + otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = + walletBox.get(WalletInfoKeys.lelantusCoinIsarRescanRequired) + as bool? ?? true; } @@ -161,8 +162,9 @@ Future migrateWalletsToIsar({ final infoMeta = WalletInfoMeta( walletId: old.walletId, - isMnemonicVerified: allWalletsBox - .get("${old.walletId}_mnemonicHasBeenVerified") as bool? ?? + isMnemonicVerified: + allWalletsBox.get("${old.walletId}_mnemonicHasBeenVerified") + as bool? ?? false, ); @@ -170,19 +172,15 @@ Future migrateWalletsToIsar({ coinName: old.coinIdentifier, walletId: old.walletId, name: old.name, - mainAddressType: AppConfig.getCryptoCurrencyFor(old.coinIdentifier)! - .defaultAddressType, + mainAddressType: + AppConfig.getCryptoCurrencyFor( + old.coinIdentifier, + )!.defaultAddressType, favouriteOrderIndex: favourites.indexOf(old.walletId), - cachedChainHeight: walletBox.get( - DBKeys.storedChainHeight, - ) as int? ?? - 0, - cachedBalanceString: walletBox.get( - DBKeys.cachedBalance, - ) as String?, - cachedBalanceSecondaryString: walletBox.get( - DBKeys.cachedBalanceSecondary, - ) as String?, + cachedChainHeight: walletBox.get(DBKeys.storedChainHeight) as int? ?? 0, + cachedBalanceString: walletBox.get(DBKeys.cachedBalance) as String?, + cachedBalanceSecondaryString: + walletBox.get(DBKeys.cachedBalanceSecondary) as String?, otherDataJsonString: jsonEncode(otherData), ); @@ -197,10 +195,12 @@ Future migrateWalletsToIsar({ if (newInfo.isNotEmpty) { await MainDB.instance.isar.writeTxn(() async { - await MainDB.instance.isar.walletInfo - .putAll(newInfo.map((e) => e.$1).toList()); - await MainDB.instance.isar.walletInfoMeta - .putAll(newInfo.map((e) => e.$2).toList()); + await MainDB.instance.isar.walletInfo.putAll( + newInfo.map((e) => e.$1).toList(), + ); + await MainDB.instance.isar.walletInfoMeta.putAll( + newInfo.map((e) => e.$2).toList(), + ); if (tokenInfo.isNotEmpty) { await MainDB.instance.isar.tokenWalletInfo.putAll(tokenInfo); From 292b494f092ba25ace2a5656a4e1df529503eefa Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 29 May 2025 11:14:16 -0600 Subject: [PATCH 101/206] remove lelantus --- .github/workflows/test.yaml | 8 - .gitignore | 1 - .gitmodules | 3 - crypto_plugins/flutter_liblelantus | 1 - docs/building.md | 1 - ios/Podfile.lock | 6 - lib/db/db_version_migration.dart | 288 +-- lib/db/isar/main_db.dart | 180 +- lib/db/migrate_wallets_to_isar.dart | 7 - .../cached_electrumx_client.dart | 163 +- .../models/firo_specific/lelantus_coin.dart | 81 - .../models/firo_specific/lelantus_coin.g.dart | 1629 ----------------- lib/models/isar/models/isar_models.dart | 1 - lib/models/lelantus_fee_data.dart | 21 - lib/models/models.dart | 1 - ...w_wallet_recovery_phrase_warning_view.dart | 7 +- .../restore_options_view.dart | 25 +- .../restore_view_only_wallet_view.dart | 9 - .../restore_wallet_view.dart | 8 - .../verify_recovery_phrase_view.dart | 6 - .../send_view/confirm_transaction_view.dart | 9 - lib/pages/send_view/send_view.dart | 99 +- .../firo_balance_selection_sheet.dart | 201 +- .../transaction_fee_selection_sheet.dart | 12 - .../global_settings_view/about_view.dart | 84 +- .../helpers/restore_create_backup.dart | 11 +- .../lelantus_settings_view.dart | 214 --- .../wallet_settings_wallet_settings_view.dart | 39 +- .../wallet_balance_toggle_sheet.dart | 160 +- .../sub_widgets/wallet_summary_info.dart | 5 - lib/pages/wallet_view/wallet_view.dart | 138 +- .../lelantus_coins/lelantus_coins_view.dart | 134 -- .../desktop_balance_toggle_button.dart | 40 +- .../wallet_view/sub_widgets/desktop_send.dart | 79 +- .../sub_widgets/desktop_send_fee_form.dart | 46 +- .../sub_widgets/desktop_wallet_features.dart | 24 +- .../sub_widgets/desktop_wallet_summary.dart | 5 - .../firo_desktop_wallet_summary.dart | 18 +- .../more_features/more_features_dialog.dart | 176 -- .../settings_menu/desktop_about_view.dart | 373 ++-- .../ui/preview_tx_button_state_provider.dart | 43 +- ...public_private_balance_state_provider.dart | 11 +- lib/route_generator.dart | 27 +- lib/utilities/git_status.dart | 73 +- lib/utilities/prefs.dart | 2 +- lib/utilities/wallet_tools.dart | 24 +- lib/wallets/api/lelantus_ffi_wrapper.dart | 551 ------ lib/wallets/isar/models/wallet_info.dart | 3 - lib/wallets/models/tx_data.dart | 28 +- lib/wallets/wallet/impl/firo_wallet.dart | 75 +- lib/wallets/wallet/wallet.dart | 8 - .../lelantus_interface.dart | 1215 ------------ .../spark_interface.dart | 3 +- lib/widgets/desktop/desktop_fee_dialog.dart | 34 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 - macos/Podfile.lock | 6 - pubspec.lock | 7 - scripts/android/build_all.sh | 2 - scripts/android/build_all_campfire.sh | 2 - scripts/android/build_all_duo.sh | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 28 - .../app_config/templates/linux/CMakeLists.txt | 3 - .../macos/Runner.xcodeproj/project.pbxproj | 12 - scripts/app_config/templates/pubspec.template | 3 - .../templates/windows/CMakeLists.txt | 3 - scripts/ios/build_all.sh | 2 - scripts/ios/build_all_campfire.sh | 2 - scripts/ios/build_all_duo.sh | 2 - scripts/linux/build_all.sh | 1 - scripts/linux/build_all_campfire.sh | 1 - scripts/linux/build_all_duo.sh | 3 +- scripts/macos/build_all.sh | 1 - scripts/macos/build_all_campfire.sh | 1 - scripts/macos/build_all_duo.sh | 1 - scripts/windows/build_all.sh | 1 - scripts/windows/build_all_campfire.sh | 1 - scripts/windows/build_all_duo.sh | 1 - scripts/windows/deps.sh | 2 - test/models/lelantus_fee_data_test.dart | 10 - 79 files changed, 520 insertions(+), 5989 deletions(-) delete mode 160000 crypto_plugins/flutter_liblelantus delete mode 100644 lib/models/isar/models/firo_specific/lelantus_coin.dart delete mode 100644 lib/models/isar/models/firo_specific/lelantus_coin.g.dart delete mode 100644 lib/models/lelantus_fee_data.dart delete mode 100644 lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart delete mode 100644 lib/pages_desktop_specific/lelantus_coins/lelantus_coins_view.dart delete mode 100644 lib/wallets/api/lelantus_ffi_wrapper.dart delete mode 100644 lib/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart delete mode 100644 test/models/lelantus_fee_data_test.dart diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 702940c60..e46a16c6c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -25,14 +25,6 @@ jobs: sudo apt clean sudo apt update sudo apt install -y unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake openjdk-8-jre-headless libgit2-dev clang libncurses5-dev libncursesw5-dev zlib1g-dev llvm debhelper libclang-dev opencl-headers libssl-dev ocl-icd-opencl-dev libc6-dev-i386 - - name: Build Lelantus - run: | - cd crypto_plugins/flutter_liblelantus/scripts/linux/ - ./build_all.sh - - name: Build Monero - run: | - cd crypto_plugins/flutter_libmonero/scripts/linux/ - ./build_monero_all.sh - name: Build Epic Cash run: | cd crypto_plugins/flutter_libepiccash/scripts/linux/ diff --git a/.gitignore b/.gitignore index 7b550e43e..30fb5a6e1 100644 --- a/.gitignore +++ b/.gitignore @@ -63,7 +63,6 @@ scripts/**/build /lib/external_api_keys.dart libepic_cash_wallet.dll -libmobileliblelantus.dll libtor_ffi.dll flutter_libsparkmobile.dll secp256k1.dll diff --git a/.gitmodules b/.gitmodules index 2186826df..d9a561cc1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "crypto_plugins/flutter_libepiccash"] path = crypto_plugins/flutter_libepiccash url = https://github.com/cypherstack/flutter_libepiccash.git -[submodule "crypto_plugins/flutter_liblelantus"] - path = crypto_plugins/flutter_liblelantus - url = https://github.com/cypherstack/flutter_liblelantus.git [submodule "crypto_plugins/frostdart"] path = crypto_plugins/frostdart url = https://github.com/cypherstack/frostdart diff --git a/crypto_plugins/flutter_liblelantus b/crypto_plugins/flutter_liblelantus deleted file mode 160000 index 081ae89d8..000000000 --- a/crypto_plugins/flutter_liblelantus +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 081ae89d8f47f5575a19dc03663727cf0d271f2c diff --git a/docs/building.md b/docs/building.md index 1475a7d6d..3ee68cf98 100644 --- a/docs/building.md +++ b/docs/building.md @@ -283,7 +283,6 @@ The WSL2 host may optionally be navigated to the `stack_wallet` repository on th If the DLLs were built on the WSL filesystem instead of on Windows, copy the resulting `dll`s to their respective positions on the Windows host: - `stack_wallet/crypto_plugins/flutter_libepiccash/scripts/windows/build/libepic_cash_wallet.dll` -- `stack_wallet/crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll` diff --git a/ios/Podfile.lock b/ios/Podfile.lock index add8f4224..13a199bd8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -65,8 +65,6 @@ PODS: - Flutter - isar_flutter_libs (1.0.0): - Flutter - - lelantus (0.0.1): - - Flutter - local_auth_darwin (0.0.1): - Flutter - FlutterMacOS @@ -129,7 +127,6 @@ DEPENDENCIES: - frostdart (from `.symlinks/plugins/frostdart/ios`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) - - lelantus (from `.symlinks/plugins/lelantus/ios`) - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) @@ -186,8 +183,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/integration_test/ios" isar_flutter_libs: :path: ".symlinks/plugins/isar_flutter_libs/ios" - lelantus: - :path: ".symlinks/plugins/lelantus/ios" local_auth_darwin: :path: ".symlinks/plugins/local_auth_darwin/darwin" package_info_plus: @@ -230,7 +225,6 @@ SPEC CHECKSUMS: frostdart: 4c72b69ccac2f13ede744107db046a125acce597 integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 isar_flutter_libs: fdf730ca925d05687f36d7f1d355e482529ed097 - lelantus: 417f0221260013dfc052cae9cf4b741b6479edba local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 diff --git a/lib/db/db_version_migration.dart b/lib/db/db_version_migration.dart index e18c4b720..8ef1f2bb5 100644 --- a/lib/db/db_version_migration.dart +++ b/lib/db/db_version_migration.dart @@ -12,7 +12,6 @@ import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; import '../app_config.dart'; -import '../electrumx_rpc/electrumx_client.dart'; import '../models/contact.dart'; import '../models/exchange/change_now/exchange_transaction.dart'; import '../models/exchange/response_objects/trade.dart'; @@ -20,9 +19,7 @@ import '../models/isar/models/blockchain_data/address.dart'; import '../models/isar/models/contact_entry.dart' as isar_contact; import '../models/isar/models/isar_models.dart' as isar_models; import '../models/models.dart'; -import '../models/node_model.dart'; import '../services/mixins/wallet_db.dart'; -import '../services/node_service.dart'; import '../services/wallets_service.dart'; import '../utilities/amount/amount.dart'; import '../utilities/constants.dart'; @@ -50,107 +47,11 @@ class DbVersionMigrator with WalletDB { case 0: await DB.instance.hive.openBox(DB.boxNameAllWalletsData); await DB.instance.hive.openBox(DB.boxNamePrefs); - final walletsService = WalletsService(); - final nodeService = NodeService(secureStorageInterface: secureStore); final prefs = Prefs.instance; - final walletInfoList = await walletsService.walletNames; await prefs.init(); - ElectrumXClient? client; - int? latestSetId; - - final firo = Firo(CryptoCurrencyNetwork.main); - // only instantiate client if there are firo wallets - if (walletInfoList.values - .any((element) => element.coinIdentifier == firo.identifier)) { - await DB.instance.hive.openBox(DB.boxNameNodeModels); - await DB.instance.hive.openBox(DB.boxNamePrimaryNodes); - final node = - nodeService.getPrimaryNodeFor(currency: firo) ?? firo.defaultNode; - final List failovers = nodeService - .failoverNodesFor(currency: firo) - .map( - (e) => ElectrumXNode( - address: e.host, - port: e.port, - name: e.name, - id: e.id, - useSSL: e.useSSL, - torEnabled: e.torEnabled, - clearnetEnabled: e.clearnetEnabled, - ), - ) - .toList(); - - client = ElectrumXClient.from( - node: ElectrumXNode( - address: node.host, - port: node.port, - name: node.name, - id: node.id, - useSSL: node.useSSL, - torEnabled: node.torEnabled, - clearnetEnabled: node.clearnetEnabled, - ), - prefs: prefs, - failovers: failovers, - cryptoCurrency: Firo(CryptoCurrencyNetwork.main), - ); - - try { - latestSetId = await client.getLelantusLatestCoinId(); - } catch (e, s) { - // default to 2 for now - latestSetId = 2; - Logging.instance.w( - "Failed to fetch latest coin id during firo db migrate: $e \nUsing a default value of 2", - error: e, - stackTrace: s, - ); - } - } - - for (final walletInfo in walletInfoList.values) { - // migrate each firo wallet's lelantus coins - if (walletInfo.coinIdentifier == firo.identifier) { - await DB.instance.hive.openBox(walletInfo.walletId); - final _lelantusCoins = DB.instance.get( - boxName: walletInfo.walletId, - key: '_lelantus_coins', - ) as List?; - final List> lelantusCoins = []; - for (final lCoin in _lelantusCoins ?? []) { - lelantusCoins - .add({lCoin.keys.first: lCoin.values.first as LelantusCoin}); - } - - final List> coins = []; - for (final element in lelantusCoins) { - final LelantusCoin coin = element.values.first; - int anonSetId = coin.anonymitySetId; - if (coin.anonymitySetId == 1 && - (coin.publicCoin == '' || - coin.publicCoin == "jmintData.publicCoin")) { - anonSetId = latestSetId!; - } - coins.add({ - element.keys.first: LelantusCoin( - coin.index, - coin.value, - coin.publicCoin, - coin.txId, - anonSetId, - coin.isUsed, - ), - }); - } - await DB.instance.put( - boxName: walletInfo.walletId, - key: '_lelantus_coins', - value: coins, - ); - } - } + // nothing happens here anymore. + // Kept for legacy reasons after removing old lelantus // update version await DB.instance.put( @@ -165,8 +66,9 @@ class DbVersionMigrator with WalletDB { case 1: await DB.instance.hive.openBox(DB.boxNameTrades); await DB.instance.hive.openBox(DB.boxNameTradesV2); - final trades = - DB.instance.values(boxName: DB.boxNameTrades); + final trades = DB.instance.values( + boxName: DB.boxNameTrades, + ); for (final old in trades) { if (old.statusObject != null) { @@ -208,9 +110,7 @@ class DbVersionMigrator with WalletDB { case 3: // clear possible broken firo cache await DB.instance.clearSharedTransactionCache( - currency: Firo( - CryptoCurrencyNetwork.test, - ), + currency: Firo(CryptoCurrencyNetwork.test), ); // update version @@ -244,8 +144,8 @@ class DbVersionMigrator with WalletDB { final themeName = DB.instance.get(boxName: "theme", key: "colorScheme") - as String? ?? - "light"; + as String? ?? + "light"; await DB.instance.put( boxName: DB.boxNamePrefs, @@ -269,11 +169,12 @@ class DbVersionMigrator with WalletDB { final count = await MainDB.instance.isar.addresses.count(); // add change/receiving tags to address labels for (var i = 0; i < count; i += 50) { - final addresses = await MainDB.instance.isar.addresses - .where() - .offset(i) - .limit(50) - .findAll(); + final addresses = + await MainDB.instance.isar.addresses + .where() + .offset(i) + .limit(50) + .findAll(); final List labels = []; for (final address in addresses) { @@ -301,11 +202,14 @@ class DbVersionMigrator with WalletDB { // update/create label if tags is not empty if (tags != null) { - isar_models.AddressLabel? label = await MainDB - .instance.isar.addressLabels - .where() - .addressStringWalletIdEqualTo(address.value, address.walletId) - .findFirst(); + isar_models.AddressLabel? label = + await MainDB.instance.isar.addressLabels + .where() + .addressStringWalletIdEqualTo( + address.value, + address.walletId, + ) + .findFirst(); if (label == null) { label = isar_models.AddressLabel( walletId: address.walletId, @@ -363,12 +267,13 @@ class DbVersionMigrator with WalletDB { Bitcoincash(CryptoCurrencyNetwork.main).identifier || info.coinIdentifier == Bitcoincash(CryptoCurrencyNetwork.test).identifier) { - final ids = await MainDB.instance - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2sh) - .idProperty() - .findAll(); + final ids = + await MainDB.instance + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2sh) + .idProperty() + .findAll(); await MainDB.instance.isar.writeTxn(() async { await MainDB.instance.isar.addresses.deleteAll(ids); @@ -490,7 +395,7 @@ class DbVersionMigrator with WalletDB { const rcvIndex = 0; final List> - transactionsData = []; + transactionsData = []; if (txnData != null) { final txns = txnData.getAllTransactions(); @@ -501,15 +406,17 @@ class DbVersionMigrator with WalletDB { walletId: walletId, txid: tx.txid, timestamp: tx.timestamp, - type: isIncoming - ? isar_models.TransactionType.incoming - : isar_models.TransactionType.outgoing, + type: + isIncoming + ? isar_models.TransactionType.incoming + : isar_models.TransactionType.outgoing, subType: isar_models.TransactionSubType.none, amount: tx.amount, - amountString: Amount( - rawValue: BigInt.from(tx.amount), - fractionDigits: epic.fractionDigits, - ).toJsonString(), + amountString: + Amount( + rawValue: BigInt.from(tx.amount), + fractionDigits: epic.fractionDigits, + ).toJsonString(), fee: tx.fees, height: tx.height, isCancelled: tx.isCancelled, @@ -531,12 +438,14 @@ class DbVersionMigrator with WalletDB { publicKey: [], derivationIndex: isIncoming ? rcvIndex : -1, derivationPath: null, - type: isIncoming - ? isar_models.AddressType.mimbleWimble - : isar_models.AddressType.unknown, - subType: isIncoming - ? isar_models.AddressSubType.receiving - : isar_models.AddressSubType.unknown, + type: + isIncoming + ? isar_models.AddressType.mimbleWimble + : isar_models.AddressType.unknown, + subType: + isIncoming + ? isar_models.AddressSubType.receiving + : isar_models.AddressSubType.unknown, ); transactionsData.add(Tuple2(iTx, address)); } @@ -594,25 +503,28 @@ class DbVersionMigrator with WalletDB { final crypto = AppConfig.getCryptoCurrencyFor(info.coinIdentifier)!; for (var i = 0; i < count; i += 50) { - final txns = await MainDB.instance - .getTransactions(walletId) - .offset(i) - .limit(50) - .findAll(); + final txns = + await MainDB.instance + .getTransactions(walletId) + .offset(i) + .limit(50) + .findAll(); // migrate amount to serialized amount string - final txnsData = txns - .map( - (tx) => Tuple2( - tx - ..amountString = Amount( - rawValue: BigInt.from(tx.amount), - fractionDigits: crypto.fractionDigits, - ).toJsonString(), - tx.address.value, - ), - ) - .toList(); + final txnsData = + txns + .map( + (tx) => Tuple2( + tx + ..amountString = + Amount( + rawValue: BigInt.from(tx.amount), + fractionDigits: crypto.fractionDigits, + ).toJsonString(), + tx.address.value, + ), + ) + .toList(); // update db records await MainDB.instance.addNewTransactionData(txnsData, walletId); @@ -621,17 +533,16 @@ class DbVersionMigrator with WalletDB { } Future _v9() async { - final addressBookBox = - await DB.instance.hive.openBox(DB.boxNameAddressBook); + final addressBookBox = await DB.instance.hive.openBox( + DB.boxNameAddressBook, + ); await MainDB.instance.initMainDB(); final keys = List.from(addressBookBox.keys); final contacts = keys .map( (id) => Contact.fromJson( - Map.from( - addressBookBox.get(id) as Map, - ), + Map.from(addressBookBox.get(id) as Map), ), ) .toList(growable: false); @@ -672,65 +583,12 @@ class DbVersionMigrator with WalletDB { Future _v10(SecureStorageInterface secureStore) async { await DB.instance.hive.openBox(DB.boxNameAllWalletsData); await DB.instance.hive.openBox(DB.boxNamePrefs); - final walletsService = WalletsService(); final prefs = Prefs.instance; - final walletInfoList = await walletsService.walletNames; 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.coinIdentifier == firo.identifier && - MainDB.instance.isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .countSync() == - 0) { - final walletBox = await DB.instance.hive.openBox(walletId); - - final hiveLCoins = DB.instance.get( - boxName: walletId, - key: "_lelantus_coins", - ) as List? ?? - []; - - final jindexes = (DB.instance - .get(boxName: walletId, key: "jindex") as List? ?? - []) - .cast(); - - final List coins = []; - for (final e in hiveLCoins) { - final map = e as Map; - final lcoin = map.values.first as LelantusCoin; - - final isJMint = jindexes.contains(lcoin.index); - - final coin = isar_models.LelantusCoin( - walletId: walletId, - txid: lcoin.txId, - value: lcoin.value.toString(), - mintIndex: lcoin.index, - anonymitySetId: lcoin.anonymitySetId, - isUsed: lcoin.isUsed, - isJMint: isJMint, - otherData: null, - ); - - coins.add(coin); - } - - if (coins.isNotEmpty) { - await MainDB.instance.isar.writeTxn(() async { - await MainDB.instance.isar.lelantusCoins.putAll(coins); - }); - } - } - } + // nothing happens here anymore. + // Kept for legacy reasons after removing old lelantus } Future _v11(SecureStorageInterface secureStore) async { diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart index a16fb2b9a..cb0163503 100644 --- a/lib/db/isar/main_db.dart +++ b/lib/db/isar/main_db.dart @@ -63,7 +63,6 @@ class MainDB { StackThemeSchema, ContactEntrySchema, OrdinalSchema, - LelantusCoinSchema, WalletInfoSchema, TransactionV2Schema, SparkCoinSchema, @@ -93,13 +92,16 @@ class MainDB { Future updateWalletInfo(WalletInfo walletInfo) async { try { await isar.writeTxn(() async { - final info = await isar.walletInfo - .where() - .walletIdEqualTo(walletInfo.walletId) - .findFirst(); + final info = + await isar.walletInfo + .where() + .walletIdEqualTo(walletInfo.walletId) + .findFirst(); if (info == null) { - throw Exception("updateWalletInfo() called with new WalletInfo." - " Use putWalletInfo()"); + throw Exception( + "updateWalletInfo() called with new WalletInfo." + " Use putWalletInfo()", + ); } await isar.walletInfo.deleteByWalletId(walletInfo.walletId); @@ -174,8 +176,7 @@ class MainDB { // addresses QueryBuilder getAddresses( String walletId, - ) => - isar.addresses.where().walletIdEqualTo(walletId); + ) => isar.addresses.where().walletIdEqualTo(walletId); Future putAddress(Address address) async { try { @@ -202,8 +203,10 @@ class MainDB { final List ids = []; await isar.writeTxn(() async { for (final address in addresses) { - final storedAddress = await isar.addresses - .getByValueWalletId(address.value, address.walletId); + final storedAddress = await isar.addresses.getByValueWalletId( + address.value, + address.walletId, + ); int id; if (storedAddress == null) { @@ -253,8 +256,7 @@ class MainDB { // transactions QueryBuilder getTransactions( String walletId, - ) => - isar.transactions.where().walletIdEqualTo(walletId); + ) => isar.transactions.where().walletIdEqualTo(walletId); Future putTransaction(Transaction transaction) async { try { @@ -294,20 +296,19 @@ class MainDB { QueryBuilder getUTXOsByAddress( String walletId, String address, - ) => - isar.utxos - .where() - .walletIdEqualTo(walletId) - .filter() - .addressEqualTo(address); + ) => isar.utxos + .where() + .walletIdEqualTo(walletId) + .filter() + .addressEqualTo(address); Future putUTXO(UTXO utxo) => isar.writeTxn(() async { - await isar.utxos.put(utxo); - }); + await isar.utxos.put(utxo); + }); Future putUTXOs(List utxos) => isar.writeTxn(() async { - await isar.utxos.putAll(utxos); - }); + await isar.utxos.putAll(utxos); + }); Future updateUTXOs(String walletId, List utxos) async { bool newUTXO = false; @@ -315,10 +316,11 @@ class MainDB { final set = utxos.toSet(); for (final utxo in utxos) { // check if utxo exists in db and update accordingly - final storedUtxo = await isar.utxos - .where() - .txidWalletIdVoutEqualTo(utxo.txid, utxo.walletId, utxo.vout) - .findFirst(); + final storedUtxo = + await isar.utxos + .where() + .txidWalletIdVoutEqualTo(utxo.txid, utxo.walletId, utxo.vout) + .findFirst(); if (storedUtxo != null) { // update @@ -344,17 +346,14 @@ class MainDB { return newUTXO; } - Stream watchUTXO({ - required Id id, - bool fireImmediately = false, - }) { + Stream watchUTXO({required Id id, bool fireImmediately = false}) { return isar.utxos.watchObject(id, fireImmediately: fireImmediately); } // transaction notes QueryBuilder - getTransactionNotes(String walletId) => - isar.transactionNotes.where().walletIdEqualTo(walletId); + getTransactionNotes(String walletId) => + isar.transactionNotes.where().walletIdEqualTo(walletId); Future putTransactionNote(TransactionNote transactionNote) => isar.writeTxn(() async { @@ -370,25 +369,23 @@ class MainDB { String walletId, String txid, ) async { - return isar.transactionNotes.getByTxidWalletId( - txid, - walletId, - ); + return isar.transactionNotes.getByTxidWalletId(txid, walletId); } Stream watchTransactionNote({ required Id id, bool fireImmediately = false, }) { - return isar.transactionNotes - .watchObject(id, fireImmediately: fireImmediately); + return isar.transactionNotes.watchObject( + id, + fireImmediately: fireImmediately, + ); } // address labels QueryBuilder getAddressLabels( String walletId, - ) => - isar.addressLabels.where().walletIdEqualTo(walletId); + ) => isar.addressLabels.where().walletIdEqualTo(walletId); Future putAddressLabel(AddressLabel addressLabel) => isar.writeTxn(() async { @@ -396,8 +393,8 @@ class MainDB { }); int putAddressLabelSync(AddressLabel addressLabel) => isar.writeTxnSync(() { - return isar.addressLabels.putSync(addressLabel); - }); + return isar.addressLabels.putSync(addressLabel); + }); Future putAddressLabels(List addressLabels) => isar.writeTxn(() async { @@ -453,59 +450,44 @@ class MainDB { // transactions for (int i = 0; i < transactionCount; i += paginateLimit) { - final txnIds = await getTransactions(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final txnIds = + await getTransactions( + walletId, + ).offset(i).limit(paginateLimit).idProperty().findAll(); await isar.transactions.deleteAll(txnIds); } // transactions V2 for (int i = 0; i < transactionCountV2; i += paginateLimit) { - final txnIds = await isar.transactionV2s - .where() - .walletIdEqualTo(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final txnIds = + await isar.transactionV2s + .where() + .walletIdEqualTo(walletId) + .offset(i) + .limit(paginateLimit) + .idProperty() + .findAll(); await isar.transactionV2s.deleteAll(txnIds); } // addresses for (int i = 0; i < addressCount; i += paginateLimit) { - final addressIds = await getAddresses(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final addressIds = + await getAddresses( + walletId, + ).offset(i).limit(paginateLimit).idProperty().findAll(); await isar.addresses.deleteAll(addressIds); } // utxos for (int i = 0; i < utxoCount; i += paginateLimit) { - final utxoIds = await getUTXOs(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final utxoIds = + await getUTXOs( + walletId, + ).offset(i).limit(paginateLimit).idProperty().findAll(); await isar.utxos.deleteAll(utxoIds); } - // lelantusCoins - await isar.lelantusCoins.where().walletIdEqualTo(walletId).deleteAll(); - // for (int i = 0; i < lelantusCoinCount; i += paginateLimit) { - // final lelantusCoinIds = await isar.lelantusCoins - // .where() - // .walletIdEqualTo(walletId) - // .offset(i) - // .limit(paginateLimit) - // .idProperty() - // .findAll(); - // await isar.lelantusCoins.deleteAll(lelantusCoinIds); - // } - // spark coins await isar.sparkCoins .where() @@ -519,11 +501,10 @@ class MainDB { await isar.writeTxn(() async { const paginateLimit = 50; for (int i = 0; i < addressLabelCount; i += paginateLimit) { - final labelIds = await getAddressLabels(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final labelIds = + await getAddressLabels( + walletId, + ).offset(i).limit(paginateLimit).idProperty().findAll(); await isar.addressLabels.deleteAll(labelIds); } }); @@ -534,11 +515,10 @@ class MainDB { await isar.writeTxn(() async { const paginateLimit = 50; for (int i = 0; i < noteCount; i += paginateLimit) { - final labelIds = await getTransactionNotes(walletId) - .offset(i) - .limit(paginateLimit) - .idProperty() - .findAll(); + final labelIds = + await getTransactionNotes( + walletId, + ).offset(i).limit(paginateLimit).idProperty().findAll(); await isar.transactionNotes.deleteAll(labelIds); } }); @@ -591,10 +571,11 @@ class MainDB { final List ids = []; await isar.writeTxn(() async { for (final tx in transactions) { - final storedTx = await isar.transactionV2s - .where() - .txidWalletIdEqualTo(tx.txid, tx.walletId) - .findFirst(); + final storedTx = + await isar.transactionV2s + .where() + .txidWalletIdEqualTo(tx.txid, tx.walletId) + .findFirst(); Id id; if (storedTx == null) { @@ -630,22 +611,11 @@ class MainDB { isar.ethContracts.where().addressEqualTo(contractAddress).findFirstSync(); Future putEthContract(EthContract contract) => isar.writeTxn(() async { - return await isar.ethContracts.put(contract); - }); + return await isar.ethContracts.put(contract); + }); Future putEthContracts(List contracts) => isar.writeTxn(() async { await isar.ethContracts.putAll(contracts); }); - - // ========== Lelantus ======================================================= - - Future getHighestUsedMintIndex({required String walletId}) async { - return await isar.lelantusCoins - .where() - .walletIdEqualTo(walletId) - .sortByMintIndexDesc() - .mintIndexProperty() - .findFirst(); - } } diff --git a/lib/db/migrate_wallets_to_isar.dart b/lib/db/migrate_wallets_to_isar.dart index 1b5e98b5a..6433799f2 100644 --- a/lib/db/migrate_wallets_to_isar.dart +++ b/lib/db/migrate_wallets_to_isar.dart @@ -146,13 +146,6 @@ Future migrateWalletsToIsar({ otherData[WalletInfoKeys.epiccashData] = jsonEncode( epicWalletInfo.toMap(), ); - } else if (old.coinIdentifier == - Firo(CryptoCurrencyNetwork.main).identifier || - old.coinIdentifier == Firo(CryptoCurrencyNetwork.test).identifier) { - otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = - walletBox.get(WalletInfoKeys.lelantusCoinIsarRescanRequired) - as bool? ?? - true; } // diff --git a/lib/electrumx_rpc/cached_electrumx_client.dart b/lib/electrumx_rpc/cached_electrumx_client.dart index c3b8ab56a..7c23af401 100644 --- a/lib/electrumx_rpc/cached_electrumx_client.dart +++ b/lib/electrumx_rpc/cached_electrumx_client.dart @@ -9,9 +9,6 @@ */ import 'dart:convert'; -import 'dart:math'; - -import 'package:string_validator/string_validator.dart'; import '../db/hive/db.dart'; import '../utilities/logger.dart'; @@ -27,105 +24,17 @@ class CachedElectrumXClient { factory CachedElectrumXClient.from({ required ElectrumXClient electrumXClient, - }) => - CachedElectrumXClient( - electrumXClient: electrumXClient, - ); - - Future> getAnonymitySet({ - required String groupId, - String blockhash = "", - required CryptoCurrency cryptoCurrency, - }) async { - try { - final box = - await DB.instance.getAnonymitySetCacheBox(currency: cryptoCurrency); - final cachedSet = box.get(groupId) as Map?; - - Map set; - - // null check to see if there is a cached set - if (cachedSet == null) { - set = { - "setId": groupId, - "blockHash": blockhash, - "setHash": "", - "coins": [], - }; - } else { - set = Map.from(cachedSet); - } - - final newSet = await electrumXClient.getLelantusAnonymitySet( - groupId: groupId, - blockhash: set["blockHash"] as String, - ); - - // update set with new data - if (newSet["setHash"] != "" && set["setHash"] != newSet["setHash"]) { - set["setHash"] = !isHexadecimal(newSet["setHash"] as String) - ? base64ToHex(newSet["setHash"] as String) - : newSet["setHash"]; - set["blockHash"] = !isHexadecimal(newSet["blockHash"] as String) - ? base64ToReverseHex(newSet["blockHash"] as String) - : newSet["blockHash"]; - for (int i = (newSet["coins"] as List).length - 1; i >= 0; i--) { - final dynamic newCoin = newSet["coins"][i]; - final List 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], - ); - } catch (e) { - translatedCoin.add(newCoin[2]); - } - 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.d( - "Updated current anonymity set for ${cryptoCurrency.identifier} with group ID $groupId", - ); - } - - return set; - } catch (e, s) { - Logging.instance.e( - "Failed to process CachedElectrumX.getAnonymitySet(): ", - error: e, - stackTrace: s, - ); - rethrow; - } - } + }) => CachedElectrumXClient(electrumXClient: electrumXClient); String base64ToHex(String source) => - base64Decode(LineSplitter.split(source).join()) - .map((e) => e.toRadixString(16).padLeft(2, '0')) - .join(); + base64Decode( + LineSplitter.split(source).join(), + ).map((e) => e.toRadixString(16).padLeft(2, '0')).join(); String base64ToReverseHex(String source) => - base64Decode(LineSplitter.split(source).join()) - .reversed - .map((e) => e.toRadixString(16).padLeft(2, '0')) - .join(); + base64Decode( + LineSplitter.split(source).join(), + ).reversed.map((e) => e.toRadixString(16).padLeft(2, '0')).join(); /// Call electrumx getTransaction on a per coin basis, storing the result in local db if not already there. /// @@ -140,11 +49,8 @@ class CachedElectrumXClient { final cachedTx = box.get(txHash) as Map?; if (cachedTx == null) { - final Map result = - await electrumXClient.getTransaction( - txHash: txHash, - verbose: verbose, - ); + final Map result = await electrumXClient + .getTransaction(txHash: txHash, verbose: verbose); result.remove("hex"); result.remove("lelantusData"); @@ -171,57 +77,6 @@ class CachedElectrumXClient { } } - Future> getUsedCoinSerials({ - required CryptoCurrency cryptoCurrency, - int startNumber = 0, - }) async { - try { - final box = - await DB.instance.getUsedSerialsCacheBox(currency: cryptoCurrency); - - final _list = box.get("serials") as List?; - - final Set cachedSerials = - _list == null ? {} : List.from(_list).toSet(); - - startNumber = max( - max(0, startNumber), - cachedSerials.length - 100, // 100 being some arbitrary buffer - ); - - final serials = await electrumXClient.getLelantusUsedCoinSerials( - startNumber: startNumber, - ); - - final newSerials = List.from(serials["serials"] as List) - .map((e) => !isHexadecimal(e) ? base64ToHex(e) : e) - .toSet(); - - // ensure we are getting some overlap so we know we are not missing any - if (cachedSerials.isNotEmpty && newSerials.isNotEmpty) { - assert(cachedSerials.intersection(newSerials).isNotEmpty); - } - - cachedSerials.addAll(newSerials); - - final resultingList = cachedSerials.toList(); - - await box.put( - "serials", - resultingList, - ); - - return resultingList; - } catch (e, s) { - Logging.instance.e( - "Failed to process CachedElectrumX.getUsedCoinSerials(): ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - /// Clear all cached transactions for the specified coin Future clearSharedTransactionCache({ required CryptoCurrency cryptoCurrency, diff --git a/lib/models/isar/models/firo_specific/lelantus_coin.dart b/lib/models/isar/models/firo_specific/lelantus_coin.dart deleted file mode 100644 index ca4c11919..000000000 --- a/lib/models/isar/models/firo_specific/lelantus_coin.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:isar/isar.dart'; - -part 'lelantus_coin.g.dart'; - -@collection -class LelantusCoin { - Id id = Isar.autoIncrement; - - @Index() - final String walletId; - - final String txid; - - final String value; // can't use BigInt in isar :shrug: - - @Index( - unique: true, - replace: false, - composite: [ - CompositeIndex("walletId"), - ], - ) - final int mintIndex; - - final int anonymitySetId; - - final bool isUsed; - - final bool isJMint; - - final String? otherData; - - LelantusCoin({ - required this.walletId, - required this.txid, - required this.value, - required this.mintIndex, - required this.anonymitySetId, - required this.isUsed, - required this.isJMint, - required this.otherData, - }); - - LelantusCoin copyWith({ - String? walletId, - String? publicCoin, - String? txid, - String? value, - int? mintIndex, - int? anonymitySetId, - bool? isUsed, - bool? isJMint, - String? otherData, - }) { - return LelantusCoin( - walletId: walletId ?? this.walletId, - txid: txid ?? this.txid, - value: value ?? this.value, - mintIndex: mintIndex ?? this.mintIndex, - anonymitySetId: anonymitySetId ?? this.anonymitySetId, - isUsed: isUsed ?? this.isUsed, - isJMint: isJMint ?? this.isJMint, - otherData: otherData ?? this.otherData, - ); - } - - @override - String toString() { - return 'LelantusCoin{' - 'id: $id, ' - 'walletId: $walletId, ' - 'txid: $txid, ' - 'value: $value, ' - 'mintIndex: $mintIndex, ' - 'anonymitySetId: $anonymitySetId, ' - 'otherData: $otherData, ' - 'isJMint: $isJMint, ' - 'isUsed: $isUsed' - '}'; - } -} diff --git a/lib/models/isar/models/firo_specific/lelantus_coin.g.dart b/lib/models/isar/models/firo_specific/lelantus_coin.g.dart deleted file mode 100644 index 1c0f4d405..000000000 --- a/lib/models/isar/models/firo_specific/lelantus_coin.g.dart +++ /dev/null @@ -1,1629 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'lelantus_coin.dart'; - -// ************************************************************************** -// IsarCollectionGenerator -// ************************************************************************** - -// coverage:ignore-file -// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types - -extension GetLelantusCoinCollection on Isar { - IsarCollection get lelantusCoins => this.collection(); -} - -const LelantusCoinSchema = CollectionSchema( - name: r'LelantusCoin', - id: -6795633185033299066, - properties: { - r'anonymitySetId': PropertySchema( - id: 0, - name: r'anonymitySetId', - type: IsarType.long, - ), - r'isJMint': PropertySchema( - id: 1, - name: r'isJMint', - type: IsarType.bool, - ), - r'isUsed': PropertySchema( - id: 2, - name: r'isUsed', - type: IsarType.bool, - ), - r'mintIndex': PropertySchema( - id: 3, - name: r'mintIndex', - type: IsarType.long, - ), - r'otherData': PropertySchema( - id: 4, - name: r'otherData', - type: IsarType.string, - ), - r'txid': PropertySchema( - id: 5, - name: r'txid', - type: IsarType.string, - ), - r'value': PropertySchema( - id: 6, - name: r'value', - type: IsarType.string, - ), - r'walletId': PropertySchema( - id: 7, - name: r'walletId', - type: IsarType.string, - ) - }, - estimateSize: _lelantusCoinEstimateSize, - serialize: _lelantusCoinSerialize, - deserialize: _lelantusCoinDeserialize, - deserializeProp: _lelantusCoinDeserializeProp, - idName: r'id', - indexes: { - r'walletId': IndexSchema( - id: -1783113319798776304, - name: r'walletId', - unique: false, - replace: false, - properties: [ - IndexPropertySchema( - name: r'walletId', - type: IndexType.hash, - caseSensitive: true, - ) - ], - ), - r'mintIndex_walletId': IndexSchema( - id: -9147309777276196770, - name: r'mintIndex_walletId', - unique: true, - replace: false, - properties: [ - IndexPropertySchema( - name: r'mintIndex', - type: IndexType.value, - caseSensitive: false, - ), - IndexPropertySchema( - name: r'walletId', - type: IndexType.hash, - caseSensitive: true, - ) - ], - ) - }, - links: {}, - embeddedSchemas: {}, - getId: _lelantusCoinGetId, - getLinks: _lelantusCoinGetLinks, - attach: _lelantusCoinAttach, - version: '3.1.8', -); - -int _lelantusCoinEstimateSize( - LelantusCoin object, - List offsets, - Map> allOffsets, -) { - var bytesCount = offsets.last; - { - final value = object.otherData; - if (value != null) { - bytesCount += 3 + value.length * 3; - } - } - bytesCount += 3 + object.txid.length * 3; - bytesCount += 3 + object.value.length * 3; - bytesCount += 3 + object.walletId.length * 3; - return bytesCount; -} - -void _lelantusCoinSerialize( - LelantusCoin object, - IsarWriter writer, - List offsets, - Map> allOffsets, -) { - writer.writeLong(offsets[0], object.anonymitySetId); - writer.writeBool(offsets[1], object.isJMint); - writer.writeBool(offsets[2], object.isUsed); - writer.writeLong(offsets[3], object.mintIndex); - writer.writeString(offsets[4], object.otherData); - writer.writeString(offsets[5], object.txid); - writer.writeString(offsets[6], object.value); - writer.writeString(offsets[7], object.walletId); -} - -LelantusCoin _lelantusCoinDeserialize( - Id id, - IsarReader reader, - List offsets, - Map> allOffsets, -) { - final object = LelantusCoin( - anonymitySetId: reader.readLong(offsets[0]), - isJMint: reader.readBool(offsets[1]), - isUsed: reader.readBool(offsets[2]), - mintIndex: reader.readLong(offsets[3]), - otherData: reader.readStringOrNull(offsets[4]), - txid: reader.readString(offsets[5]), - value: reader.readString(offsets[6]), - walletId: reader.readString(offsets[7]), - ); - object.id = id; - return object; -} - -P _lelantusCoinDeserializeProp

    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

    }>_mBfU=E=vfcfGy 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ఞ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%0A{b*LUw17QtfA{1P(88s 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%0DGbAa@f2Oq2<~vE$AdAKm6mq10jlT%ZJB6 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�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.VX~*IfvhrFDG|m>)CW&_3@t;v;Vz!`D0$2 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�O8Dvy4_~Tcv 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%0DZyS6?54zV%LtU2n(15rn$+@ta?!LD^fo^b@N$ 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� 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%0DM2wjK0%6l8X% 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

}>_mBfU=E=vfcfGy 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