From 46d5f260541200d019d138db7f0993848203328e Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 19 Oct 2022 14:21:48 -0600 Subject: [PATCH 1/6] fix bitcoin cash null errors --- .../coins/bitcoincash/bitcoincash_wallet.dart | 69 ++++++++++++++----- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 30f04e9183..5708ee7356 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -43,7 +43,7 @@ import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; -const int MINIMUM_CONFIRMATIONS = 3; +const int MINIMUM_CONFIRMATIONS = 1; const int DUST_LIMIT = 546; const String GENESIS_HASH_MAINNET = @@ -265,6 +265,9 @@ class BitcoinCashWallet extends CoinServiceAPI { DerivePathType addressType({required String address}) { Uint8List? decodeBase58; Segwit? decodeBech32; + if (Bitbox.Address.detectFormat(address) == 0) { + address = Bitbox.Address.toLegacyAddress(address); + } try { decodeBase58 = bs58check.decode(address); } catch (err) { @@ -825,9 +828,6 @@ class BitcoinCashWallet extends CoinServiceAPI { /// Refreshes display data for the wallet @override Future refresh() async { - final bchaddr = Bitbox.Address.toCashAddress(await currentReceivingAddress); - print("bchaddr: $bchaddr ${await currentReceivingAddress}"); - if (refreshMutex) { Logging.instance.log("$walletId $walletName refreshMutex denied", level: LogLevel.Info); @@ -1384,7 +1384,9 @@ class BitcoinCashWallet extends CoinServiceAPI { initialChangeAddressP2SH, 1, DerivePathType.bip49); // this._currentReceivingAddress = Future(() => initialReceivingAddress); - _currentReceivingAddressP2PKH = Future(() => initialReceivingAddressP2PKH); + + var newaddr = await _getCurrentAddressForChain(0, DerivePathType.bip44); + _currentReceivingAddressP2PKH = Future(() => newaddr); _currentReceivingAddressP2SH = Future(() => initialReceivingAddressP2SH); Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info); @@ -1521,6 +1523,11 @@ class BitcoinCashWallet extends CoinServiceAPI { print("Array key is ${jsonEncode(arrayKey)}"); final internalChainArray = DB.instance.get(boxName: walletId, key: arrayKey); + if (derivePathType == DerivePathType.bip44) { + if (Bitbox.Address.detectFormat(internalChainArray.last as String) == 1) { + return Bitbox.Address.toCashAddress(internalChainArray.last as String); + } + } return internalChainArray.last as String; } @@ -1986,6 +1993,9 @@ class BitcoinCashWallet extends CoinServiceAPI { /// Returns the scripthash or throws an exception on invalid bch address String _convertToScriptHash(String bchAddress, NetworkType network) { try { + if (Bitbox.Address.detectFormat(bchAddress) == 0) { + bchAddress = Bitbox.Address.toLegacyAddress(bchAddress); + } final output = Address.addressToOutputScript(bchAddress, network); final hash = sha256.convert(output.toList(growable: false)).toString(); @@ -2058,11 +2068,27 @@ class BitcoinCashWallet extends CoinServiceAPI { } Future _fetchTransactionData() async { - final List allAddresses = await _fetchAllOwnAddresses(); + List allAddressesOld = await _fetchAllOwnAddresses(); + List allAddresses = []; + for (String address in allAddressesOld) { + if (Bitbox.Address.detectFormat(address) == 1) { + allAddresses.add(Bitbox.Address.toCashAddress(address)); + } else { + allAddresses.add(address); + } + } - final changeAddressesP2PKH = + var changeAddressesP2PKHOld = DB.instance.get(boxName: walletId, key: 'changeAddressesP2PKH') as List; + List changeAddressesP2PKH = []; + for (var address in changeAddressesP2PKHOld) { + if (Bitbox.Address.detectFormat(address as String) == 1) { + changeAddressesP2PKH.add(Bitbox.Address.toCashAddress(address)); + } else { + changeAddressesP2PKH.add(address); + } + } final List> allTxHashes = await _fetchHistory(allAddresses); @@ -2166,7 +2192,8 @@ class BitcoinCashWallet extends CoinServiceAPI { .log("recipientsArray: $recipientsArray", level: LogLevel.Info); final foundInSenders = - allAddresses.any((element) => sendersArray.contains(element)); + allAddresses.any((element) => sendersArray.contains(element)) || + allAddressesOld.any((element) => sendersArray.contains(element)); Logging.instance .log("foundInSenders: $foundInSenders", level: LogLevel.Info); @@ -2228,7 +2255,8 @@ class BitcoinCashWallet extends CoinServiceAPI { .toBigInt() .toInt(); totalOut += value; - if (allAddresses.contains(address)) { + if (allAddresses.contains(address) || + allAddressesOld.contains(address)) { outputAmtAddressedToWallet += value; } } @@ -2743,7 +2771,10 @@ class BitcoinCashWallet extends CoinServiceAPI { for (final output in tx["vout"] as List) { final n = output["n"]; if (n != null && n == utxosToUse[i].vout) { - final address = output["scriptPubKey"]["addresses"][0] as String; + String address = output["scriptPubKey"]["addresses"][0] as String; + if (Bitbox.Address.detectFormat(address) == 0) { + address = Bitbox.Address.toLegacyAddress(address); + } if (!addressTxid.containsKey(address)) { addressTxid[address] = []; } @@ -2772,8 +2803,13 @@ class BitcoinCashWallet extends CoinServiceAPI { derivePathType: DerivePathType.bip44, ); for (int i = 0; i < p2pkhLength; i++) { + String address = addressesP2PKH[i]; + if (Bitbox.Address.detectFormat(address) == 0) { + address = Bitbox.Address.toLegacyAddress(address); + } + // receives - final receiveDerivation = receiveDerivations[addressesP2PKH[i]]; + final receiveDerivation = receiveDerivations[address]; // if a match exists it will not be null if (receiveDerivation != null) { final data = P2PKH( @@ -2783,7 +2819,7 @@ class BitcoinCashWallet extends CoinServiceAPI { network: _network, ).data; - for (String tx in addressTxid[addressesP2PKH[i]]!) { + for (String tx in addressTxid[address]!) { results[tx] = { "output": data.output, "keyPair": ECPair.fromWIF( @@ -2794,7 +2830,7 @@ class BitcoinCashWallet extends CoinServiceAPI { } } else { // if its not a receive, check change - final changeDerivation = changeDerivations[addressesP2PKH[i]]; + final changeDerivation = changeDerivations[address]; // if a match exists it will not be null if (changeDerivation != null) { final data = P2PKH( @@ -2804,7 +2840,7 @@ class BitcoinCashWallet extends CoinServiceAPI { network: _network, ).data; - for (String tx in addressTxid[addressesP2PKH[i]]!) { + for (String tx in addressTxid[address]!) { results[tx] = { "output": data.output, "keyPair": ECPair.fromWIF( @@ -3377,8 +3413,9 @@ class BitcoinCashWallet extends CoinServiceAPI { 0, DerivePathType .bip44); // Add that new receiving address to the array of receiving addresses - _currentReceivingAddressP2PKH = Future(() => - newReceivingAddress); // Set the new receiving address that the service + var newaddr = await _getCurrentAddressForChain(0, DerivePathType.bip44); + _currentReceivingAddressP2PKH = Future( + () => newaddr); // Set the new receiving address that the service return true; } catch (e, s) { From 2a3997e8371904e8ef8c24426d8b4c69f2c1be36 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 19 Oct 2022 16:05:36 -0600 Subject: [PATCH 2/6] refresh bitcoin cash cache if it has old data --- .../coins/bitcoincash/bitcoincash_wallet.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 5708ee7356..314a03b096 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -2113,7 +2113,16 @@ class BitcoinCashWallet extends CoinServiceAPI { if (txHeight > 0 && txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) { if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) { - allTxHashes.remove(tx); + print(cachedTransactions.findTransaction(tx["tx_hash"] as String)); + print(unconfirmedCachedTransactions[tx["tx_hash"] as String]); + final cachedTx = + cachedTransactions.findTransaction(tx["tx_hash"] as String); + if (!(cachedTx != null && + addressType(address: cachedTx.address) == + DerivePathType.bip44 && + Bitbox.Address.detectFormat(cachedTx.address) == 1)) { + allTxHashes.remove(tx); + } } } } @@ -2122,7 +2131,6 @@ class BitcoinCashWallet extends CoinServiceAPI { List> allTransactions = []; for (final txHash in allTxHashes) { - Logging.instance.log("bch: $txHash", level: LogLevel.Info); final tx = await cachedElectrumXClient.getTransaction( txHash: txHash["tx_hash"] as String, verbose: true, From 27c2e3831131ab5a4b83b1fe8b3f82a4c8aa3b59 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 19 Oct 2022 16:16:00 -0600 Subject: [PATCH 3/6] fix bitcoin cash tests --- .../coins/bitcoincash/bitcoincash_wallet.dart | 8 +++++--- .../bitcoincash/bitcoincash_wallet_test.dart | 20 +++++-------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 314a03b096..3a5cebdece 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -265,9 +265,11 @@ class BitcoinCashWallet extends CoinServiceAPI { DerivePathType addressType({required String address}) { Uint8List? decodeBase58; Segwit? decodeBech32; - if (Bitbox.Address.detectFormat(address) == 0) { - address = Bitbox.Address.toLegacyAddress(address); - } + try { + if (Bitbox.Address.detectFormat(address) == 0) { + address = Bitbox.Address.toLegacyAddress(address); + } + } catch (e, s) {} try { decodeBase58 = bs58check.decode(address); } catch (err) { diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart index a9a7fdaf72..4c392fe816 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart @@ -26,7 +26,7 @@ import 'bitcoincash_wallet_test_parameters.dart'; void main() { group("bitcoincash constants", () { test("bitcoincash minimum confirmations", () async { - expect(MINIMUM_CONFIRMATIONS, 3); + expect(MINIMUM_CONFIRMATIONS, 1); }); test("bitcoincash dust limit", () async { expect(DUST_LIMIT, 546); @@ -831,18 +831,9 @@ void main() { await bch?.initializeNew(); await bch?.initializeExisting(); - expect( - Address.validateAddress( - await bch!.currentReceivingAddress, bitcoincashtestnet), - true); - expect( - Address.validateAddress( - await bch!.currentReceivingAddress, bitcoincashtestnet), - true); - expect( - Address.validateAddress( - await bch!.currentReceivingAddress, bitcoincashtestnet), - true); + expect(bch?.validateAddress(await bch!.currentReceivingAddress), true); + expect(bch?.validateAddress(await bch!.currentReceivingAddress), true); + expect(bch?.validateAddress(await bch!.currentReceivingAddress), true); verifyNever(client?.ping()).called(0); verify(client?.getServerFeatures()).called(1); @@ -884,8 +875,7 @@ void main() { expect(addresses?.length, 2); for (int i = 0; i < 2; i++) { - expect( - Address.validateAddress(addresses![i], bitcoincashtestnet), true); + expect(bch?.validateAddress(addresses![i]), true); } verifyNever(client?.ping()).called(0); From b8836397a9a49b85abcc81204e9e7b7e28f42ea2 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 19 Oct 2022 16:51:50 -0600 Subject: [PATCH 4/6] externalCalls set and db migration --- lib/main.dart | 11 +++++++++-- lib/services/price.dart | 7 ++++--- lib/utilities/constants.dart | 2 +- lib/utilities/db_version_migration.dart | 12 ++++++++++++ lib/utilities/prefs.dart | 9 +++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ad1ef9b7fd..eb7cd8e64a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -143,7 +143,12 @@ void main() async { boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ?? 0; if (dbVersion < Constants.currentHiveDbVersion) { - await DbVersionMigrator().migrate(dbVersion); + try { + await DbVersionMigrator().migrate(dbVersion); + } catch (e, s) { + Logging.instance.log("Cannot migrate database\n$e $s", + level: LogLevel.Error, printFullLength: true); + } } monero.onStartup(); @@ -231,7 +236,9 @@ class _MaterialAppWithThemeState extends ConsumerState // unawaited(_nodeService.updateCommunityNodes()); // run without awaiting - if (Constants.enableExchange && _prefs.externalCalls) { + if (Constants.enableExchange && + _prefs.externalCalls && + await _prefs.isExternalCallsSet()) { unawaited(ExchangeDataLoadingService().loadAll(ref)); } diff --git a/lib/services/price.dart b/lib/services/price.dart index 4f6650b060..b44e055d51 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -78,12 +78,12 @@ class PriceAPI { } final externalCalls = Prefs.instance.externalCalls; - if (!Logger.isTestEnv && !externalCalls) { + if ((!Logger.isTestEnv && !externalCalls) || + !(await Prefs.instance.isExternalCallsSet())) { Logging.instance.log("User does not want to use external calls", level: LogLevel.Info); return _cachedPrices; } - Map> result = {}; try { final uri = Uri.parse( @@ -123,7 +123,8 @@ class PriceAPI { static Future?> availableBaseCurrencies() async { final externalCalls = Prefs.instance.externalCalls; - if (!Logger.isTestEnv && !externalCalls) { + if ((!Logger.isTestEnv && !externalCalls) || + !(await Prefs.instance.isExternalCallsSet())) { Logging.instance.log("User does not want to use external calls", level: LogLevel.Info); return null; diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 4eb69d7e17..2495a6be42 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -36,7 +36,7 @@ abstract class Constants { // Enable Logger.print statements static const bool disableLogger = false; - static const int currentHiveDbVersion = 2; + static const int currentHiveDbVersion = 3; static List possibleLengthsForCoin(Coin coin) { final List values = []; diff --git a/lib/utilities/db_version_migration.dart b/lib/utilities/db_version_migration.dart index 26af1c48a5..d1763e266c 100644 --- a/lib/utilities/db_version_migration.dart +++ b/lib/utilities/db_version_migration.dart @@ -143,6 +143,18 @@ class DbVersionMigrator { // try to continue migrating return await migrate(2); + case 2: + await Hive.openBox(DB.boxNamePrefs); + final prefs = Prefs.instance; + await prefs.init(); + if (!(await prefs.isExternalCallsSet())) { + prefs.externalCalls = true; + } + + // update version + await DB.instance.put( + boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 3); + return await migrate(3); default: // finally return diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 2fc21a78d5..2462910532 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -571,4 +571,13 @@ class Prefs extends ChangeNotifier { boxName: DB.boxNamePrefs, key: "externalCalls") as bool? ?? true; } + + Future isExternalCallsSet() async { + if (await DB.instance + .get(boxName: DB.boxNamePrefs, key: "externalCalls") == + null) { + return false; + } + return true; + } } From 1dd5df5916b9c084132de3b6bf7f153b2f34c617 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 19 Oct 2022 17:24:28 -0600 Subject: [PATCH 5/6] v1.5.9 build 79 --- ios/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index ec3100f8ea..32c584797e 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -451,7 +451,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 78; + CURRENT_PROJECT_VERSION = 79; DEVELOPMENT_TEAM = 4DQKUWSG6C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -505,7 +505,7 @@ "$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**", "$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs", ); - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -635,7 +635,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 78; + CURRENT_PROJECT_VERSION = 79; DEVELOPMENT_TEAM = 4DQKUWSG6C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -689,7 +689,7 @@ "$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**", "$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs", ); - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -711,7 +711,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 78; + CURRENT_PROJECT_VERSION = 79; DEVELOPMENT_TEAM = 4DQKUWSG6C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -765,7 +765,7 @@ "$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**", "$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs", ); - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/pubspec.yaml b/pubspec.yaml index d4d3546256..517f6222eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.5.8+78 +version: 1.5.9+79 environment: sdk: ">=2.17.0 <3.0.0" From c55a7fb73d78dbe8cdd827f7a19266a7bcb5243e Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 19 Oct 2022 17:49:19 -0600 Subject: [PATCH 6/6] fix price test tests --- test/price_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/price_test.dart b/test/price_test.dart index b806bfd611..6abbb6741f 100644 --- a/test/price_test.dart +++ b/test/price_test.dart @@ -16,6 +16,9 @@ void main() { setUp(() async { await setUpTestHive(); await Hive.openBox(DB.boxNamePriceCache); + await Hive.openBox(DB.boxNamePrefs); + await DB.instance.put( + boxName: DB.boxNamePrefs, key: "externalCalls", value: true); }); test("getPricesAnd24hChange fetch", () async {