diff --git a/lib/electrumx_rpc/cached_electrumx.dart b/lib/electrumx_rpc/cached_electrumx.dart
index 935e8605e..2aab533f8 100644
--- a/lib/electrumx_rpc/cached_electrumx.dart
+++ b/lib/electrumx_rpc/cached_electrumx.dart
@@ -115,8 +115,9 @@ class CachedElectrumX {
             key: groupId,
             value: set);
         Logging.instance.log(
-            "Updated currently anonymity set for ${coin.name} with group ID $groupId",
-            level: LogLevel.Info);
+          "Updated current anonymity set for ${coin.name} with group ID $groupId",
+          level: LogLevel.Info,
+        );
       }
 
       return set;
@@ -187,16 +188,17 @@ class CachedElectrumX {
     }
   }
 
-  Future<List<dynamic>> getUsedCoinSerials({
+  Future<List<String>> getUsedCoinSerials({
     required Coin coin,
     int startNumber = 0,
   }) async {
     try {
-      List<dynamic>? cachedSerials = DB.instance.get<dynamic>(
+      final _list = DB.instance.get<dynamic>(
           boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
           key: "serials") as List?;
 
-      cachedSerials ??= [];
+      List<String> cachedSerials =
+          _list == null ? [] : List<String>.from(_list);
 
       final startNumber = cachedSerials.length;
 
@@ -210,8 +212,9 @@ class CachedElectrumX {
           );
 
       final serials = await client.getUsedCoinSerials(startNumber: startNumber);
-      List newSerials = [];
-      for (var element in (serials["serials"] as List)) {
+      List<String> newSerials = [];
+
+      for (final element in (serials["serials"] as List)) {
         if (!isHexadecimal(element as String)) {
           newSerials.add(base64ToHex(element));
         } else {
@@ -221,9 +224,10 @@ class CachedElectrumX {
       cachedSerials.addAll(newSerials);
 
       await DB.instance.put<dynamic>(
-          boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
-          key: "serials",
-          value: cachedSerials);
+        boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
+        key: "serials",
+        value: cachedSerials,
+      );
 
       return cachedSerials;
     } catch (e, s) {
diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart
index 57e916e2e..23e367ca4 100644
--- a/lib/services/coins/firo/firo_wallet.dart
+++ b/lib/services/coins/firo/firo_wallet.dart
@@ -4,6 +4,7 @@ import 'dart:io';
 import 'dart:isolate';
 import 'dart:math';
 
+import 'package:bip32/bip32.dart' as bip32;
 import 'package:bip39/bip39.dart' as bip39;
 import 'package:bitcoindart/bitcoindart.dart';
 import 'package:decimal/decimal.dart';
@@ -145,37 +146,25 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
     } else if (function == "restore") {
       final latestSetId = arguments['latestSetId'] as int;
       final setDataMap = arguments['setDataMap'] as Map;
-      final usedSerialNumbers = arguments['usedSerialNumbers'] as List?;
+      final usedSerialNumbers = arguments['usedSerialNumbers'] as List<String>;
       final mnemonic = arguments['mnemonic'] as String;
       final mnemonicPassphrase = arguments['mnemonicPassphrase'] as String;
       final coin = arguments['coin'] as Coin;
-      final network = arguments['network'] as NetworkType?;
-      if (!(usedSerialNumbers == null || network == null)) {
-        var restoreData = await isolateRestore(
-          mnemonic,
-          mnemonicPassphrase,
-          coin,
-          latestSetId,
-          setDataMap,
-          usedSerialNumbers,
-          network,
-        );
-        sendPort.send(restoreData);
-        return;
-      }
-    } else if (function == "isolateDerive") {
-      final mnemonic = arguments['mnemonic'] as String;
-      final mnemonicPassphrase = arguments['mnemonicPassphrase'] as String;
-      final from = arguments['from'] as int;
-      final to = arguments['to'] as int;
-      final network = arguments['network'] as NetworkType?;
-      if (!(network == null)) {
-        var derived = await isolateDerive(
-            mnemonic, mnemonicPassphrase, from, to, network);
-        sendPort.send(derived);
-        return;
-      }
+      final network = arguments['network'] as NetworkType;
+
+      final restoreData = await isolateRestore(
+        mnemonic,
+        mnemonicPassphrase,
+        coin,
+        latestSetId,
+        setDataMap,
+        usedSerialNumbers,
+        network,
+      );
+      sendPort.send(restoreData);
+      return;
     }
+
     Logging.instance.log(
         "Error Arguments for $function not formatted correctly",
         level: LogLevel.Fatal);
@@ -199,76 +188,13 @@ void stop(ReceivePort port) {
   }
 }
 
-Future<Map<String, dynamic>> isolateDerive(
-  String mnemonic,
-  String mnemonicPassphrase,
-  int from,
-  int to,
-  NetworkType _network,
-) async {
-  Map<String, dynamic> result = {};
-  Map<String, dynamic> allReceive = {};
-  Map<String, dynamic> allChange = {};
-  final root = await Bip32Utils.getBip32Root(
-    mnemonic,
-    mnemonicPassphrase,
-    _network,
-  );
-
-  for (int i = from; i < to; i++) {
-    final derivePathReceiving = constructDerivePath(
-      networkWIF: _network.wif,
-      chain: 0,
-      index: i,
-    );
-    var currentNode = await Bip32Utils.getBip32NodeFromRoot(
-      root,
-      derivePathReceiving,
-    );
-    var address = P2PKH(
-            network: _network, data: PaymentData(pubkey: currentNode.publicKey))
-        .data
-        .address!;
-    allReceive["$i"] = {
-      "publicKey": Format.uint8listToString(currentNode.publicKey),
-      "wif": currentNode.toWIF(),
-      "address": address,
-    };
-
-    final derivePathChange = constructDerivePath(
-      networkWIF: _network.wif,
-      chain: 1,
-      index: i,
-    );
-    currentNode = await Bip32Utils.getBip32NodeFromRoot(
-      root,
-      derivePathChange,
-    );
-    address = P2PKH(
-            network: _network, data: PaymentData(pubkey: currentNode.publicKey))
-        .data
-        .address!;
-    allChange["$i"] = {
-      "publicKey": Format.uint8listToString(currentNode.publicKey),
-      "wif": currentNode.toWIF(),
-      "address": address,
-    };
-    if (i % 50 == 0) {
-      Logging.instance.log("thread at $i", level: LogLevel.Info);
-    }
-  }
-  result['receive'] = allReceive;
-  result['change'] = allChange;
-  return result;
-}
-
 Future<Map<String, dynamic>> isolateRestore(
   String mnemonic,
   String mnemonicPassphrase,
   Coin coin,
   int _latestSetId,
   Map<dynamic, dynamic> _setDataMap,
-  List<dynamic> _usedSerialNumbers,
+  List<String> _usedSerialNumbers,
   NetworkType network,
 ) async {
   List<int> jindexes = [];
@@ -279,11 +205,7 @@ Future<Map<String, dynamic>> isolateRestore(
   var currentIndex = 0;
 
   try {
-    final usedSerialNumbers = _usedSerialNumbers;
-    Set<dynamic> usedSerialNumbersSet = {};
-    for (int ind = 0; ind < usedSerialNumbers.length; ind++) {
-      usedSerialNumbersSet.add(usedSerialNumbers[ind]);
-    }
+    Set<String> usedSerialNumbersSet = _usedSerialNumbers.toSet();
 
     final root = await Bip32Utils.getBip32Root(
       mnemonic,
@@ -296,43 +218,60 @@ Future<Map<String, dynamic>> isolateRestore(
         chain: MINT_INDEX,
         index: currentIndex,
       );
-      final mintKeyPair =
-          await Bip32Utils.getBip32NodeFromRoot(root, _derivePath);
-      final mintTag = CreateTag(
-          Format.uint8listToString(mintKeyPair.privateKey!),
-          currentIndex,
-          Format.uint8listToString(mintKeyPair.identifier),
-          isTestnet: coin == Coin.firoTestNet);
+      final bip32.BIP32 mintKeyPair = await Bip32Utils.getBip32NodeFromRoot(
+        root,
+        _derivePath,
+      );
+      final String mintTag = CreateTag(
+        Format.uint8listToString(mintKeyPair.privateKey!),
+        currentIndex,
+        Format.uint8listToString(mintKeyPair.identifier),
+        isTestnet: coin == Coin.firoTestNet,
+      );
 
       for (var setId = 1; setId <= _latestSetId; setId++) {
-        final setData = _setDataMap[setId];
-        final foundCoin = setData["coins"].firstWhere(
-            (dynamic e) => e[1] == mintTag,
-            orElse: () => <Object>[]);
+        final setData = _setDataMap[setId] as Map;
+        final foundCoin = (setData["coins"] as List).firstWhere(
+          (e) => e[1] == mintTag,
+          orElse: () => <Object>[],
+        );
 
         if (foundCoin.length == 4) {
           lastFoundIndex = currentIndex;
-          if (foundCoin[2] is int) {
-            final amount = foundCoin[2] as int;
-            final serialNumber = GetSerialNumber(amount,
-                Format.uint8listToString(mintKeyPair.privateKey!), currentIndex,
-                isTestnet: coin == Coin.firoTestNet);
-            String publicCoin = foundCoin[0] as String;
-            String txId = foundCoin[3] as String;
-            bool isUsed = usedSerialNumbersSet.contains(serialNumber);
-            final duplicateCoin = lelantusCoins.firstWhere((element) {
-              final coin = element.values.first;
-              return coin.txId == txId &&
-                  coin.index == currentIndex &&
-                  coin.anonymitySetId != setId;
-            }, orElse: () => {});
+
+          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 = GetSerialNumber(
+              amount,
+              Format.uint8listToString(mintKeyPair.privateKey!),
+              currentIndex,
+              isTestnet: coin == Coin.firoTestNet,
+            );
+            final bool isUsed = usedSerialNumbersSet.contains(serialNumber);
+            final duplicateCoin = lelantusCoins.firstWhere(
+              (element) {
+                final coin = element.values.first;
+                return coin.txId == txId &&
+                    coin.index == currentIndex &&
+                    coin.anonymitySetId != setId;
+              },
+              orElse: () => {},
+            );
             if (duplicateCoin.isNotEmpty) {
-              //todo: check if print needed
-              // debugPrint("removing duplicate: $duplicateCoin");
+              Logging.instance.log(
+                "Firo isolateRestore removing duplicate coin: $duplicateCoin",
+                level: LogLevel.Info,
+              );
               lelantusCoins.remove(duplicateCoin);
             }
             lelantusCoins.add({
-              publicCoin: LelantusCoin(
+              txId: LelantusCoin(
                 currentIndex,
                 amount,
                 publicCoin,
@@ -341,47 +280,56 @@ Future<Map<String, dynamic>> isolateRestore(
                 isUsed,
               )
             });
-            Logging.instance
-                .log("amount $amount used $isUsed", level: LogLevel.Info);
-          } else {
-            final keyPath = GetAesKeyPath(foundCoin[0] as String);
-            final derivePath = constructDerivePath(
+            Logging.instance.log(
+              "amount $amount used $isUsed",
+              level: LogLevel.Info,
+            );
+          } else if (thirdValue is String) {
+            final int keyPath = GetAesKeyPath(publicCoin);
+            final String derivePath = constructDerivePath(
               networkWIF: network.wif,
               chain: JMINT_INDEX,
               index: keyPath,
             );
-            final aesKeyPair =
-                await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
+            final aesKeyPair = await Bip32Utils.getBip32NodeFromRoot(
+              root,
+              derivePath,
+            );
 
             if (aesKeyPair.privateKey != null) {
-              final aesPrivateKey =
-                  Format.uint8listToString(aesKeyPair.privateKey!);
-              final amount = decryptMintAmount(
+              final String aesPrivateKey = Format.uint8listToString(
+                aesKeyPair.privateKey!,
+              );
+              final int amount = decryptMintAmount(
                 aesPrivateKey,
-                foundCoin[2] as String,
+                thirdValue,
               );
 
-              final serialNumber = GetSerialNumber(
-                  amount,
-                  Format.uint8listToString(mintKeyPair.privateKey!),
-                  currentIndex,
-                  isTestnet: coin == Coin.firoTestNet);
-              String publicCoin = foundCoin[0] as String;
-              String txId = foundCoin[3] as String;
+              final String serialNumber = GetSerialNumber(
+                amount,
+                Format.uint8listToString(mintKeyPair.privateKey!),
+                currentIndex,
+                isTestnet: coin == Coin.firoTestNet,
+              );
               bool isUsed = usedSerialNumbersSet.contains(serialNumber);
-              final duplicateCoin = lelantusCoins.firstWhere((element) {
-                final coin = element.values.first;
-                return coin.txId == txId &&
-                    coin.index == currentIndex &&
-                    coin.anonymitySetId != setId;
-              }, orElse: () => {});
+              final duplicateCoin = lelantusCoins.firstWhere(
+                (element) {
+                  final coin = element.values.first;
+                  return coin.txId == txId &&
+                      coin.index == currentIndex &&
+                      coin.anonymitySetId != setId;
+                },
+                orElse: () => {},
+              );
               if (duplicateCoin.isNotEmpty) {
-                //todo: check if print needed
-                // debugPrint("removing duplicate: $duplicateCoin");
+                Logging.instance.log(
+                  "Firo isolateRestore removing duplicate coin: $duplicateCoin",
+                  level: LogLevel.Info,
+                );
                 lelantusCoins.remove(duplicateCoin);
               }
               lelantusCoins.add({
-                '${foundCoin[3]!}': LelantusCoin(
+                txId: LelantusCoin(
                   currentIndex,
                   amount,
                   publicCoin,
@@ -392,9 +340,24 @@ Future<Map<String, dynamic>> isolateRestore(
               });
               jindexes.add(currentIndex);
 
-              spendTxIds.add(foundCoin[3] as String);
+              spendTxIds.add(txId);
+            } else {
+              Logging.instance.log(
+                "AES keypair derivation issue for derive path: $derivePath",
+                level: LogLevel.Warning,
+              );
             }
+          } else {
+            Logging.instance.log(
+              "Unexpected coin found: $foundCoin",
+              level: LogLevel.Warning,
+            );
           }
+        } else {
+          Logging.instance.log(
+            "Coin not found in data with the mint tag: $mintTag",
+            level: LogLevel.Warning,
+          );
         }
       }
 
@@ -900,6 +863,7 @@ class FiroWallet extends CoinServiceAPI
       .or()
       .isLelantusEqualTo(false)
       .findAll();
+
   // _transactionData ??= _refreshTransactions();
 
   // models.TransactionData? cachedTxData;
@@ -943,10 +907,12 @@ class FiroWallet extends CoinServiceAPI
 
   /// Holds the max fee that can be sent
   Future<int>? _maxFee;
+
   @override
   Future<int> get maxFee => _maxFee ??= _fetchMaxFee();
 
   Future<FeeObject>? _feeObject;
+
   @override
   Future<FeeObject> get fees => _feeObject ??= _getFees();
 
@@ -978,6 +944,7 @@ class FiroWallet extends CoinServiceAPI
       await _generateAddressForChain(1, 0);
 
   late String _walletName;
+
   @override
   String get walletName => _walletName;
 
@@ -987,6 +954,7 @@ class FiroWallet extends CoinServiceAPI
 
   /// unique wallet id
   late final String _walletId;
+
   @override
   String get walletId => _walletId;
 
@@ -1287,9 +1255,11 @@ class FiroWallet extends CoinServiceAPI
   }
 
   late ElectrumX _electrumXClient;
+
   ElectrumX get electrumXClient => _electrumXClient;
 
   late CachedElectrumX _cachedElectrumXClient;
+
   CachedElectrumX get cachedElectrumXClient => _cachedElectrumXClient;
 
   late SecureStorageInterface _secureStore;
@@ -1703,66 +1673,65 @@ class FiroWallet extends CoinServiceAPI
         String? pubKey;
         String? wif;
 
-        // fetch receiving derivations if null
-        receiveDerivations[sd.derivePathType] ??= Map<String, dynamic>.from(
-          jsonDecode((await _secureStore.read(
-                key: "${walletId}_receiveDerivations",
-              )) ??
-              "{}") as Map,
-        );
+        final address = await db.getAddress(walletId, sd.utxo.address!);
+        if (address?.derivationPath != null) {
+          final node = await Bip32Utils.getBip32Node(
+            (await mnemonicString)!,
+            (await mnemonicPassphrase)!,
+            _network,
+            address!.derivationPath!.value,
+          );
 
-        dynamic receiveDerivation;
-        for (int j = 0;
-            j < receiveDerivations[sd.derivePathType]!.length &&
-                receiveDerivation == null;
-            j++) {
-          if (receiveDerivations[sd.derivePathType]!["$j"]["address"] ==
-              sd.utxo.address!) {
-            receiveDerivation = receiveDerivations[sd.derivePathType]!["$j"];
-          }
+          wif = node.toWIF();
+          pubKey = Format.uint8listToString(node.publicKey);
         }
-
-        if (receiveDerivation != null) {
-          pubKey = receiveDerivation["publicKey"] as String;
-          wif = receiveDerivation["wif"] as String;
-        } else {
-          // fetch change derivations if null
-          changeDerivations[sd.derivePathType] ??= Map<String, dynamic>.from(
+        if (wif == null || pubKey == null) {
+          // fetch receiving derivations if null
+          receiveDerivations[sd.derivePathType] ??= Map<String, dynamic>.from(
             jsonDecode((await _secureStore.read(
-                  key: "${walletId}_changeDerivations",
+                  key: "${walletId}_receiveDerivations",
                 )) ??
                 "{}") as Map,
           );
 
-          dynamic changeDerivation;
+          dynamic receiveDerivation;
           for (int j = 0;
-              j < changeDerivations[sd.derivePathType]!.length &&
-                  changeDerivation == null;
+              j < receiveDerivations[sd.derivePathType]!.length &&
+                  receiveDerivation == null;
               j++) {
-            if (changeDerivations[sd.derivePathType]!["$j"]["address"] ==
+            if (receiveDerivations[sd.derivePathType]!["$j"]["address"] ==
                 sd.utxo.address!) {
-              changeDerivation = changeDerivations[sd.derivePathType]!["$j"];
+              receiveDerivation = receiveDerivations[sd.derivePathType]!["$j"];
             }
           }
 
-          if (changeDerivation != null) {
-            pubKey = changeDerivation["publicKey"] as String;
-            wif = changeDerivation["wif"] as String;
-          }
-        }
-
-        if (wif == null || pubKey == null) {
-          final address = await db.getAddress(walletId, sd.utxo.address!);
-          if (address?.derivationPath != null) {
-            final node = await Bip32Utils.getBip32Node(
-              (await mnemonicString)!,
-              (await mnemonicPassphrase)!,
-              _network,
-              address!.derivationPath!.value,
+          if (receiveDerivation != null) {
+            pubKey = receiveDerivation["publicKey"] as String;
+            wif = receiveDerivation["wif"] as String;
+          } else {
+            // fetch change derivations if null
+            changeDerivations[sd.derivePathType] ??= Map<String, dynamic>.from(
+              jsonDecode((await _secureStore.read(
+                    key: "${walletId}_changeDerivations",
+                  )) ??
+                  "{}") as Map,
             );
 
-            wif = node.toWIF();
-            pubKey = Format.uint8listToString(node.publicKey);
+            dynamic changeDerivation;
+            for (int j = 0;
+                j < changeDerivations[sd.derivePathType]!.length &&
+                    changeDerivation == null;
+                j++) {
+              if (changeDerivations[sd.derivePathType]!["$j"]["address"] ==
+                  sd.utxo.address!) {
+                changeDerivation = changeDerivations[sd.derivePathType]!["$j"];
+              }
+            }
+
+            if (changeDerivation != null) {
+              pubKey = changeDerivation["publicKey"] as String;
+              wif = changeDerivation["wif"] as String;
+            }
           }
         }
 
@@ -1793,6 +1762,8 @@ class FiroWallet extends CoinServiceAPI
           sd.redeemScript = redeemScript;
           sd.output = data.output;
           sd.keyPair = keyPair;
+        } else {
+          throw Exception("key or wif not found for ${sd.utxo}");
         }
       }
 
@@ -2210,6 +2181,7 @@ class FiroWallet extends CoinServiceAPI
   }
 
   bool refreshMutex = false;
+
   @override
   bool get isRefreshing => refreshMutex;
 
@@ -2236,28 +2208,6 @@ class FiroWallet extends CoinServiceAPI
 
       GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
 
-      final receiveDerivationsString =
-          await _secureStore.read(key: "${walletId}_receiveDerivations");
-      if (receiveDerivationsString == null ||
-          receiveDerivationsString == "{}") {
-        GlobalEventBus.instance
-            .fire(RefreshPercentChangedEvent(0.05, walletId));
-        final mnemonic = await mnemonicString;
-        final mnemonicPassphrase =
-            await _secureStore.read(key: '${_walletId}_mnemonicPassphrase');
-        if (mnemonicPassphrase == null) {
-          Logging.instance.log(
-              "Exception in _generateAddressForChain: mnemonic passphrase null, possible migration issue; if using internal builds, delete wallet and restore from seed, if using a release build, please file bug report",
-              level: LogLevel.Error);
-        }
-
-        await fillAddresses(
-          mnemonic!,
-          mnemonicPassphrase!,
-          numberOfThreads: Platform.numberOfProcessors - isolates.length - 1,
-        );
-      }
-
       await checkReceivingAddressForTransactions();
       GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId));
 
@@ -2404,12 +2354,6 @@ class FiroWallet extends CoinServiceAPI
           element.values.any((elementCoin) => elementCoin.value == 0));
     }
     final jindexes = firoGetJIndex();
-    final transactions = await _txnData;
-    final lelantusTransactionsd = await db
-        .getTransactions(walletId)
-        .filter()
-        .isLelantusEqualTo(true)
-        .findAll();
 
     List<LelantusCoin> coins = [];
 
@@ -2423,42 +2367,26 @@ class FiroWallet extends CoinServiceAPI
 
     for (int i = 0; i < lelantusCoinsList.length; i++) {
       // Logging.instance.log("lelantusCoinsList[$i]: ${lelantusCoinsList[i]}");
+      final txid = lelantusCoinsList[i].txId;
       final txn = await cachedElectrumXClient.getTransaction(
-        txHash: lelantusCoinsList[i].txId,
+        txHash: txid,
         verbose: true,
         coin: coin,
       );
       final confirmations = txn["confirmations"];
       bool isUnconfirmed = confirmations is int && confirmations < 1;
+
+      final tx = await db.getTransaction(walletId, txid);
+
       if (!jindexes!.contains(lelantusCoinsList[i].index) &&
-          transactions
-              .where((e) => e.txid == lelantusCoinsList[i].txId)
-              .isEmpty &&
-          !(lelantusTransactionsd
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .isNotEmpty &&
-              lelantusTransactionsd
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .first
-                  .isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS))) {
+          tx != null &&
+          tx.isLelantus == true &&
+          !(tx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS))) {
         isUnconfirmed = true;
       }
 
-      // TODO: optimize the following
-      if ((transactions
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .isNotEmpty &&
-              !transactions
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .first
-                  .isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) ||
-          (lelantusTransactionsd
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .isNotEmpty &&
-              !lelantusTransactionsd
-                  .where((e) => e.txid == lelantusCoinsList[i].txId)
-                  .first
-                  .isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS))) {
+      if (tx != null &&
+          !tx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) {
         continue;
       }
       if (!lelantusCoinsList[i].isUsed &&
@@ -2482,61 +2410,54 @@ class FiroWallet extends CoinServiceAPI
         lelantusCoins.removeWhere((element) =>
             element.values.any((elementCoin) => elementCoin.value == 0));
       }
-      final data = await _txnData;
-      final lData = await db
-          .getTransactions(walletId)
-          .filter()
-          .isLelantusEqualTo(true)
-          .findAll();
+
       final currentChainHeight = await chainHeight;
       final jindexes = firoGetJIndex();
       int intLelantusBalance = 0;
       int unconfirmedLelantusBalance = 0;
 
-      for (var element in lelantusCoins) {
-        element.forEach((key, value) {
-          isar_models.Transaction? tx;
-          try {
-            tx == data.firstWhere((e) => e.txid == value.txId);
-          } catch (_) {
-            tx = null;
-          }
+      for (final element in lelantusCoins) {
+        element.forEach((key, lelantusCoin) {
+          isar_models.Transaction? txn = db.isar.transactions
+              .where()
+              .txidWalletIdEqualTo(
+                lelantusCoin.txId,
+                walletId,
+              )
+              .findFirstSync();
 
-          isar_models.Transaction? ltx;
-          try {
-            ltx = lData.firstWhere((e) => e.txid == value.txId);
-          } catch (_) {
-            ltx = null;
-          }
-
-          // Logging.instance.log("$value $tx $ltx");
-          if (!jindexes!.contains(value.index) && tx == null) {
-            if (!value.isUsed &&
-                ltx != null &&
-                ltx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) {
-              // mint tx, add value to balance
-              intLelantusBalance += value.value;
-            } /* else {
+          if (txn == null) {
+            // TODO: ??????????????????????????????????????
+          } else {
+            bool isLelantus = txn.isLelantus == true;
+            if (!jindexes!.contains(lelantusCoin.index) && isLelantus) {
+              if (!lelantusCoin.isUsed &&
+                  txn.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) {
+                // mint tx, add value to balance
+                intLelantusBalance += lelantusCoin.value;
+              } /* else {
             // This coin is not confirmed and may be replaced
             }*/
-          } else if (jindexes.contains(value.index) &&
-              tx == null &&
-              !value.isUsed &&
-              ltx != null &&
-              !ltx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) {
-            unconfirmedLelantusBalance += value.value;
-          } else if (jindexes.contains(value.index) && !value.isUsed) {
-            intLelantusBalance += value.value;
-          } else if (!value.isUsed &&
-              (tx == null
-                  ? true
-                  : tx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS) !=
-                      false)) {
-            intLelantusBalance += value.value;
-          } else if (tx != null &&
-              tx.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS) ==
-                  false) {
-            unconfirmedLelantusBalance += value.value;
+            } else if (jindexes.contains(lelantusCoin.index) &&
+                isLelantus &&
+                !lelantusCoin.isUsed &&
+                !txn.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS)) {
+              unconfirmedLelantusBalance += lelantusCoin.value;
+            } else if (jindexes.contains(lelantusCoin.index) &&
+                !lelantusCoin.isUsed) {
+              intLelantusBalance += lelantusCoin.value;
+            } else if (!lelantusCoin.isUsed &&
+                (txn.isLelantus == true
+                    ? true
+                    : txn.isConfirmed(
+                            currentChainHeight, MINIMUM_CONFIRMATIONS) !=
+                        false)) {
+              intLelantusBalance += lelantusCoin.value;
+            } else if (!isLelantus &&
+                txn.isConfirmed(currentChainHeight, MINIMUM_CONFIRMATIONS) ==
+                    false) {
+              unconfirmedLelantusBalance += lelantusCoin.value;
+            }
           }
         });
       }
@@ -2721,12 +2642,13 @@ class FiroWallet extends CoinServiceAPI
 
   /// Builds and signs a transaction
   Future<Map<String, dynamic>> buildMintTransaction(
-      List<isar_models.UTXO> utxosToUse,
-      int satoshisPerRecipient,
-      List<Map<String, dynamic>> mintsMap) async {
+    List<isar_models.UTXO> utxosToUse,
+    int satoshisPerRecipient,
+    List<Map<String, dynamic>> mintsMap,
+  ) async {
     //todo: check if print needed
     // debugPrint(utxosToUse.toString());
-    List<String> addressesToDerive = [];
+    List<String> addressStringsToGet = [];
 
     // Populating the addresses to derive
     for (var i = 0; i < utxosToUse.length; i++) {
@@ -2745,64 +2667,95 @@ class FiroWallet extends CoinServiceAPI
         final address =
             vouts[outputIndex]["scriptPubKey"]["addresses"][0] as String?;
         if (address != null) {
-          addressesToDerive.add(address);
+          addressStringsToGet.add(address);
         }
       }
     }
 
-    List<ECPair> elipticCurvePairArray = [];
+    final List<isar_models.Address> addresses = [];
+    for (final addressString in addressStringsToGet) {
+      final address = await db.getAddress(walletId, addressString);
+      if (address == null) {
+        Logging.instance.log(
+          "Failed to fetch the corresponding address object for $addressString",
+          level: LogLevel.Fatal,
+        );
+      } else {
+        addresses.add(address);
+      }
+    }
+
+    List<ECPair> ellipticCurvePairArray = [];
     List<Uint8List> outputDataArray = [];
 
-    final receiveDerivationsString =
-        await _secureStore.read(key: "${walletId}_receiveDerivations");
-    final changeDerivationsString =
-        await _secureStore.read(key: "${walletId}_changeDerivations");
+    Map<String, dynamic>? receiveDerivations;
+    Map<String, dynamic>? changeDerivations;
 
-    final receiveDerivations = Map<String, dynamic>.from(
-        jsonDecode(receiveDerivationsString ?? "{}") as Map);
-    final changeDerivations = Map<String, dynamic>.from(
-        jsonDecode(changeDerivationsString ?? "{}") as Map);
+    for (final addressString in addressStringsToGet) {
+      String? pubKey;
+      String? wif;
 
-    for (var i = 0; i < addressesToDerive.length; i++) {
-      final addressToCheckFor = addressesToDerive[i];
+      final address = await db.getAddress(walletId, addressString);
 
-      for (var i = 0; i < receiveDerivations.length; i++) {
-        final receive = receiveDerivations["$i"];
-        final change = changeDerivations["$i"];
+      if (address?.derivationPath != null) {
+        final node = await Bip32Utils.getBip32Node(
+          (await mnemonicString)!,
+          (await mnemonicPassphrase)!,
+          _network,
+          address!.derivationPath!.value,
+        );
+        wif = node.toWIF();
+        pubKey = Format.uint8listToString(node.publicKey);
+      }
 
-        if (receive['address'] == addressToCheckFor) {
-          Logging.instance
-              .log('Receiving found on loop $i', level: LogLevel.Info);
-          // Logging.instance.log(
-          //     'decoded receive[\'wif\'] version: ${wif.decode(receive['wif'] as String)}, _network: $_network');
-          elipticCurvePairArray
-              .add(ECPair.fromWIF(receive['wif'] as String, network: _network));
-          outputDataArray.add(P2PKH(
-                  network: _network,
-                  data: PaymentData(
-                      pubkey: Format.stringToUint8List(
-                          receive['publicKey'] as String)))
-              .data
-              .output!);
-          break;
+      if (wif == null || pubKey == null) {
+        receiveDerivations ??= Map<String, dynamic>.from(
+          jsonDecode((await _secureStore.read(
+                  key: "${walletId}_receiveDerivations")) ??
+              "{}") as Map,
+        );
+        for (var i = 0; i < receiveDerivations.length; i++) {
+          final receive = receiveDerivations["$i"];
+          if (receive['address'] == addressString) {
+            wif = receive['wif'] as String;
+            pubKey = receive['publicKey'] as String;
+            break;
+          }
         }
-        if (change['address'] == addressToCheckFor) {
-          Logging.instance.log('Change found on loop $i', level: LogLevel.Info);
-          // Logging.instance.log(
-          //     'decoded change[\'wif\'] version: ${wif.decode(change['wif'] as String)}, _network: $_network');
-          elipticCurvePairArray
-              .add(ECPair.fromWIF(change['wif'] as String, network: _network));
 
-          outputDataArray.add(P2PKH(
-                  network: _network,
-                  data: PaymentData(
-                      pubkey: Format.stringToUint8List(
-                          change['publicKey'] as String)))
-              .data
-              .output!);
-          break;
+        if (wif == null || pubKey == null) {
+          changeDerivations ??= Map<String, dynamic>.from(
+            jsonDecode((await _secureStore.read(
+                    key: "${walletId}_changeDerivations")) ??
+                "{}") as Map,
+          );
+
+          for (var i = 0; i < changeDerivations.length; i++) {
+            final change = changeDerivations["$i"];
+            if (change['address'] == addressString) {
+              wif = change['wif'] as String;
+              pubKey = change['publicKey'] as String;
+
+              break;
+            }
+          }
         }
       }
+
+      ellipticCurvePairArray.add(
+        ECPair.fromWIF(
+          wif!,
+          network: _network,
+        ),
+      );
+      outputDataArray.add(P2PKH(
+        network: _network,
+        data: PaymentData(
+          pubkey: Format.stringToUint8List(
+            pubKey!,
+          ),
+        ),
+      ).data.output!);
     }
 
     final txb = TransactionBuilder(network: _network);
@@ -2831,7 +2784,7 @@ class FiroWallet extends CoinServiceAPI
     for (var i = 0; i < utxosToUse.length; i++) {
       txb.sign(
         vin: i,
-        keyPair: elipticCurvePairArray[i],
+        keyPair: ellipticCurvePairArray[i],
         witnessValue: utxosToUse[i].value,
       );
     }
@@ -3859,72 +3812,6 @@ class FiroWallet extends CoinServiceAPI
     return address!.value;
   }
 
-  Future<void> fillAddresses(
-    String suppliedMnemonic,
-    String mnemonicPassphrase, {
-    int perBatch = 50,
-    int numberOfThreads = 4,
-  }) async {
-    if (numberOfThreads <= 0) {
-      numberOfThreads = 1;
-    }
-    if (Platform.environment["FLUTTER_TEST"] == "true" || integrationTestFlag) {
-      perBatch = 10;
-      numberOfThreads = 4;
-    }
-
-    final receiveDerivationsString =
-        await _secureStore.read(key: "${walletId}_receiveDerivations");
-    final changeDerivationsString =
-        await _secureStore.read(key: "${walletId}_changeDerivations");
-
-    var receiveDerivations = Map<String, dynamic>.from(
-        jsonDecode(receiveDerivationsString ?? "{}") as Map);
-    var changeDerivations = Map<String, dynamic>.from(
-        jsonDecode(changeDerivationsString ?? "{}") as Map);
-
-    final int start = receiveDerivations.length;
-
-    List<ReceivePort> ports = List.empty(growable: true);
-    for (int i = 0; i < numberOfThreads; i++) {
-      ReceivePort receivePort = await getIsolate({
-        "function": "isolateDerive",
-        "mnemonic": suppliedMnemonic,
-        "mnemonicPassphrase": mnemonicPassphrase,
-        "from": start + i * perBatch,
-        "to": start + (i + 1) * perBatch,
-        "network": _network,
-      });
-      ports.add(receivePort);
-    }
-    for (int i = 0; i < numberOfThreads; i++) {
-      ReceivePort receivePort = ports.elementAt(i);
-      var message = await receivePort.first;
-      if (message is String) {
-        Logging.instance.log("this is a string", level: LogLevel.Error);
-        stop(receivePort);
-        throw Exception("isolateDerive isolate failed");
-      }
-      stop(receivePort);
-      Logging.instance.log('Closing isolateDerive!', level: LogLevel.Info);
-      receiveDerivations.addAll(message['receive'] as Map<String, dynamic>);
-      changeDerivations.addAll(message['change'] as Map<String, dynamic>);
-    }
-    Logging.instance.log("isolate derives", level: LogLevel.Info);
-    // Logging.instance.log(receiveDerivations);
-    // Logging.instance.log(changeDerivations);
-
-    final newReceiveDerivationsString = jsonEncode(receiveDerivations);
-    final newChangeDerivationsString = jsonEncode(changeDerivations);
-
-    await _secureStore.write(
-        key: "${walletId}_receiveDerivations",
-        value: newReceiveDerivationsString);
-    await _secureStore.write(
-        key: "${walletId}_changeDerivations",
-        value: newChangeDerivationsString);
-  }
-
   /// Generates a new internal or external chain address for the wallet using a BIP84 derivation path.
   /// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
   /// [index] - This can be any integer >= 0
@@ -3934,75 +3821,44 @@ class FiroWallet extends CoinServiceAPI
     final _mnemonicPassphrase = await mnemonicPassphrase;
     if (_mnemonicPassphrase == null) {
       Logging.instance.log(
-          "Exception in _generateAddressForChain: mnemonic passphrase null, possible migration issue; if using internal builds, delete wallet and restore from seed, if using a release build, please file bug report",
+          "Exception in _generateAddressForChain: mnemonic passphrase null,"
+          " possible migration issue; if using internal builds, delete "
+          "wallet and restore from seed, if using a release build, "
+          "please file bug report",
           level: LogLevel.Error);
     }
 
-    Map<String, dynamic>? derivations;
-    if (chain == 0) {
-      final receiveDerivationsString =
-          await _secureStore.read(key: "${walletId}_receiveDerivations");
-      derivations = Map<String, dynamic>.from(
-          jsonDecode(receiveDerivationsString ?? "{}") as Map);
-    } else if (chain == 1) {
-      final changeDerivationsString =
-          await _secureStore.read(key: "${walletId}_changeDerivations");
-      derivations = Map<String, dynamic>.from(
-          jsonDecode(changeDerivationsString ?? "{}") as Map);
-    }
     final derivePath = constructDerivePath(
       networkWIF: _network.wif,
       chain: chain,
       index: index,
     );
-    if (derivations!.isNotEmpty) {
-      if (derivations["$index"] == null) {
-        await fillAddresses(
-          _mnemonic!,
-          _mnemonicPassphrase!,
-          numberOfThreads: Platform.numberOfProcessors - isolates.length - 1,
-        );
-        Logging.instance.log("calling _generateAddressForChain recursively",
-            level: LogLevel.Info);
-        return _generateAddressForChain(chain, index);
-      }
-      return isar_models.Address(
-        walletId: walletId,
-        value: derivations["$index"]['address'] as String,
-        publicKey: Format.stringToUint8List(
-            derivations["$index"]['publicKey'] as String),
-        type: isar_models.AddressType.p2pkh,
-        derivationIndex: index,
-        derivationPath: isar_models.DerivationPath()..value = derivePath,
-        subType: chain == 0
-            ? isar_models.AddressSubType.receiving
-            : isar_models.AddressSubType.change,
-      );
-    } else {
-      final node = await Bip32Utils.getBip32Node(
-        _mnemonic!,
-        _mnemonicPassphrase!,
-        _network,
-        derivePath,
-      );
 
-      final address =
-          P2PKH(network: _network, data: PaymentData(pubkey: node.publicKey))
-              .data
-              .address!;
+    final node = await Bip32Utils.getBip32Node(
+      _mnemonic!,
+      _mnemonicPassphrase!,
+      _network,
+      derivePath,
+    );
 
-      return isar_models.Address(
-        walletId: walletId,
-        value: address,
-        publicKey: node.publicKey,
-        type: isar_models.AddressType.p2pkh,
-        derivationIndex: index,
-        derivationPath: isar_models.DerivationPath()..value = derivePath,
-        subType: chain == 0
-            ? isar_models.AddressSubType.receiving
-            : isar_models.AddressSubType.change,
-      );
-    }
+    final address = P2PKH(
+      network: _network,
+      data: PaymentData(
+        pubkey: node.publicKey,
+      ),
+    ).data.address!;
+
+    return isar_models.Address(
+      walletId: walletId,
+      value: address,
+      publicKey: node.publicKey,
+      type: isar_models.AddressType.p2pkh,
+      derivationIndex: index,
+      derivationPath: isar_models.DerivationPath()..value = derivePath,
+      subType: chain == 0
+          ? isar_models.AddressSubType.receiving
+          : isar_models.AddressSubType.change,
+    );
   }
 
   // /// Takes in a list of isar_models.UTXOs and adds a name (dependent on object index within list)
@@ -4087,6 +3943,8 @@ class FiroWallet extends CoinServiceAPI
         _mnemonic!,
         _mnemonicPassphrase!,
         maxUnusedAddressGap,
+        maxNumberOfIndexesToCheck,
+        true,
       );
 
       longMutex = false;
@@ -4124,151 +3982,6 @@ class FiroWallet extends CoinServiceAPI
     await _secureStore.delete(key: "${walletId}_changeDerivations");
   }
 
-  // Future<void> _rescanBackup() async {
-  //   Logging.instance.log("starting rescan backup", level: LogLevel.Info);
-  //
-  //   // backup current and clear data
-  //   final tempReceivingAddresses =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'receivingAddresses');
-  //   await DB.instance.delete<dynamic>(
-  //     key: 'receivingAddresses',
-  //     boxName: walletId,
-  //   );
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'receivingAddresses_BACKUP',
-  //       value: tempReceivingAddresses);
-  //
-  //   final tempChangeAddresses =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddresses');
-  //   await DB.instance.delete<dynamic>(
-  //     key: 'changeAddresses',
-  //     boxName: walletId,
-  //   );
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'changeAddresses_BACKUP',
-  //       value: tempChangeAddresses);
-  //
-  //   final tempReceivingIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'receivingIndex');
-  //   await DB.instance.delete<dynamic>(
-  //     key: 'receivingIndex',
-  //     boxName: walletId,
-  //   );
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'receivingIndex_BACKUP',
-  //       value: tempReceivingIndex);
-  //
-  //   final tempChangeIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'changeIndex');
-  //   await DB.instance.delete<dynamic>(
-  //     key: 'changeIndex',
-  //     boxName: walletId,
-  //   );
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'changeIndex_BACKUP', value: tempChangeIndex);
-  //
-  //   final receiveDerivationsString =
-  //       await _secureStore.read(key: "${walletId}_receiveDerivations");
-  //   final changeDerivationsString =
-  //       await _secureStore.read(key: "${walletId}_changeDerivations");
-  //
-  //   await _secureStore.write(
-  //       key: "${walletId}_receiveDerivations_BACKUP",
-  //       value: receiveDerivationsString);
-  //   await _secureStore.write(
-  //       key: "${walletId}_changeDerivations_BACKUP",
-  //       value: changeDerivationsString);
-  //
-  //   await _secureStore.write(
-  //       key: "${walletId}_receiveDerivations", value: null);
-  //   await _secureStore.write(key: "${walletId}_changeDerivations", value: null);
-  //
-  //   // back up but no need to delete
-  //   final tempMintIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'mintIndex');
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'mintIndex_BACKUP', value: tempMintIndex);
-  //
-  //   final tempLelantusCoins =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: '_lelantus_coins');
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: '_lelantus_coins_BACKUP',
-  //       value: tempLelantusCoins);
-  //
-  //   final tempJIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'jindex');
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'jindex_BACKUP', value: tempJIndex);
-  //
-  //   final tempLelantusTxModel = DB.instance
-  //       .get<dynamic>(boxName: walletId, key: 'latest_lelantus_tx_model');
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'latest_lelantus_tx_model_BACKUP',
-  //       value: tempLelantusTxModel);
-  //
-  //   Logging.instance.log("rescan backup complete", level: LogLevel.Info);
-  // }
-  //
-  // Future<void> _rescanRestore() async {
-  //   Logging.instance.log("starting rescan restore", level: LogLevel.Info);
-  //
-  //   // restore from backup
-  //   final tempReceivingAddresses = DB.instance
-  //       .get<dynamic>(boxName: walletId, key: 'receivingAddresses_BACKUP');
-  //   final tempChangeAddresses = DB.instance
-  //       .get<dynamic>(boxName: walletId, key: 'changeAddresses_BACKUP');
-  //   final tempReceivingIndex = DB.instance
-  //       .get<dynamic>(boxName: walletId, key: 'receivingIndex_BACKUP');
-  //   final tempChangeIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'changeIndex_BACKUP');
-  //   final tempMintIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'mintIndex_BACKUP');
-  //   final tempLelantusCoins = DB.instance
-  //       .get<dynamic>(boxName: walletId, key: '_lelantus_coins_BACKUP');
-  //   final tempJIndex =
-  //       DB.instance.get<dynamic>(boxName: walletId, key: 'jindex_BACKUP');
-  //   final tempLelantusTxModel = DB.instance.get<dynamic>(
-  //       boxName: walletId, key: 'latest_lelantus_tx_model_BACKUP');
-  //
-  //   final receiveDerivationsString =
-  //       await _secureStore.read(key: "${walletId}_receiveDerivations_BACKUP");
-  //   final changeDerivationsString =
-  //       await _secureStore.read(key: "${walletId}_changeDerivations_BACKUP");
-  //
-  //   await _secureStore.write(
-  //       key: "${walletId}_receiveDerivations", value: receiveDerivationsString);
-  //   await _secureStore.write(
-  //       key: "${walletId}_changeDerivations", value: changeDerivationsString);
-  //
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'receivingAddresses',
-  //       value: tempReceivingAddresses);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'changeAddresses', value: tempChangeAddresses);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'receivingIndex', value: tempReceivingIndex);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'changeIndex', value: tempChangeIndex);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: 'mintIndex', value: tempMintIndex);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId, key: '_lelantus_coins', value: tempLelantusCoins);
-  //   await DB.instance
-  //       .put<dynamic>(boxName: walletId, key: 'jindex', value: tempJIndex);
-  //   await DB.instance.put<dynamic>(
-  //       boxName: walletId,
-  //       key: 'latest_lelantus_tx_model',
-  //       value: tempLelantusTxModel);
-  //
-  //   Logging.instance.log("rescan restore  complete", level: LogLevel.Info);
-  // }
-
   /// wrapper for _recoverWalletFromBIP32SeedPhrase()
   @override
   Future<void> recoverFromMnemonic({
@@ -4329,6 +4042,8 @@ class FiroWallet extends CoinServiceAPI
         mnemonic.trim(),
         mnemonicPassphrase ?? "",
         maxUnusedAddressGap,
+        maxNumberOfIndexesToCheck,
+        false,
       );
 
       await compute(
@@ -4363,142 +4078,270 @@ class FiroWallet extends CoinServiceAPI
     return setDataMap;
   }
 
-  Future<void> _makeDerivations(
+  Future<Map<String, int>> _getBatchTxCount({
+    required Map<String, String> addresses,
+  }) async {
+    try {
+      final Map<String, List<dynamic>> args = {};
+      for (final entry in addresses.entries) {
+        args[entry.key] = [
+          AddressUtils.convertToScriptHash(entry.value, _network)
+        ];
+      }
+      final response = await electrumXClient.getBatchHistory(args: args);
+
+      final Map<String, int> result = {};
+      for (final entry in response.entries) {
+        result[entry.key] = entry.value.length;
+      }
+      return result;
+    } catch (e, s) {
+      Logging.instance.log(
+          "Exception rethrown in _getBatchTxCount(address: $addresses: $e\n$s",
+          level: LogLevel.Error);
+      rethrow;
+    }
+  }
+
+  Future<Tuple2<List<isar_models.Address>, int>> _checkGaps(
+    int maxNumberOfIndexesToCheck,
+    int maxUnusedAddressGap,
+    int txCountBatchSize,
+    bip32.BIP32 root,
+    int chain,
+  ) async {
+    List<isar_models.Address> addressArray = [];
+    int gapCounter = 0;
+    int highestIndexWithHistory = 0;
+
+    for (int index = 0;
+        index < maxNumberOfIndexesToCheck && gapCounter < maxUnusedAddressGap;
+        index += txCountBatchSize) {
+      List<String> iterationsAddressArray = [];
+      Logging.instance.log(
+        "index: $index, \t GapCounter $chain: $gapCounter",
+        level: LogLevel.Info,
+      );
+
+      final _id = "k_$index";
+      Map<String, String> txCountCallArgs = {};
+
+      for (int j = 0; j < txCountBatchSize; j++) {
+        final derivePath = constructDerivePath(
+          networkWIF: root.network.wif,
+          chain: chain,
+          index: index + j,
+        );
+        final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
+
+        final data = PaymentData(pubkey: node.publicKey);
+        final String addressString = P2PKH(
+          data: data,
+          network: _network,
+        ).data.address!;
+        const isar_models.AddressType addrType = isar_models.AddressType.p2pkh;
+
+        final address = isar_models.Address(
+          walletId: walletId,
+          value: addressString,
+          publicKey: node.publicKey,
+          type: addrType,
+          derivationIndex: index + j,
+          derivationPath: isar_models.DerivationPath()..value = derivePath,
+          subType: chain == 0
+              ? isar_models.AddressSubType.receiving
+              : isar_models.AddressSubType.change,
+        );
+
+        addressArray.add(address);
+
+        txCountCallArgs.addAll({
+          "${_id}_$j": addressString,
+        });
+      }
+
+      // get address tx counts
+      final counts = await _getBatchTxCount(addresses: txCountCallArgs);
+
+      // check and add appropriate addresses
+      for (int k = 0; k < txCountBatchSize; k++) {
+        int count = counts["${_id}_$k"]!;
+        if (count > 0) {
+          iterationsAddressArray.add(txCountCallArgs["${_id}_$k"]!);
+
+          // update highest
+          highestIndexWithHistory = index + k;
+
+          // reset counter
+          gapCounter = 0;
+        }
+
+        // increase counter when no tx history found
+        if (count == 0) {
+          gapCounter++;
+        }
+      }
+      // cache all the transactions while waiting for the current function to finish.
+      unawaited(getTransactionCacheEarly(iterationsAddressArray));
+    }
+    return Tuple2(addressArray, highestIndexWithHistory);
+  }
+
+  Future<void> getTransactionCacheEarly(List<String> allAddresses) async {
+    try {
+      final List<Map<String, dynamic>> allTxHashes =
+          await _fetchHistory(allAddresses);
+      for (final txHash in allTxHashes) {
+        try {
+          unawaited(cachedElectrumXClient.getTransaction(
+            txHash: txHash["tx_hash"] as String,
+            verbose: true,
+            coin: coin,
+          ));
+        } catch (e) {
+          continue;
+        }
+      }
+    } catch (e) {
+      //
+    }
+  }
+
+  Future<void> _recoverHistory(
     String suppliedMnemonic,
     String mnemonicPassphrase,
     int maxUnusedAddressGap,
+    int maxNumberOfIndexesToCheck,
+    bool isRescan,
   ) async {
-    List<isar_models.Address> receivingAddressArray = [];
-    List<isar_models.Address> changeAddressArray = [];
+    final root = await Bip32Utils.getBip32Root(
+      suppliedMnemonic,
+      mnemonicPassphrase,
+      _network,
+    );
 
-    int receivingIndex = -1;
-    int changeIndex = -1;
+    final List<Future<Tuple2<List<isar_models.Address>, int>>> receiveFutures =
+        [];
+    final List<Future<Tuple2<List<isar_models.Address>, int>>> changeFutures =
+        [];
 
-    // The gap limit will be capped at 20
-    int receivingGapCounter = 0;
-    int changeGapCounter = 0;
+    const receiveChain = 0;
+    const changeChain = 1;
+    const indexZero = 0;
 
-    await fillAddresses(suppliedMnemonic, mnemonicPassphrase,
-        numberOfThreads: Platform.numberOfProcessors - isolates.length - 1);
+    // actual size is 36 due to p2pkh, p2sh, and p2wpkh so 12x3
+    const txCountBatchSize = 12;
 
-    final receiveDerivationsString =
-        await _secureStore.read(key: "${walletId}_receiveDerivations");
-    final changeDerivationsString =
-        await _secureStore.read(key: "${walletId}_changeDerivations");
+    try {
+      // receiving addresses
+      Logging.instance.log(
+        "checking receiving addresses...",
+        level: LogLevel.Info,
+      );
 
-    final receiveDerivations = Map<String, dynamic>.from(
-        jsonDecode(receiveDerivationsString ?? "{}") as Map);
-    final changeDerivations = Map<String, dynamic>.from(
-        jsonDecode(changeDerivationsString ?? "{}") as Map);
+      receiveFutures.add(
+        _checkGaps(
+          maxNumberOfIndexesToCheck,
+          maxUnusedAddressGap,
+          txCountBatchSize,
+          root,
+          receiveChain,
+        ),
+      );
 
-    // log("rcv: $receiveDerivations");
-    // log("chg: $changeDerivations");
+      // change addresses
+      Logging.instance.log(
+        "checking change addresses...",
+        level: LogLevel.Info,
+      );
+      changeFutures.add(
+        _checkGaps(
+          maxNumberOfIndexesToCheck,
+          maxUnusedAddressGap,
+          txCountBatchSize,
+          root,
+          changeChain,
+        ),
+      );
 
-    // Deriving and checking for receiving addresses
-    for (var i = 0; i < receiveDerivations.length; i++) {
-      // Break out of loop when receivingGapCounter hits maxUnusedAddressGap
-      // Same gap limit for change as for receiving, breaks when it hits maxUnusedAddressGap
-      if (receivingGapCounter >= maxUnusedAddressGap &&
-          changeGapCounter >= maxUnusedAddressGap) {
-        break;
-      }
+      // io limitations may require running these linearly instead
+      final futuresResult = await Future.wait([
+        Future.wait(receiveFutures),
+        Future.wait(changeFutures),
+      ]);
 
-      final receiveDerivation = receiveDerivations["$i"];
-      final address = receiveDerivation['address'] as String;
+      final receiveResults = futuresResult[0];
+      final changeResults = futuresResult[1];
 
-      final changeDerivation = changeDerivations["$i"];
-      final _address = changeDerivation['address'] as String;
-      Future<int>? futureNumTxs;
-      Future<int>? _futureNumTxs;
-      if (receivingGapCounter < maxUnusedAddressGap) {
-        futureNumTxs = _getReceivedTxCount(address: address);
-      }
-      if (changeGapCounter < maxUnusedAddressGap) {
-        _futureNumTxs = _getReceivedTxCount(address: _address);
-      }
-      try {
-        if (futureNumTxs != null) {
-          int numTxs = await futureNumTxs;
-          if (numTxs >= 1) {
-            receivingIndex = i;
-            final derivePath = constructDerivePath(
-              networkWIF: _network.wif,
-              chain: 0,
-              index: receivingIndex,
-            );
-            final addr = isar_models.Address(
-              walletId: walletId,
-              value: address,
-              publicKey: Format.stringToUint8List(
-                  receiveDerivation['publicKey'] as String),
-              type: isar_models.AddressType.p2pkh,
-              derivationIndex: i,
-              derivationPath: isar_models.DerivationPath()..value = derivePath,
-              subType: isar_models.AddressSubType.receiving,
-            );
-            receivingAddressArray.add(addr);
-          } else if (numTxs == 0) {
-            receivingGapCounter += 1;
-          }
+      final List<isar_models.Address> addressesToStore = [];
+
+      int highestReceivingIndexWithHistory = 0;
+      // If restoring a wallet that never received any funds, then set receivingArray manually
+      // If we didn't do this, it'd store an empty array
+      for (final tuple in receiveResults) {
+        if (tuple.item1.isEmpty) {
+          final address = await _generateAddressForChain(
+            receiveChain,
+            indexZero,
+          );
+          addressesToStore.add(address);
+        } else {
+          highestReceivingIndexWithHistory =
+              max(tuple.item2, highestReceivingIndexWithHistory);
+          addressesToStore.addAll(tuple.item1);
         }
-      } catch (e, s) {
-        Logging.instance.log(
-            "Exception rethrown from recoverWalletFromBIP32SeedPhrase(): $e\n$s",
-            level: LogLevel.Error);
-        rethrow;
       }
 
-      try {
-        if (_futureNumTxs != null) {
-          int numTxs = await _futureNumTxs;
-          if (numTxs >= 1) {
-            changeIndex = i;
-            final derivePath = constructDerivePath(
-              networkWIF: _network.wif,
-              chain: 1,
-              index: changeIndex,
-            );
-            final addr = isar_models.Address(
-              walletId: walletId,
-              value: _address,
-              publicKey: Format.stringToUint8List(
-                  changeDerivation['publicKey'] as String),
-              type: isar_models.AddressType.p2pkh,
-              derivationIndex: i,
-              derivationPath: isar_models.DerivationPath()..value = derivePath,
-              subType: isar_models.AddressSubType.change,
-            );
-            changeAddressArray.add(addr);
-          } else if (numTxs == 0) {
-            changeGapCounter += 1;
-          }
+      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.item1.isEmpty) {
+          final address = await _generateAddressForChain(
+            changeChain,
+            indexZero,
+          );
+          addressesToStore.add(address);
+        } else {
+          highestChangeIndexWithHistory =
+              max(tuple.item2, highestChangeIndexWithHistory);
+          addressesToStore.addAll(tuple.item1);
         }
-      } catch (e, s) {
-        Logging.instance.log(
-            "Exception rethrown from recoverWalletFromBIP32SeedPhrase(): $e\n$s",
-            level: LogLevel.Error);
-        rethrow;
       }
-    }
 
-    // If restoring a wallet that never received any funds, then set receivingArray manually
-    // If we didn't do this, it'd store an empty array
-    if (receivingIndex == -1) {
-      final receivingAddress = await _generateAddressForChain(0, 0);
-      receivingAddressArray.add(receivingAddress);
-    }
+      // remove extra addresses to help minimize risk of creating a large gap
+      addressesToStore.removeWhere((e) =>
+          e.subType == isar_models.AddressSubType.change &&
+          e.derivationIndex > highestChangeIndexWithHistory);
+      addressesToStore.removeWhere((e) =>
+          e.subType == isar_models.AddressSubType.receiving &&
+          e.derivationIndex > highestReceivingIndexWithHistory);
 
-    // 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.
-    if (changeIndex == -1) {
-      final changeAddress = await _generateAddressForChain(1, 0);
-      changeAddressArray.add(changeAddress);
-    }
+      if (isRescan) {
+        await db.updateOrPutAddresses(addressesToStore);
+      } else {
+        await db.putAddresses(addressesToStore);
+      }
 
-    await db.updateOrPutAddresses([
-      ...receivingAddressArray,
-      ...changeAddressArray,
-    ]);
+      await Future.wait([
+        _refreshTransactions(),
+        _refreshUTXOs(),
+      ]);
+
+      await Future.wait([
+        updateCachedId(walletId),
+        updateCachedIsFavorite(false),
+      ]);
+
+      longMutex = false;
+    } catch (e, s) {
+      Logging.instance.log(
+          "Exception rethrown from _recoverWalletFromBIP32SeedPhrase(): $e\n$s",
+          level: LogLevel.Error);
+
+      longMutex = false;
+      rethrow;
+    }
   }
 
   /// Recovers wallet from [suppliedMnemonic]. Expects a valid mnemonic.
@@ -4506,6 +4349,8 @@ class FiroWallet extends CoinServiceAPI
     String suppliedMnemonic,
     String mnemonicPassphrase,
     int maxUnusedAddressGap,
+    int maxNumberOfIndexesToCheck,
+    bool isRescan,
   ) async {
     longMutex = true;
     Logging.instance
@@ -4513,16 +4358,26 @@ class FiroWallet extends CoinServiceAPI
     try {
       final latestSetId = await getLatestSetId();
       final setDataMap = getSetDataMap(latestSetId);
+
       final usedSerialNumbers = getUsedCoinSerials();
-      final makeDerivations = _makeDerivations(
-          suppliedMnemonic, mnemonicPassphrase, maxUnusedAddressGap);
+      final generateAndCheckAddresses = _recoverHistory(
+        suppliedMnemonic,
+        mnemonicPassphrase,
+        maxUnusedAddressGap,
+        maxNumberOfIndexesToCheck,
+        isRescan,
+      );
 
       await Future.wait([
         updateCachedId(walletId),
         updateCachedIsFavorite(false),
       ]);
 
-      await Future.wait([usedSerialNumbers, setDataMap, makeDerivations]);
+      await Future.wait([
+        usedSerialNumbers,
+        setDataMap,
+        generateAndCheckAddresses,
+      ]);
 
       await _restore(latestSetId, await setDataMap, await usedSerialNumbers);
       longMutex = false;
@@ -4535,8 +4390,11 @@ class FiroWallet extends CoinServiceAPI
     }
   }
 
-  Future<void> _restore(int latestSetId, Map<dynamic, dynamic> setDataMap,
-      dynamic usedSerialNumbers) async {
+  Future<void> _restore(
+    int latestSetId,
+    Map<dynamic, dynamic> setDataMap,
+    List<String> usedSerialNumbers,
+  ) async {
     final _mnemonic = await mnemonicString;
     final _mnemonicPassphrase = await mnemonicPassphrase;
 
@@ -4707,11 +4565,13 @@ class FiroWallet extends CoinServiceAPI
     }
   }
 
-  Future<List<dynamic>> getUsedCoinSerials() async {
+  Future<List<String>> getUsedCoinSerials() async {
     try {
       final response = await cachedElectrumXClient.getUsedCoinSerials(
         coin: coin,
       );
+      print("getUsedCoinSerials");
+      print(response);
       return response;
     } catch (e, s) {
       Logging.instance.log("Exception rethrown in firo_wallet.dart: $e\n$s",
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 026d06a20..b63e29f34 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
@@ -175,7 +175,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX {
             _i9.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i9.Future<Map<String, dynamic>>);
   @override
-  _i9.Future<List<dynamic>> getUsedCoinSerials({
+  _i9.Future<List<String>> getUsedCoinSerials({
     required _i10.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -188,8 +188,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i9.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i9.Future<List<dynamic>>);
+        returnValue: _i9.Future<List<String>>.value(<String>[]),
+      ) as _i9.Future<List<String>>);
   @override
   _i9.Future<void> clearSharedTransactionCache({required _i10.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart
index 12ae0ae62..93eb0e1c8 100644
--- a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart
+++ b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart
@@ -487,7 +487,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i5.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
+  _i5.Future<List<String>> getUsedCoinSerials({
     required _i7.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -500,8 +500,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i5.Future<List<String>>.value(<String>[]),
+      ) as _i5.Future<List<String>>);
   @override
   _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart
index 699278ce1..05cd24ebd 100644
--- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart
+++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart
@@ -487,7 +487,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i5.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
+  _i5.Future<List<String>> getUsedCoinSerials({
     required _i7.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -500,8 +500,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i5.Future<List<String>>.value(<String>[]),
+      ) as _i5.Future<List<String>>);
   @override
   _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart
index 3c78f6dc6..ff04b9f73 100644
--- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart
+++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart
@@ -487,7 +487,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i5.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
+  _i5.Future<List<String>> getUsedCoinSerials({
     required _i7.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -500,8 +500,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i5.Future<List<String>>.value(<String>[]),
+      ) as _i5.Future<List<String>>);
   @override
   _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/services/coins/firo/firo_wallet_test.dart b/test/services/coins/firo/firo_wallet_test.dart
index d7b23e51e..766df279f 100644
--- a/test/services/coins/firo/firo_wallet_test.dart
+++ b/test/services/coins/firo/firo_wallet_test.dart
@@ -8,6 +8,7 @@ import 'package:hive/hive.dart';
 import 'package:hive_test/hive_test.dart';
 import 'package:mockito/annotations.dart';
 import 'package:mockito/mockito.dart';
+import 'package:stackwallet/db/isar/main_db.dart';
 import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
 import 'package:stackwallet/electrumx_rpc/electrumx.dart';
 import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
@@ -17,7 +18,6 @@ import 'package:stackwallet/models/lelantus_fee_data.dart';
 import 'package:stackwallet/models/paymint/transactions_model.dart' as old;
 import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
 import 'package:stackwallet/services/transaction_notification_tracker.dart';
-import 'package:stackwallet/utilities/address_utils.dart';
 import 'package:stackwallet/utilities/amount/amount.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
@@ -34,16 +34,10 @@ import 'sample_data/transaction_data_samples.dart';
   ElectrumX,
   CachedElectrumX,
   TransactionNotificationTracker,
+  MainDB,
 ])
 void main() {
   group("isolate functions", () {
-    test("isolateDerive", () async {
-      final result = await isolateDerive(
-          IsolateDeriveParams.mnemonic, "", 0, 2, firoNetwork);
-      expect(result, isA<Map<String, dynamic>>());
-      expect(result.toString(), IsolateDeriveParams.expected);
-    });
-
     test("isolateRestore success", () async {
       final cachedClient = MockCachedElectrumX();
       final txDataOLD = old.TransactionData.fromJson(dateTimeChunksJson);
@@ -76,7 +70,7 @@ void main() {
         Coin.firo,
         1,
         setData,
-        usedSerials,
+        List<String>.from(usedSerials),
         firoNetwork,
       );
       const currentHeight = 100000000000;
@@ -136,7 +130,7 @@ void main() {
                 Coin.firo,
                 1,
                 setData,
-                usedSerials,
+                List<String>.from(usedSerials),
                 firoNetwork,
               ),
           throwsA(isA<Error>()));
@@ -1169,42 +1163,6 @@ void main() {
           "b36161c6e619395b3d40a851c45c1fef7a5c541eed911b5524a66c5703a689c9");
     });
 
-    test("fillAddresses", () async {
-      final client = MockElectrumX();
-      final cachedClient = MockCachedElectrumX();
-      final secureStore = FakeSecureStorage();
-
-      final firo = FiroWallet(
-        walletName: testWalletName,
-        walletId: "${testWalletId}fillAddresses",
-        coin: Coin.firo,
-        client: client,
-        cachedClient: cachedClient,
-        secureStore: secureStore,
-        tracker: MockTransactionNotificationTracker(),
-      );
-
-      await firo.fillAddresses(
-        FillAddressesParams.mnemonic,
-        "",
-      );
-
-      final rcv = await secureStore.read(
-          key: "${testWalletId}fillAddresses_receiveDerivations");
-      final chg = await secureStore.read(
-          key: "${testWalletId}fillAddresses_changeDerivations");
-      final receiveDerivations =
-          Map<String, dynamic>.from(jsonDecode(rcv as String) as Map);
-      final changeDerivations =
-          Map<String, dynamic>.from(jsonDecode(chg as String) as Map);
-
-      expect(receiveDerivations.toString(),
-          FillAddressesParams.expectedReceiveDerivationsString);
-
-      expect(changeDerivations.toString(),
-          FillAddressesParams.expectedChangeDerivationsString);
-    });
-
     // the above test needs to pass in order for this test to pass
     test("buildMintTransaction", () async {
       TestWidgetsFlutterBinding.ensureInitialized();
@@ -1230,6 +1188,7 @@ void main() {
       final client = MockElectrumX();
       final cachedClient = MockCachedElectrumX();
       final secureStore = FakeSecureStorage();
+      final mainDB = MockMainDB();
 
       await secureStore.write(
           key: "${testWalletId}buildMintTransaction_mnemonic",
@@ -1246,6 +1205,9 @@ void main() {
       when(client.getBlockHeadTip()).thenAnswer(
           (_) async => {"height": 455873, "hex": "this value not used here"});
 
+      when(mainDB.getAddress("${testWalletId}buildMintTransaction", any))
+          .thenAnswer((realInvocation) async => null);
+
       final firo = FiroWallet(
         walletName: testWalletName,
         walletId: "${testWalletId}buildMintTransaction",
@@ -1254,6 +1216,7 @@ void main() {
         cachedClient: cachedClient,
         secureStore: secureStore,
         tracker: MockTransactionNotificationTracker(),
+        mockableOverride: mainDB,
       );
 
       final wallet =
@@ -2314,8 +2277,8 @@ void main() {
               groupId: "1", blockhash: "", coin: Coin.firo))
           .thenAnswer((_) async => GetAnonymitySetSampleData.data);
       when(cachedClient.getUsedCoinSerials(startNumber: 0, coin: Coin.firo))
-          .thenAnswer(
-              (_) async => GetUsedSerialsSampleData.serials['serials'] as List);
+          .thenAnswer((_) async => List<String>.from(
+              GetUsedSerialsSampleData.serials['serials'] as List));
 
       final firo = FiroWallet(
         walletId: "${testWalletId}getUsedCoinSerials",
@@ -2811,169 +2774,6 @@ void main() {
     //       throwsA(isA<Exception>()));
     // }, timeout: const Timeout(Duration(minutes: 3)));
 
-    test("send fails due to bad transaction created", () async {
-      TestWidgetsFlutterBinding.ensureInitialized();
-      const MethodChannel('uk.spiralarm.flutter/devicelocale')
-          .setMockMethodCallHandler((methodCall) async => 'en_US');
-
-      final client = MockElectrumX();
-      final cachedClient = MockCachedElectrumX();
-      final secureStore = FakeSecureStorage();
-
-      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
-      when(client.getBlockHeadTip()).thenAnswer(
-          (_) async => {"height": 459185, "hex": "... some block hex ..."});
-
-      when(client.broadcastTransaction(rawTx: anyNamed("rawTx")))
-          .thenAnswer((_) async {
-        return "some bad txid";
-      });
-
-      when(client.getBatchHistory(args: batchHistoryRequest0))
-          .thenAnswer((realInvocation) async => batchHistoryResponse0);
-
-      when(cachedClient.getAnonymitySet(
-        groupId: "1",
-        coin: Coin.firo,
-      )).thenAnswer((_) async => GetAnonymitySetSampleData.data);
-
-      // mock transaction calls
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash0,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData0);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash1,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData1);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash2,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData2);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash3,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData3);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash4,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData4);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash5,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData5);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash6,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData6);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash7,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData7);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash8,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData8);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash9,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData9);
-      when(cachedClient.getTransaction(
-        txHash: SampleGetTransactionData.txHash10,
-        coin: Coin.firo,
-      )).thenAnswer((_) async => SampleGetTransactionData.txData10);
-
-      final firo = FiroWallet(
-        walletId: "${testWalletId}send",
-        coin: Coin.firo,
-        walletName: testWalletName,
-        client: client,
-        cachedClient: cachedClient,
-        secureStore: secureStore,
-        tracker: MockTransactionNotificationTracker(),
-      );
-
-      // set mnemonic
-      await secureStore.write(
-          key: "${testWalletId}send_mnemonic", value: TEST_MNEMONIC);
-
-      // set timer to non null so a periodic timer isn't created
-      firo.timer = Timer(const Duration(), () {});
-
-      // build sending wallet
-      await firo.fillAddresses(
-        TEST_MNEMONIC,
-        "",
-      );
-      final wallet = await Hive.openBox<dynamic>("${testWalletId}send");
-
-      final rcv =
-          await secureStore.read(key: "${testWalletId}send_receiveDerivations");
-      final chg =
-          await secureStore.read(key: "${testWalletId}send_changeDerivations");
-      final receiveDerivations =
-          Map<String, dynamic>.from(jsonDecode(rcv as String) as Map);
-      final changeDerivations =
-          Map<String, dynamic>.from(jsonDecode(chg as String) as Map);
-
-      for (int i = 0; i < receiveDerivations.length; i++) {
-        final receiveHash = AddressUtils.convertToScriptHash(
-            receiveDerivations["$i"]!["address"] as String, firoNetwork);
-        final changeHash = AddressUtils.convertToScriptHash(
-            changeDerivations["$i"]!["address"] as String, firoNetwork);
-        List<Map<String, dynamic>> data;
-        switch (receiveHash) {
-          case SampleGetHistoryData.scripthash0:
-            data = SampleGetHistoryData.data0;
-            break;
-          case SampleGetHistoryData.scripthash1:
-            data = SampleGetHistoryData.data1;
-            break;
-          case SampleGetHistoryData.scripthash2:
-            data = SampleGetHistoryData.data2;
-            break;
-          case SampleGetHistoryData.scripthash3:
-            data = SampleGetHistoryData.data3;
-            break;
-          default:
-            data = [];
-        }
-        when(client.getHistory(scripthash: receiveHash))
-            .thenAnswer((_) async => data);
-
-        switch (changeHash) {
-          case SampleGetHistoryData.scripthash0:
-            data = SampleGetHistoryData.data0;
-            break;
-          case SampleGetHistoryData.scripthash1:
-            data = SampleGetHistoryData.data1;
-            break;
-          case SampleGetHistoryData.scripthash2:
-            data = SampleGetHistoryData.data2;
-            break;
-          case SampleGetHistoryData.scripthash3:
-            data = SampleGetHistoryData.data3;
-            break;
-          default:
-            data = [];
-        }
-
-        when(client.getHistory(scripthash: changeHash))
-            .thenAnswer((_) async => data);
-      }
-
-      await wallet.put('_lelantus_coins', SampleLelantus.lelantusCoins);
-      await wallet.put('jindex', [2, 4, 6]);
-      await wallet.put('mintIndex', 8);
-      await wallet.put('receivingAddresses', [
-        "a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg",
-        "aPjLWDTPQsoPHUTxKBNRzoebDALj3eTcfh",
-        "aKmXfS7nEZdqWBGRdAXcyMoEoKhZQDPBoq"
-      ]);
-      await wallet
-          .put('changeAddresses', ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);
-    }, timeout: const Timeout(Duration(minutes: 3)));
-
     // test("wallet balances", () async {
     //   TestWidgetsFlutterBinding.ensureInitialized();
     //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
diff --git a/test/services/coins/firo/firo_wallet_test.mocks.dart b/test/services/coins/firo/firo_wallet_test.mocks.dart
index 0e3549d87..bb6d13ca7 100644
--- a/test/services/coins/firo/firo_wallet_test.mocks.dart
+++ b/test/services/coins/firo/firo_wallet_test.mocks.dart
@@ -3,16 +3,22 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i5;
+import 'dart:async' as _i6;
 
 import 'package:decimal/decimal.dart' as _i2;
+import 'package:isar/isar.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i6;
-import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i4;
+import 'package:stackwallet/db/isar/main_db.dart' as _i10;
+import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i7;
+import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i5;
+import 'package:stackwallet/models/isar/models/block_explorer.dart' as _i12;
+import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i11;
+import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
 import 'package:stackwallet/services/transaction_notification_tracker.dart'
-    as _i8;
-import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i7;
+    as _i9;
+import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i8;
 import 'package:stackwallet/utilities/prefs.dart' as _i3;
+import 'package:tuple/tuple.dart' as _i14;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -45,16 +51,37 @@ class _FakePrefs_1 extends _i1.SmartFake implements _i3.Prefs {
         );
 }
 
+class _FakeIsar_2 extends _i1.SmartFake implements _i4.Isar {
+  _FakeIsar_2(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
+
+class _FakeQueryBuilder_3<OBJ, R, S> extends _i1.SmartFake
+    implements _i4.QueryBuilder<OBJ, R, S> {
+  _FakeQueryBuilder_3(
+    Object parent,
+    Invocation parentInvocation,
+  ) : super(
+          parent,
+          parentInvocation,
+        );
+}
+
 /// A class which mocks [ElectrumX].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
+class MockElectrumX extends _i1.Mock implements _i5.ElectrumX {
   MockElectrumX() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  set failovers(List<_i4.ElectrumXNode>? _failovers) => super.noSuchMethod(
+  set failovers(List<_i5.ElectrumXNode>? _failovers) => super.noSuchMethod(
         Invocation.setter(
           #failovers,
           _failovers,
@@ -90,7 +117,7 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
         returnValue: false,
       ) as bool);
   @override
-  _i5.Future<dynamic> request({
+  _i6.Future<dynamic> request({
     required String? command,
     List<dynamic>? args = const [],
     Duration? connectionTimeout = const Duration(seconds: 60),
@@ -109,10 +136,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #retries: retries,
           },
         ),
-        returnValue: _i5.Future<dynamic>.value(),
-      ) as _i5.Future<dynamic>);
+        returnValue: _i6.Future<dynamic>.value(),
+      ) as _i6.Future<dynamic>);
   @override
-  _i5.Future<List<Map<String, dynamic>>> batchRequest({
+  _i6.Future<List<Map<String, dynamic>>> batchRequest({
     required String? command,
     required Map<String, List<dynamic>>? args,
     Duration? connectionTimeout = const Duration(seconds: 60),
@@ -129,11 +156,11 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #retries: retries,
           },
         ),
-        returnValue: _i5.Future<List<Map<String, dynamic>>>.value(
+        returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
             <Map<String, dynamic>>[]),
-      ) as _i5.Future<List<Map<String, dynamic>>>);
+      ) as _i6.Future<List<Map<String, dynamic>>>);
   @override
-  _i5.Future<bool> ping({
+  _i6.Future<bool> ping({
     String? requestID,
     int? retryCount = 1,
   }) =>
@@ -146,10 +173,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #retryCount: retryCount,
           },
         ),
-        returnValue: _i5.Future<bool>.value(false),
-      ) as _i5.Future<bool>);
+        returnValue: _i6.Future<bool>.value(false),
+      ) as _i6.Future<bool>);
   @override
-  _i5.Future<Map<String, dynamic>> getBlockHeadTip({String? requestID}) =>
+  _i6.Future<Map<String, dynamic>> getBlockHeadTip({String? requestID}) =>
       (super.noSuchMethod(
         Invocation.method(
           #getBlockHeadTip,
@@ -157,10 +184,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           {#requestID: requestID},
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<Map<String, dynamic>> getServerFeatures({String? requestID}) =>
+  _i6.Future<Map<String, dynamic>> getServerFeatures({String? requestID}) =>
       (super.noSuchMethod(
         Invocation.method(
           #getServerFeatures,
@@ -168,10 +195,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           {#requestID: requestID},
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<String> broadcastTransaction({
+  _i6.Future<String> broadcastTransaction({
     required String? rawTx,
     String? requestID,
   }) =>
@@ -184,10 +211,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #requestID: requestID,
           },
         ),
-        returnValue: _i5.Future<String>.value(''),
-      ) as _i5.Future<String>);
+        returnValue: _i6.Future<String>.value(''),
+      ) as _i6.Future<String>);
   @override
-  _i5.Future<Map<String, dynamic>> getBalance({
+  _i6.Future<Map<String, dynamic>> getBalance({
     required String? scripthash,
     String? requestID,
   }) =>
@@ -201,10 +228,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<Map<String, dynamic>>> getHistory({
+  _i6.Future<List<Map<String, dynamic>>> getHistory({
     required String? scripthash,
     String? requestID,
   }) =>
@@ -217,11 +244,11 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #requestID: requestID,
           },
         ),
-        returnValue: _i5.Future<List<Map<String, dynamic>>>.value(
+        returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
             <Map<String, dynamic>>[]),
-      ) as _i5.Future<List<Map<String, dynamic>>>);
+      ) as _i6.Future<List<Map<String, dynamic>>>);
   @override
-  _i5.Future<Map<String, List<Map<String, dynamic>>>> getBatchHistory(
+  _i6.Future<Map<String, List<Map<String, dynamic>>>> getBatchHistory(
           {required Map<String, List<dynamic>>? args}) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -229,11 +256,11 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           [],
           {#args: args},
         ),
-        returnValue: _i5.Future<Map<String, List<Map<String, dynamic>>>>.value(
+        returnValue: _i6.Future<Map<String, List<Map<String, dynamic>>>>.value(
             <String, List<Map<String, dynamic>>>{}),
-      ) as _i5.Future<Map<String, List<Map<String, dynamic>>>>);
+      ) as _i6.Future<Map<String, List<Map<String, dynamic>>>>);
   @override
-  _i5.Future<List<Map<String, dynamic>>> getUTXOs({
+  _i6.Future<List<Map<String, dynamic>>> getUTXOs({
     required String? scripthash,
     String? requestID,
   }) =>
@@ -246,11 +273,11 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #requestID: requestID,
           },
         ),
-        returnValue: _i5.Future<List<Map<String, dynamic>>>.value(
+        returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
             <Map<String, dynamic>>[]),
-      ) as _i5.Future<List<Map<String, dynamic>>>);
+      ) as _i6.Future<List<Map<String, dynamic>>>);
   @override
-  _i5.Future<Map<String, List<Map<String, dynamic>>>> getBatchUTXOs(
+  _i6.Future<Map<String, List<Map<String, dynamic>>>> getBatchUTXOs(
           {required Map<String, List<dynamic>>? args}) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -258,11 +285,11 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           [],
           {#args: args},
         ),
-        returnValue: _i5.Future<Map<String, List<Map<String, dynamic>>>>.value(
+        returnValue: _i6.Future<Map<String, List<Map<String, dynamic>>>>.value(
             <String, List<Map<String, dynamic>>>{}),
-      ) as _i5.Future<Map<String, List<Map<String, dynamic>>>>);
+      ) as _i6.Future<Map<String, List<Map<String, dynamic>>>>);
   @override
-  _i5.Future<Map<String, dynamic>> getTransaction({
+  _i6.Future<Map<String, dynamic>> getTransaction({
     required String? txHash,
     bool? verbose = true,
     String? requestID,
@@ -278,10 +305,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<Map<String, dynamic>> getAnonymitySet({
+  _i6.Future<Map<String, dynamic>> getAnonymitySet({
     String? groupId = r'1',
     String? blockhash = r'',
     String? requestID,
@@ -297,10 +324,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<dynamic> getMintData({
+  _i6.Future<dynamic> getMintData({
     dynamic mints,
     String? requestID,
   }) =>
@@ -313,10 +340,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #requestID: requestID,
           },
         ),
-        returnValue: _i5.Future<dynamic>.value(),
-      ) as _i5.Future<dynamic>);
+        returnValue: _i6.Future<dynamic>.value(),
+      ) as _i6.Future<dynamic>);
   @override
-  _i5.Future<Map<String, dynamic>> getUsedCoinSerials({
+  _i6.Future<Map<String, dynamic>> getUsedCoinSerials({
     String? requestID,
     required int? startNumber,
   }) =>
@@ -330,19 +357,19 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<int> getLatestCoinId({String? requestID}) => (super.noSuchMethod(
+  _i6.Future<int> getLatestCoinId({String? requestID}) => (super.noSuchMethod(
         Invocation.method(
           #getLatestCoinId,
           [],
           {#requestID: requestID},
         ),
-        returnValue: _i5.Future<int>.value(0),
-      ) as _i5.Future<int>);
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
   @override
-  _i5.Future<Map<String, dynamic>> getFeeRate({String? requestID}) =>
+  _i6.Future<Map<String, dynamic>> getFeeRate({String? requestID}) =>
       (super.noSuchMethod(
         Invocation.method(
           #getFeeRate,
@@ -350,10 +377,10 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
           {#requestID: requestID},
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<_i2.Decimal> estimateFee({
+  _i6.Future<_i2.Decimal> estimateFee({
     String? requestID,
     required int? blocks,
   }) =>
@@ -366,7 +393,7 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             #blocks: blocks,
           },
         ),
-        returnValue: _i5.Future<_i2.Decimal>.value(_FakeDecimal_0(
+        returnValue: _i6.Future<_i2.Decimal>.value(_FakeDecimal_0(
           this,
           Invocation.method(
             #estimateFee,
@@ -377,15 +404,15 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             },
           ),
         )),
-      ) as _i5.Future<_i2.Decimal>);
+      ) as _i6.Future<_i2.Decimal>);
   @override
-  _i5.Future<_i2.Decimal> relayFee({String? requestID}) => (super.noSuchMethod(
+  _i6.Future<_i2.Decimal> relayFee({String? requestID}) => (super.noSuchMethod(
         Invocation.method(
           #relayFee,
           [],
           {#requestID: requestID},
         ),
-        returnValue: _i5.Future<_i2.Decimal>.value(_FakeDecimal_0(
+        returnValue: _i6.Future<_i2.Decimal>.value(_FakeDecimal_0(
           this,
           Invocation.method(
             #relayFee,
@@ -393,13 +420,13 @@ class MockElectrumX extends _i1.Mock implements _i4.ElectrumX {
             {#requestID: requestID},
           ),
         )),
-      ) as _i5.Future<_i2.Decimal>);
+      ) as _i6.Future<_i2.Decimal>);
 }
 
 /// A class which mocks [CachedElectrumX].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
+class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX {
   MockCachedElectrumX() {
     _i1.throwOnMissingStub(this);
   }
@@ -428,15 +455,15 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
         ),
       ) as _i3.Prefs);
   @override
-  List<_i4.ElectrumXNode> get failovers => (super.noSuchMethod(
+  List<_i5.ElectrumXNode> get failovers => (super.noSuchMethod(
         Invocation.getter(#failovers),
-        returnValue: <_i4.ElectrumXNode>[],
-      ) as List<_i4.ElectrumXNode>);
+        returnValue: <_i5.ElectrumXNode>[],
+      ) as List<_i5.ElectrumXNode>);
   @override
-  _i5.Future<Map<String, dynamic>> getAnonymitySet({
+  _i6.Future<Map<String, dynamic>> getAnonymitySet({
     required String? groupId,
     String? blockhash = r'',
-    required _i7.Coin? coin,
+    required _i8.Coin? coin,
   }) =>
       (super.noSuchMethod(
         Invocation.method(
@@ -449,8 +476,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
   String base64ToHex(String? source) => (super.noSuchMethod(
         Invocation.method(
@@ -468,9 +495,9 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
         returnValue: '',
       ) as String);
   @override
-  _i5.Future<Map<String, dynamic>> getTransaction({
+  _i6.Future<Map<String, dynamic>> getTransaction({
     required String? txHash,
-    required _i7.Coin? coin,
+    required _i8.Coin? coin,
     bool? verbose = true,
   }) =>
       (super.noSuchMethod(
@@ -484,11 +511,11 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
           },
         ),
         returnValue:
-            _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
-      ) as _i5.Future<Map<String, dynamic>>);
+            _i6.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
+      ) as _i6.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
-    required _i7.Coin? coin,
+  _i6.Future<List<String>> getUsedCoinSerials({
+    required _i8.Coin? coin,
     int? startNumber = 0,
   }) =>
       (super.noSuchMethod(
@@ -500,26 +527,26 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i6.Future<List<String>>.value(<String>[]),
+      ) as _i6.Future<List<String>>);
   @override
-  _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
+  _i6.Future<void> clearSharedTransactionCache({required _i8.Coin? coin}) =>
       (super.noSuchMethod(
         Invocation.method(
           #clearSharedTransactionCache,
           [],
           {#coin: coin},
         ),
-        returnValue: _i5.Future<void>.value(),
-        returnValueForMissingStub: _i5.Future<void>.value(),
-      ) as _i5.Future<void>);
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
 }
 
 /// A class which mocks [TransactionNotificationTracker].
 ///
 /// See the documentation for Mockito's code generation for more information.
 class MockTransactionNotificationTracker extends _i1.Mock
-    implements _i8.TransactionNotificationTracker {
+    implements _i9.TransactionNotificationTracker {
   MockTransactionNotificationTracker() {
     _i1.throwOnMissingStub(this);
   }
@@ -548,14 +575,14 @@ class MockTransactionNotificationTracker extends _i1.Mock
         returnValue: false,
       ) as bool);
   @override
-  _i5.Future<void> addNotifiedPending(String? txid) => (super.noSuchMethod(
+  _i6.Future<void> addNotifiedPending(String? txid) => (super.noSuchMethod(
         Invocation.method(
           #addNotifiedPending,
           [txid],
         ),
-        returnValue: _i5.Future<void>.value(),
-        returnValueForMissingStub: _i5.Future<void>.value(),
-      ) as _i5.Future<void>);
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
   @override
   bool wasNotifiedConfirmed(String? txid) => (super.noSuchMethod(
         Invocation.method(
@@ -565,21 +592,582 @@ class MockTransactionNotificationTracker extends _i1.Mock
         returnValue: false,
       ) as bool);
   @override
-  _i5.Future<void> addNotifiedConfirmed(String? txid) => (super.noSuchMethod(
+  _i6.Future<void> addNotifiedConfirmed(String? txid) => (super.noSuchMethod(
         Invocation.method(
           #addNotifiedConfirmed,
           [txid],
         ),
-        returnValue: _i5.Future<void>.value(),
-        returnValueForMissingStub: _i5.Future<void>.value(),
-      ) as _i5.Future<void>);
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
   @override
-  _i5.Future<void> deleteTransaction(String? txid) => (super.noSuchMethod(
+  _i6.Future<void> deleteTransaction(String? txid) => (super.noSuchMethod(
         Invocation.method(
           #deleteTransaction,
           [txid],
         ),
-        returnValue: _i5.Future<void>.value(),
-        returnValueForMissingStub: _i5.Future<void>.value(),
-      ) as _i5.Future<void>);
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+}
+
+/// A class which mocks [MainDB].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockMainDB extends _i1.Mock implements _i10.MainDB {
+  MockMainDB() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  _i4.Isar get isar => (super.noSuchMethod(
+        Invocation.getter(#isar),
+        returnValue: _FakeIsar_2(
+          this,
+          Invocation.getter(#isar),
+        ),
+      ) as _i4.Isar);
+  @override
+  _i6.Future<bool> initMainDB({_i4.Isar? mock}) => (super.noSuchMethod(
+        Invocation.method(
+          #initMainDB,
+          [],
+          {#mock: mock},
+        ),
+        returnValue: _i6.Future<bool>.value(false),
+      ) as _i6.Future<bool>);
+  @override
+  List<_i11.ContactEntry> getContactEntries() => (super.noSuchMethod(
+        Invocation.method(
+          #getContactEntries,
+          [],
+        ),
+        returnValue: <_i11.ContactEntry>[],
+      ) as List<_i11.ContactEntry>);
+  @override
+  _i6.Future<bool> deleteContactEntry({required String? id}) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #deleteContactEntry,
+          [],
+          {#id: id},
+        ),
+        returnValue: _i6.Future<bool>.value(false),
+      ) as _i6.Future<bool>);
+  @override
+  _i6.Future<bool> isContactEntryExists({required String? id}) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #isContactEntryExists,
+          [],
+          {#id: id},
+        ),
+        returnValue: _i6.Future<bool>.value(false),
+      ) as _i6.Future<bool>);
+  @override
+  _i11.ContactEntry? getContactEntry({required String? id}) =>
+      (super.noSuchMethod(Invocation.method(
+        #getContactEntry,
+        [],
+        {#id: id},
+      )) as _i11.ContactEntry?);
+  @override
+  _i6.Future<bool> putContactEntry(
+          {required _i11.ContactEntry? contactEntry}) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putContactEntry,
+          [],
+          {#contactEntry: contactEntry},
+        ),
+        returnValue: _i6.Future<bool>.value(false),
+      ) as _i6.Future<bool>);
+  @override
+  _i12.TransactionBlockExplorer? getTransactionBlockExplorer(
+          {required _i8.Coin? coin}) =>
+      (super.noSuchMethod(Invocation.method(
+        #getTransactionBlockExplorer,
+        [],
+        {#coin: coin},
+      )) as _i12.TransactionBlockExplorer?);
+  @override
+  _i6.Future<int> putTransactionBlockExplorer(
+          _i12.TransactionBlockExplorer? explorer) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putTransactionBlockExplorer,
+          [explorer],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i4.QueryBuilder<_i13.Address, _i13.Address, _i4.QAfterWhereClause>
+      getAddresses(String? walletId) => (super.noSuchMethod(
+            Invocation.method(
+              #getAddresses,
+              [walletId],
+            ),
+            returnValue: _FakeQueryBuilder_3<_i13.Address, _i13.Address,
+                _i4.QAfterWhereClause>(
+              this,
+              Invocation.method(
+                #getAddresses,
+                [walletId],
+              ),
+            ),
+          ) as _i4
+              .QueryBuilder<_i13.Address, _i13.Address, _i4.QAfterWhereClause>);
+  @override
+  _i6.Future<int> putAddress(_i13.Address? address) => (super.noSuchMethod(
+        Invocation.method(
+          #putAddress,
+          [address],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i6.Future<List<int>> putAddresses(List<_i13.Address>? addresses) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putAddresses,
+          [addresses],
+        ),
+        returnValue: _i6.Future<List<int>>.value(<int>[]),
+      ) as _i6.Future<List<int>>);
+  @override
+  _i6.Future<List<int>> updateOrPutAddresses(List<_i13.Address>? addresses) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #updateOrPutAddresses,
+          [addresses],
+        ),
+        returnValue: _i6.Future<List<int>>.value(<int>[]),
+      ) as _i6.Future<List<int>>);
+  @override
+  _i6.Future<_i13.Address?> getAddress(
+    String? walletId,
+    String? address,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getAddress,
+          [
+            walletId,
+            address,
+          ],
+        ),
+        returnValue: _i6.Future<_i13.Address?>.value(),
+      ) as _i6.Future<_i13.Address?>);
+  @override
+  _i6.Future<int> updateAddress(
+    _i13.Address? oldAddress,
+    _i13.Address? newAddress,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #updateAddress,
+          [
+            oldAddress,
+            newAddress,
+          ],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i4.QueryBuilder<_i13.Transaction, _i13.Transaction, _i4.QAfterWhereClause>
+      getTransactions(String? walletId) => (super.noSuchMethod(
+            Invocation.method(
+              #getTransactions,
+              [walletId],
+            ),
+            returnValue: _FakeQueryBuilder_3<_i13.Transaction, _i13.Transaction,
+                _i4.QAfterWhereClause>(
+              this,
+              Invocation.method(
+                #getTransactions,
+                [walletId],
+              ),
+            ),
+          ) as _i4.QueryBuilder<_i13.Transaction, _i13.Transaction,
+              _i4.QAfterWhereClause>);
+  @override
+  _i6.Future<int> putTransaction(_i13.Transaction? transaction) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putTransaction,
+          [transaction],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i6.Future<List<int>> putTransactions(List<_i13.Transaction>? transactions) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putTransactions,
+          [transactions],
+        ),
+        returnValue: _i6.Future<List<int>>.value(<int>[]),
+      ) as _i6.Future<List<int>>);
+  @override
+  _i6.Future<_i13.Transaction?> getTransaction(
+    String? walletId,
+    String? txid,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getTransaction,
+          [
+            walletId,
+            txid,
+          ],
+        ),
+        returnValue: _i6.Future<_i13.Transaction?>.value(),
+      ) as _i6.Future<_i13.Transaction?>);
+  @override
+  _i6.Stream<_i13.Transaction?> watchTransaction({
+    required int? id,
+    bool? fireImmediately = false,
+  }) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #watchTransaction,
+          [],
+          {
+            #id: id,
+            #fireImmediately: fireImmediately,
+          },
+        ),
+        returnValue: _i6.Stream<_i13.Transaction?>.empty(),
+      ) as _i6.Stream<_i13.Transaction?>);
+  @override
+  _i4.QueryBuilder<_i13.UTXO, _i13.UTXO, _i4.QAfterWhereClause> getUTXOs(
+          String? walletId) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getUTXOs,
+          [walletId],
+        ),
+        returnValue:
+            _FakeQueryBuilder_3<_i13.UTXO, _i13.UTXO, _i4.QAfterWhereClause>(
+          this,
+          Invocation.method(
+            #getUTXOs,
+            [walletId],
+          ),
+        ),
+      ) as _i4.QueryBuilder<_i13.UTXO, _i13.UTXO, _i4.QAfterWhereClause>);
+  @override
+  _i6.Future<void> putUTXO(_i13.UTXO? utxo) => (super.noSuchMethod(
+        Invocation.method(
+          #putUTXO,
+          [utxo],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> putUTXOs(List<_i13.UTXO>? utxos) => (super.noSuchMethod(
+        Invocation.method(
+          #putUTXOs,
+          [utxos],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> updateUTXOs(
+    String? walletId,
+    List<_i13.UTXO>? utxos,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #updateUTXOs,
+          [
+            walletId,
+            utxos,
+          ],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Stream<_i13.UTXO?> watchUTXO({
+    required int? id,
+    bool? fireImmediately = false,
+  }) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #watchUTXO,
+          [],
+          {
+            #id: id,
+            #fireImmediately: fireImmediately,
+          },
+        ),
+        returnValue: _i6.Stream<_i13.UTXO?>.empty(),
+      ) as _i6.Stream<_i13.UTXO?>);
+  @override
+  _i4.QueryBuilder<_i13.TransactionNote, _i13.TransactionNote,
+      _i4.QAfterWhereClause> getTransactionNotes(
+          String? walletId) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getTransactionNotes,
+          [walletId],
+        ),
+        returnValue: _FakeQueryBuilder_3<_i13.TransactionNote,
+            _i13.TransactionNote, _i4.QAfterWhereClause>(
+          this,
+          Invocation.method(
+            #getTransactionNotes,
+            [walletId],
+          ),
+        ),
+      ) as _i4.QueryBuilder<_i13.TransactionNote, _i13.TransactionNote,
+          _i4.QAfterWhereClause>);
+  @override
+  _i6.Future<void> putTransactionNote(_i13.TransactionNote? transactionNote) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putTransactionNote,
+          [transactionNote],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> putTransactionNotes(
+          List<_i13.TransactionNote>? transactionNotes) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putTransactionNotes,
+          [transactionNotes],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<_i13.TransactionNote?> getTransactionNote(
+    String? walletId,
+    String? txid,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getTransactionNote,
+          [
+            walletId,
+            txid,
+          ],
+        ),
+        returnValue: _i6.Future<_i13.TransactionNote?>.value(),
+      ) as _i6.Future<_i13.TransactionNote?>);
+  @override
+  _i6.Stream<_i13.TransactionNote?> watchTransactionNote({
+    required int? id,
+    bool? fireImmediately = false,
+  }) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #watchTransactionNote,
+          [],
+          {
+            #id: id,
+            #fireImmediately: fireImmediately,
+          },
+        ),
+        returnValue: _i6.Stream<_i13.TransactionNote?>.empty(),
+      ) as _i6.Stream<_i13.TransactionNote?>);
+  @override
+  _i4.QueryBuilder<_i13.AddressLabel, _i13.AddressLabel, _i4.QAfterWhereClause>
+      getAddressLabels(String? walletId) => (super.noSuchMethod(
+            Invocation.method(
+              #getAddressLabels,
+              [walletId],
+            ),
+            returnValue: _FakeQueryBuilder_3<_i13.AddressLabel,
+                _i13.AddressLabel, _i4.QAfterWhereClause>(
+              this,
+              Invocation.method(
+                #getAddressLabels,
+                [walletId],
+              ),
+            ),
+          ) as _i4.QueryBuilder<_i13.AddressLabel, _i13.AddressLabel,
+              _i4.QAfterWhereClause>);
+  @override
+  _i6.Future<int> putAddressLabel(_i13.AddressLabel? addressLabel) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putAddressLabel,
+          [addressLabel],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  int putAddressLabelSync(_i13.AddressLabel? addressLabel) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putAddressLabelSync,
+          [addressLabel],
+        ),
+        returnValue: 0,
+      ) as int);
+  @override
+  _i6.Future<void> putAddressLabels(List<_i13.AddressLabel>? addressLabels) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putAddressLabels,
+          [addressLabels],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<_i13.AddressLabel?> getAddressLabel(
+    String? walletId,
+    String? addressString,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getAddressLabel,
+          [
+            walletId,
+            addressString,
+          ],
+        ),
+        returnValue: _i6.Future<_i13.AddressLabel?>.value(),
+      ) as _i6.Future<_i13.AddressLabel?>);
+  @override
+  _i13.AddressLabel? getAddressLabelSync(
+    String? walletId,
+    String? addressString,
+  ) =>
+      (super.noSuchMethod(Invocation.method(
+        #getAddressLabelSync,
+        [
+          walletId,
+          addressString,
+        ],
+      )) as _i13.AddressLabel?);
+  @override
+  _i6.Stream<_i13.AddressLabel?> watchAddressLabel({
+    required int? id,
+    bool? fireImmediately = false,
+  }) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #watchAddressLabel,
+          [],
+          {
+            #id: id,
+            #fireImmediately: fireImmediately,
+          },
+        ),
+        returnValue: _i6.Stream<_i13.AddressLabel?>.empty(),
+      ) as _i6.Stream<_i13.AddressLabel?>);
+  @override
+  _i6.Future<int> updateAddressLabel(_i13.AddressLabel? addressLabel) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #updateAddressLabel,
+          [addressLabel],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i6.Future<void> deleteWalletBlockchainData(String? walletId) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #deleteWalletBlockchainData,
+          [walletId],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> deleteAddressLabels(String? walletId) => (super.noSuchMethod(
+        Invocation.method(
+          #deleteAddressLabels,
+          [walletId],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> deleteTransactionNotes(String? walletId) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #deleteTransactionNotes,
+          [walletId],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i6.Future<void> addNewTransactionData(
+    List<_i14.Tuple2<_i13.Transaction, _i13.Address?>>? transactionsData,
+    String? walletId,
+  ) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #addNewTransactionData,
+          [
+            transactionsData,
+            walletId,
+          ],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
+  @override
+  _i4.QueryBuilder<_i13.EthContract, _i13.EthContract, _i4.QWhere>
+      getEthContracts() => (super.noSuchMethod(
+            Invocation.method(
+              #getEthContracts,
+              [],
+            ),
+            returnValue: _FakeQueryBuilder_3<_i13.EthContract, _i13.EthContract,
+                _i4.QWhere>(
+              this,
+              Invocation.method(
+                #getEthContracts,
+                [],
+              ),
+            ),
+          ) as _i4
+              .QueryBuilder<_i13.EthContract, _i13.EthContract, _i4.QWhere>);
+  @override
+  _i6.Future<_i13.EthContract?> getEthContract(String? contractAddress) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getEthContract,
+          [contractAddress],
+        ),
+        returnValue: _i6.Future<_i13.EthContract?>.value(),
+      ) as _i6.Future<_i13.EthContract?>);
+  @override
+  _i13.EthContract? getEthContractSync(String? contractAddress) =>
+      (super.noSuchMethod(Invocation.method(
+        #getEthContractSync,
+        [contractAddress],
+      )) as _i13.EthContract?);
+  @override
+  _i6.Future<int> putEthContract(_i13.EthContract? contract) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putEthContract,
+          [contract],
+        ),
+        returnValue: _i6.Future<int>.value(0),
+      ) as _i6.Future<int>);
+  @override
+  _i6.Future<void> putEthContracts(List<_i13.EthContract>? contracts) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #putEthContracts,
+          [contracts],
+        ),
+        returnValue: _i6.Future<void>.value(),
+        returnValueForMissingStub: _i6.Future<void>.value(),
+      ) as _i6.Future<void>);
 }
