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/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/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 30f04e9183..3a5cebdece 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,11 @@ class BitcoinCashWallet extends CoinServiceAPI { DerivePathType addressType({required String address}) { Uint8List? decodeBase58; Segwit? decodeBech32; + try { + if (Bitbox.Address.detectFormat(address) == 0) { + address = Bitbox.Address.toLegacyAddress(address); + } + } catch (e, s) {} try { decodeBase58 = bs58check.decode(address); } catch (err) { @@ -825,9 +830,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 +1386,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 +1525,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 +1995,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 +2070,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); @@ -2087,7 +2115,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); + } } } } @@ -2096,7 +2133,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, @@ -2166,7 +2202,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 +2265,8 @@ class BitcoinCashWallet extends CoinServiceAPI { .toBigInt() .toInt(); totalOut += value; - if (allAddresses.contains(address)) { + if (allAddresses.contains(address) || + allAddressesOld.contains(address)) { outputAmtAddressedToWallet += value; } } @@ -2743,7 +2781,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 +2813,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 +2829,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 +2840,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 +2850,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 +3423,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) { 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; + } } 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" 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 { 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);