From f3325807e0f994c89e2f6f04377cfb8687d602b1 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 23 Jan 2023 10:32:53 -0600
Subject: [PATCH] null address fix

---
 .../coins/bitcoin/bitcoin_wallet.dart         | 52 +++++++++---------
 .../coins/bitcoincash/bitcoincash_wallet.dart | 52 +++++++++---------
 .../coins/dogecoin/dogecoin_wallet.dart       | 52 +++++++++---------
 lib/services/coins/firo/firo_wallet.dart      | 52 +++++++++---------
 .../coins/litecoin/litecoin_wallet.dart       | 52 +++++++++---------
 lib/services/coins/monero/monero_wallet.dart  |  2 +
 .../coins/namecoin/namecoin_wallet.dart       | 53 ++++++++++---------
 .../coins/particl/particl_wallet.dart         | 52 +++++++++---------
 .../coins/wownero/wownero_wallet.dart         |  9 ++--
 9 files changed, 189 insertions(+), 187 deletions(-)

diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart
index 9e8702ea3..d0b114829 100644
--- a/lib/services/coins/bitcoin/bitcoin_wallet.dart
+++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart
@@ -186,24 +186,28 @@ class BitcoinWallet extends CoinServiceAPI
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip84);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip84);
 
   @override
   Future<void> exit() async {
@@ -1164,6 +1168,8 @@ class BitcoinWallet extends CoinServiceAPI
     }
 
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // hack to add tx to txData before refresh completes
@@ -1857,7 +1863,7 @@ class BitcoinWallet extends CoinServiceAPI
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1876,12 +1882,9 @@ class BitcoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } catch (e, s) {
       Logging.instance.log(
@@ -1899,7 +1902,7 @@ class BitcoinWallet extends CoinServiceAPI
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1918,12 +1921,9 @@ class BitcoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart
index 1a6587e6b..70e3a5d55 100644
--- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart
+++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart
@@ -162,24 +162,28 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip44);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip44);
 
   @override
   Future<void> exit() async {
@@ -1093,6 +1097,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
     }
 
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // hack to add tx to txData before refresh completes
@@ -1740,7 +1746,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1759,12 +1765,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
@@ -1787,7 +1790,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1806,12 +1809,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart
index 63568cc59..1c083d3bd 100644
--- a/lib/services/coins/dogecoin/dogecoin_wallet.dart
+++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart
@@ -161,25 +161,29 @@ class DogecoinWallet extends CoinServiceAPI
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip44);
 
   // @override
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip44);
 
   @override
   Future<void> exit() async {
@@ -999,6 +1003,8 @@ class DogecoinWallet extends CoinServiceAPI
     }
 
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // hack to add tx to txData before refresh completes
@@ -1645,7 +1651,7 @@ class DogecoinWallet extends CoinServiceAPI
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1664,12 +1670,9 @@ class DogecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
@@ -1692,7 +1695,7 @@ class DogecoinWallet extends CoinServiceAPI
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1711,12 +1714,9 @@ class DogecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await checkChangeAddressForTransactions();
       }
     } catch (e, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart
index 0962e6fdc..ec63db186 100644
--- a/lib/services/coins/firo/firo_wallet.dart
+++ b/lib/services/coins/firo/firo_wallet.dart
@@ -871,24 +871,28 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2pkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2pkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0);
 
   late String _walletName;
   @override
@@ -1831,6 +1835,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
           "Attempted to initialize an existing wallet using an unknown wallet ID!");
     }
     await _prefs.init();