diff --git a/test/services/coins/manager_test.mocks.dart b/test/services/coins/manager_test.mocks.dart
index 2319e31ba..8a607f14f 100644
--- a/test/services/coins/manager_test.mocks.dart
+++ b/test/services/coins/manager_test.mocks.dart
@@ -658,28 +658,6 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
         returnValueForMissingStub: _i11.Future<void>.value(),
       ) as _i11.Future<void>);
   @override
-  _i11.Future<void> fillAddresses(
-    String? suppliedMnemonic,
-    String? mnemonicPassphrase, {
-    int? perBatch = 50,
-    int? numberOfThreads = 4,
-  }) =>
-      (super.noSuchMethod(
-        Invocation.method(
-          #fillAddresses,
-          [
-            suppliedMnemonic,
-            mnemonicPassphrase,
-          ],
-          {
-            #perBatch: perBatch,
-            #numberOfThreads: numberOfThreads,
-          },
-        ),
-        returnValue: _i11.Future<void>.value(),
-        returnValueForMissingStub: _i11.Future<void>.value(),
-      ) as _i11.Future<void>);
-  @override
   _i11.Future<void> fullRescan(
     int? maxUnusedAddressGap,
     int? maxNumberOfIndexesToCheck,
@@ -728,6 +706,16 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
         returnValue: _i11.Future<Map<int, dynamic>>.value(<int, dynamic>{}),
       ) as _i11.Future<Map<int, dynamic>>);
   @override