+    await checkChangeAddressForTransactions();
+    await checkReceivingAddressForTransactions();
   }
 
   Future<bool> refreshIfThereIsNewData() async {
@@ -3144,7 +3150,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -3165,12 +3171,9 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await checkReceivingAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
@@ -3194,7 +3197,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
           'Number of txs for current change address: $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -3215,12 +3218,9 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart
index d0c922afa..fe1fdf13c 100644
--- a/lib/services/coins/litecoin/litecoin_wallet.dart
+++ b/lib/services/coins/litecoin/litecoin_wallet.dart
@@ -186,24 +186,28 @@ class LitecoinWallet extends CoinServiceAPI
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip84);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip84);
 
   @override
   Future<void> exit() async {
@@ -1182,6 +1186,8 @@ class LitecoinWallet extends CoinServiceAPI
           "Attempted to initialize an existing wallet using an unknown wallet ID!");
     }
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // hack to add tx to txData before refresh completes
@@ -1880,7 +1886,7 @@ class LitecoinWallet extends CoinServiceAPI
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1899,12 +1905,9 @@ class LitecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } catch (e, s) {
       Logging.instance.log(
@@ -1922,7 +1925,7 @@ class LitecoinWallet extends CoinServiceAPI
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1941,12 +1944,9 @@ class LitecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart
index ee3807163..d46595ec4 100644
--- a/lib/services/coins/monero/monero_wallet.dart
+++ b/lib/services/coins/monero/monero_wallet.dart
@@ -288,6 +288,8 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
     }
     walletBase = (await walletService!.openWallet(_walletId, password))
         as MoneroWalletBase;
+
+    await _checkCurrentReceivingAddressesForTransactions();
     // walletBase!.onNewBlock = onNewBlock;
     // walletBase!.onNewTransaction = onNewTransaction;
     // walletBase!.syncStatusChanged = syncStatusChanged;
diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart
index e9ef15b90..cae6cf29a 100644
--- a/lib/services/coins/namecoin/namecoin_wallet.dart
+++ b/lib/services/coins/namecoin/namecoin_wallet.dart
@@ -181,24 +181,28 @@ class NamecoinWallet extends CoinServiceAPI
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip84);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip84);
 
   @override
   Future<void> exit() async {
@@ -1171,6 +1175,8 @@ class NamecoinWallet extends CoinServiceAPI
           "Attempted to initialize an existing wallet using an unknown wallet ID!");
     }
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // hack to add tx to txData before refresh completes
@@ -1862,7 +1868,7 @@ class NamecoinWallet extends CoinServiceAPI
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1881,12 +1887,9 @@ class NamecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } catch (e, s) {
       Logging.instance.log(
@@ -1904,7 +1907,7 @@ class NamecoinWallet extends CoinServiceAPI
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1923,12 +1926,10 @@ class NamecoinWallet extends CoinServiceAPI
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkChangeAddressForTransactions();
         }
+
+        // keep checking until address with no tx history is set as current
+        await _checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart
index e705a6178..d19fdf769 100644
--- a/lib/services/coins/particl/particl_wallet.dart
+++ b/lib/services/coins/particl/particl_wallet.dart
@@ -176,24 +176,28 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
   Future<String> get currentReceivingAddress async =>
       (await _currentReceivingAddress).value;
 
-  Future<isar_models.Address> get _currentReceivingAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.receiving)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentReceivingAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.receiving)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(0, 0, DerivePathType.bip84);
 
   Future<String> get currentChangeAddress async =>
       (await _currentChangeAddress).value;
 
-  Future<isar_models.Address> get _currentChangeAddress async => (await db
-      .getAddresses(walletId)
-      .filter()
-      .typeEqualTo(isar_models.AddressType.p2wpkh)
-      .subTypeEqualTo(isar_models.AddressSubType.change)
-      .sortByDerivationIndexDesc()
-      .findFirst())!;
+  Future<isar_models.Address> get _currentChangeAddress async =>
+      (await db
+          .getAddresses(walletId)
+          .filter()
+          .typeEqualTo(isar_models.AddressType.p2wpkh)
+          .subTypeEqualTo(isar_models.AddressSubType.change)
+          .sortByDerivationIndexDesc()
+          .findFirst()) ??
+      await _generateAddressForChain(1, 0, DerivePathType.bip84);
 
   @override
   Future<void> exit() async {
@@ -1100,6 +1104,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
           "Attempted to initialize an existing wallet using an unknown wallet ID!");
     }
     await _prefs.init();
+    await _checkCurrentChangeAddressesForTransactions();
+    await _checkCurrentReceivingAddressesForTransactions();
   }
 
   // TODO make sure this copied implementation from bitcoin_wallet.dart applies for particl just as well--or import it
@@ -1749,7 +1755,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
           'Number of txs for current receiving address $currentReceiving: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentReceiving.derivationIndex < 0) {
         // First increment the receiving index
         final newReceivingIndex = currentReceiving.derivationIndex + 1;
 
@@ -1768,12 +1774,9 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } catch (e, s) {
       Logging.instance.log(
@@ -1791,7 +1794,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
           'Number of txs for current change address $currentChange: $txCount',
           level: LogLevel.Info);
 
-      if (txCount >= 1) {
+      if (txCount >= 1 || currentChange.derivationIndex < 0) {
         // First increment the change index
         final newChangeIndex = currentChange.derivationIndex + 1;
 
@@ -1810,12 +1813,9 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newChangeAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkChangeAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkChangeAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(
diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart
index d471208cd..b1afa561d 100644
--- a/lib/services/coins/wownero/wownero_wallet.dart
+++ b/lib/services/coins/wownero/wownero_wallet.dart
@@ -306,6 +306,8 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
     walletBase = (await walletService?.openWallet(_walletId, password!))
         as WowneroWalletBase;
 
+    await _checkCurrentReceivingAddressesForTransactions();
+
     Logging.instance.log(
       "Opened existing ${coin.prettyName} wallet $walletName",
       level: LogLevel.Info,
@@ -1245,12 +1247,9 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
         } else {
           // we need to update the address
           await db.updateAddress(existing, newReceivingAddress);
-
-          // since we updated an existing address there is a chance it has
-          // some tx history. To prevent address reuse we will call check again
-          // recursively
-          await _checkReceivingAddressForTransactions();
         }
+        // keep checking until address with no tx history is set as current
+        await _checkReceivingAddressForTransactions();
       }
     } on SocketException catch (se, s) {
       Logging.instance.log(