+  _i11.Future<void> getTransactionCacheEarly(List<String>? allAddresses) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getTransactionCacheEarly,
+          [allAddresses],
+        ),
+        returnValue: _i11.Future<void>.value(),
+        returnValueForMissingStub: _i11.Future<void>.value(),
+      ) as _i11.Future<void>);
+  @override
   _i11.Future<List<Map<String, dynamic>>> fetchAnonymitySets() =>
       (super.noSuchMethod(
         Invocation.method(
@@ -746,13 +734,13 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
         returnValue: _i11.Future<int>.value(0),
       ) as _i11.Future<int>);
   @override
-  _i11.Future<List<dynamic>> getUsedCoinSerials() => (super.noSuchMethod(
+  _i11.Future<List<String>> getUsedCoinSerials() => (super.noSuchMethod(
         Invocation.method(
           #getUsedCoinSerials,
           [],
         ),
-        returnValue: _i11.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i11.Future<List<dynamic>>);
+        returnValue: _i11.Future<List<String>>.value(<String>[]),
+      ) as _i11.Future<List<String>>);
   @override
   _i11.Future<void> exit() => (super.noSuchMethod(
         Invocation.method(
diff --git a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart
index 28500d8af..3e9fd4fde 100644
--- a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart
+++ b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart
@@ -487,7 +487,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i5.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
+  _i5.Future<List<String>> getUsedCoinSerials({
     required _i7.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -500,8 +500,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i5.Future<List<String>>.value(<String>[]),
+      ) as _i5.Future<List<String>>);
   @override
   _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/services/coins/particl/particl_wallet_test.mocks.dart b/test/services/coins/particl/particl_wallet_test.mocks.dart
index 43a1473ce..11a8de944 100644
--- a/test/services/coins/particl/particl_wallet_test.mocks.dart
+++ b/test/services/coins/particl/particl_wallet_test.mocks.dart
@@ -487,7 +487,7 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             _i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
       ) as _i5.Future<Map<String, dynamic>>);
   @override
-  _i5.Future<List<dynamic>> getUsedCoinSerials({
+  _i5.Future<List<String>> getUsedCoinSerials({
     required _i7.Coin? coin,
     int? startNumber = 0,
   }) =>
@@ -500,8 +500,8 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
             #startNumber: startNumber,
           },
         ),
-        returnValue: _i5.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i5.Future<List<dynamic>>);
+        returnValue: _i5.Future<List<String>>.value(<String>[]),
+      ) as _i5.Future<List<String>>);
   @override
   _i5.Future<void> clearSharedTransactionCache({required _i7.Coin? coin}) =>
       (super.noSuchMethod(
diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart
index e35ea6a6d..67081a304 100644
--- a/test/widget_tests/transaction_card_test.mocks.dart
+++ b/test/widget_tests/transaction_card_test.mocks.dart
@@ -1647,28 +1647,6 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
         returnValueForMissingStub: _i18.Future<void>.value(),
       ) as _i18.Future<void>);
   @override
-  _i18.Future<void> fillAddresses(
-    String? suppliedMnemonic,
-    String? mnemonicPassphrase, {
-    int? perBatch = 50,
-    int? numberOfThreads = 4,
-  }) =>
-      (super.noSuchMethod(
-        Invocation.method(
-          #fillAddresses,
-          [
-            suppliedMnemonic,
-            mnemonicPassphrase,
-          ],
-          {
-            #perBatch: perBatch,
-            #numberOfThreads: numberOfThreads,
-          },
-        ),
-        returnValue: _i18.Future<void>.value(),
-        returnValueForMissingStub: _i18.Future<void>.value(),
-      ) as _i18.Future<void>);
-  @override
   _i18.Future<void> fullRescan(
     int? maxUnusedAddressGap,
     int? maxNumberOfIndexesToCheck,
@@ -1717,6 +1695,16 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
         returnValue: _i18.Future<Map<int, dynamic>>.value(<int, dynamic>{}),
       ) as _i18.Future<Map<int, dynamic>>);
   @override
+  _i18.Future<void> getTransactionCacheEarly(List<String>? allAddresses) =>
+      (super.noSuchMethod(
+        Invocation.method(
+          #getTransactionCacheEarly,
+          [allAddresses],
+        ),
+        returnValue: _i18.Future<void>.value(),
+        returnValueForMissingStub: _i18.Future<void>.value(),
+      ) as _i18.Future<void>);
+  @override
   _i18.Future<List<Map<String, dynamic>>> fetchAnonymitySets() =>
       (super.noSuchMethod(
         Invocation.method(
@@ -1735,13 +1723,13 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
         returnValue: _i18.Future<int>.value(0),
       ) as _i18.Future<int>);
   @override
-  _i18.Future<List<dynamic>> getUsedCoinSerials() => (super.noSuchMethod(
+  _i18.Future<List<String>> getUsedCoinSerials() => (super.noSuchMethod(
         Invocation.method(
           #getUsedCoinSerials,
           [],
         ),
-        returnValue: _i18.Future<List<dynamic>>.value(<dynamic>[]),
-      ) as _i18.Future<List<dynamic>>);
+        returnValue: _i18.Future<List<String>>.value(<String>[]),
+      ) as _i18.Future<List<String>>);
   @override
   _i18.Future<void> exit() => (super.noSuchMethod(
         Invocation.method(