diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart
index c6eceea80..528c99f98 100644
--- a/lib/db/isar/main_db.dart
+++ b/lib/db/isar/main_db.dart
@@ -592,7 +592,8 @@ class MainDB {
       });
       return ids;
     } catch (e) {
-      throw MainDBException("failed updateOrPutAddresses: $transactions", e);
+      throw MainDBException(
+          "failed updateOrPutTransactionV2s: $transactions", e);
     }
   }
 
diff --git a/lib/main.dart b/lib/main.dart
index 478315623..1d06bbce5 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -317,13 +317,6 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
       _desktopHasPassword =
           await ref.read(storageCryptoHandlerProvider).hasPassword();
     }
-
-    ref
-        .read(priceAnd24hChangeNotifierProvider)
-        .tokenContractAddressesToCheck
-        .addAll(
-          await MainDB.instance.getEthContracts().addressProperty().findAll(),
-        );
   }
 
   Future<void> load() async {
diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart
index 4a5dcae28..82ca119a4 100644
--- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart
+++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart
@@ -23,6 +23,7 @@ import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/ad
 import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_text.dart';
 import 'package:stackwallet/pages/home_view/home_view.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
+import 'package:stackwallet/providers/global/price_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/themes/stack_colors.dart';
 import 'package:stackwallet/utilities/assets.dart';
@@ -151,6 +152,7 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
 
     if (contract != null) {
       await MainDB.instance.putEthContract(contract);
+      unawaited(ref.read(priceAnd24hChangeNotifierProvider).updatePrice());
       if (mounted) {
         setState(() {
           if (tokenEntities
@@ -175,7 +177,8 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
 
     if (contracts.isEmpty) {
       contracts.addAll(DefaultTokens.list);
-      MainDB.instance.putEthContracts(contracts);
+      MainDB.instance.putEthContracts(contracts).then(
+          (_) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice());
     }
 
     tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e)));
diff --git a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart
index c817b5899..32e1b618c 100644
--- a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart
+++ b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart
@@ -8,6 +8,7 @@
  *
  */
 
+import 'dart:async';
 import 'dart:io';
 
 import 'package:flutter/material.dart';
@@ -107,6 +108,7 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
 
     if (contract != null) {
       await MainDB.instance.putEthContract(contract);
+      unawaited(ref.read(priceAnd24hChangeNotifierProvider).updatePrice());
       if (mounted) {
         setState(() {
           if (tokenEntities
@@ -143,7 +145,8 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
 
     if (contracts.isEmpty) {
       contracts.addAll(DefaultTokens.list);
-      MainDB.instance.putEthContracts(contracts);
+      MainDB.instance.putEthContracts(contracts).then(
+          (value) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice());
     }
 
     tokenEntities.addAll(contracts.map((e) => EthTokenEntity(e)));
diff --git a/lib/pages/pinpad_views/lock_screen_view.dart b/lib/pages/pinpad_views/lock_screen_view.dart
index f8b473d5c..e4ecb85a4 100644
--- a/lib/pages/pinpad_views/lock_screen_view.dart
+++ b/lib/pages/pinpad_views/lock_screen_view.dart
@@ -27,6 +27,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
 import 'package:stackwallet/utilities/show_loading.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
 import 'package:stackwallet/widgets/background.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
@@ -98,14 +99,20 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
         final walletId = widget.routeOnSuccessArguments as String;
 
         final wallet = ref.read(pWallets).getWallet(walletId);
-        if (wallet.info.coin == Coin.monero) {
-          await showLoading(
-            opaqueBG: true,
-            whileFuture: wallet.init(),
-            context: context,
-            message: "Loading ${wallet.info.coin.prettyName} wallet...",
-          );
+        final Future<void> loadFuture;
+        if (wallet is CwBasedInterface) {
+          loadFuture =
+              wallet.init().then((value) async => await (wallet).open());
+        } else {
+          loadFuture = wallet.init();
         }
+
+        await showLoading(
+          opaqueBG: true,
+          whileFuture: loadFuture,
+          context: context,
+          message: "Loading ${wallet.info.coin.prettyName} wallet...",
+        );
       }
 
       if (mounted) {
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
index 275defc05..301830004 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
@@ -42,7 +42,9 @@ import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/prefs.dart';
 import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
+import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
 import 'package:stackwallet/wallets/wallet/wallet.dart';
+import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
 import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
 import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
 import 'package:tuple/tuple.dart';
@@ -368,7 +370,7 @@ abstract class SWB {
     return backupJson;
   }
 
-  static Future<bool> asyncRestore(
+  static Future<bool> _asyncRestore(
     Tuple2<dynamic, WalletInfo> tuple,
     Prefs prefs,
     NodeService nodeService,
@@ -422,6 +424,12 @@ abstract class SWB {
         restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0;
       }
 
+      Future<void>? restoringFuture;
+
+      if (!(wallet is CwBasedInterface || wallet is EpiccashWallet)) {
+        restoringFuture = wallet.recover(isRescan: false);
+      }
+
       uiState?.update(
         walletId: info.walletId,
         restoringStatus: StackRestoringStatus.restoring,
@@ -466,6 +474,8 @@ abstract class SWB {
         return false;
       }
 
+      await restoringFuture;
+
       Logging.instance.log(
           "SWB restored: ${info.walletId} ${info.name} ${info.coin.prettyName}",
           level: LogLevel.Info);
@@ -690,13 +700,34 @@ abstract class SWB {
       // TODO: use these for monero and possibly other coins later on?
       // final List<String> txidList = List<String>.from(walletbackup['txidList'] as List? ?? []);
 
+      Map<String, dynamic>? otherData;
+      try {
+        if (walletbackup["otherDataJsonString"] is String) {
+          final data =
+              jsonDecode(walletbackup["otherDataJsonString"] as String);
+          otherData = Map<String, dynamic>.from(data as Map);
+        }
+      } catch (e, s) {
+        Logging.instance.log(
+          "SWB restore walletinfo otherdata error: $e\n$s",
+          level: LogLevel.Error,
+        );
+      }
+
+      if (coin == Coin.firo) {
+        otherData ??= {};
+        // swb will do a restore so this flag should be set to false so another
+        // rescan/restore isn't done when opening the wallet
+        otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = false;
+      }
+
       final info = WalletInfo(
         coinName: coin.name,
         walletId: walletId,
         name: walletName,
         mainAddressType: coin.primaryAddressType,
         restoreHeight: walletbackup['restoreHeight'] as int? ?? 0,
-        otherDataJsonString: walletbackup["otherDataJsonString"] as String?,
+        otherDataJsonString: otherData == null ? null : jsonEncode(otherData),
         cachedChainHeight: walletbackup['storedChainHeight'] as int? ?? 0,
       );
 
@@ -757,7 +788,7 @@ abstract class SWB {
       )) {
         return false;
       }
-      final bools = await asyncRestore(
+      final bools = await _asyncRestore(
         tuple,
         _prefs,
         nodeService,
@@ -796,10 +827,10 @@ abstract class SWB {
     }
 
     Logging.instance.log("done with SWB restore", level: LogLevel.Warning);
-    if (Util.isDesktop) {
-      await Wallets.sharedInstance
-          .loadAfterStackRestore(_prefs, uiState?.wallets ?? []);
-    }
+
+    await Wallets.sharedInstance
+        .loadAfterStackRestore(_prefs, uiState?.wallets ?? [], Util.isDesktop);
+
     return true;
   }
 
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
index 3de77e609..147d3a6a6 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
@@ -216,9 +216,9 @@ class _StackRestoreProgressViewState
 
   void _addWalletsToHomeView() {
     ref.read(pWallets).loadAfterStackRestore(
-          ref.read(prefsChangeNotifierProvider),
-          ref.read(stackRestoringUIStateProvider).wallets,
-        );
+        ref.read(prefsChangeNotifierProvider),
+        ref.read(stackRestoringUIStateProvider).wallets,
+        Util.isDesktop);
   }
 
   @override
diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart
index 7130c0517..1401625c9 100644
--- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart
+++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart
@@ -104,7 +104,7 @@ class _TransactionCardStateV2 extends ConsumerState<TransactionCardV2> {
 
     final price = ref
         .watch(priceAnd24hChangeNotifierProvider.select((value) => isTokenTx
-            ? value.getTokenPrice(_transaction.otherData!)
+            ? value.getTokenPrice(tokenContract!.address)
             : value.getPrice(coin)))
         .item1;
 
diff --git a/lib/pages/wallets_view/sub_widgets/favorite_card.dart b/lib/pages/wallets_view/sub_widgets/favorite_card.dart
index e3b030fa3..4cbd10140 100644
--- a/lib/pages/wallets_view/sub_widgets/favorite_card.dart
+++ b/lib/pages/wallets_view/sub_widgets/favorite_card.dart
@@ -115,17 +115,21 @@ class _FavoriteCardState extends ConsumerState<FavoriteCard> {
       child: GestureDetector(
         onTap: () async {
           final wallet = ref.read(pWallets).getWallet(walletId);
-          await wallet.init();
+
+          final Future<void> loadFuture;
           if (wallet is CwBasedInterface) {
-            if (mounted) {
-              await showLoading(
-                whileFuture: wallet.open(),
-                context: context,
-                message: 'Opening ${wallet.info.name}',
-                isDesktop: Util.isDesktop,
-              );
-            }
+            loadFuture =
+                wallet.init().then((value) async => await (wallet).open());
+          } else {
+            loadFuture = wallet.init();
           }
+          await showLoading(
+            whileFuture: loadFuture,
+            context: context,
+            message: 'Opening ${wallet.info.name}',
+            isDesktop: Util.isDesktop,
+          );
+
           if (mounted) {
             if (Util.isDesktop) {
               await Navigator.of(context).pushNamed(
diff --git a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart
index 247694477..194b8df10 100644
--- a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart
+++ b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart
@@ -40,7 +40,7 @@ class WalletListItem extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    debugPrint("BUILD: $runtimeType");
+    // debugPrint("BUILD: $runtimeType");
     final walletCountString =
         walletCount == 1 ? "$walletCount wallet" : "$walletCount wallets";
     final currency = ref
@@ -63,17 +63,19 @@ class WalletListItem extends ConsumerWidget {
                 .read(pWallets)
                 .wallets
                 .firstWhere((e) => e.info.coin == coin);
-            await wallet.init();
+            final Future<void> loadFuture;
             if (wallet is CwBasedInterface) {
-              if (context.mounted) {
-                await showLoading(
-                  whileFuture: wallet.open(),
-                  context: context,
-                  message: 'Opening ${wallet.info.name}',
-                  isDesktop: Util.isDesktop,
-                );
-              }
+              loadFuture =
+                  wallet.init().then((value) async => await (wallet).open());
+            } else {
+              loadFuture = wallet.init();
             }
+            await showLoading(
+              whileFuture: loadFuture,
+              context: context,
+              message: 'Opening ${wallet.info.name}',
+              isDesktop: Util.isDesktop,
+            );
             if (context.mounted) {
               unawaited(
                 Navigator.of(context).pushNamed(
diff --git a/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart b/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart
index 89a9db785..7f138509f 100644
--- a/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart
+++ b/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart
@@ -80,17 +80,20 @@ class CoinWalletsTable extends ConsumerWidget {
 
                             final wallet =
                                 ref.read(pWallets).getWallet(walletIds[i]);
-                            await wallet.init();
+                            final Future<void> loadFuture;
                             if (wallet is CwBasedInterface) {
-                              if (context.mounted) {
-                                await showLoading(
-                                  whileFuture: wallet.open(),
-                                  context: context,
-                                  message: 'Opening ${wallet.info.name}',
-                                  isDesktop: Util.isDesktop,
-                                );
-                              }
+                              loadFuture = wallet
+                                  .init()
+                                  .then((value) async => await (wallet).open());
+                            } else {
+                              loadFuture = wallet.init();
                             }
+                            await showLoading(
+                              whileFuture: loadFuture,
+                              context: context,
+                              message: 'Opening ${wallet.info.name}',
+                              isDesktop: Util.isDesktop,
+                            );
 
                             if (context.mounted) {
                               await Navigator.of(context).pushNamed(
diff --git a/lib/services/price_service.dart b/lib/services/price_service.dart
index 8a0b2741a..561aa184c 100644
--- a/lib/services/price_service.dart
+++ b/lib/services/price_service.dart
@@ -12,7 +12,9 @@ import 'dart:async';
 
 import 'package:decimal/decimal.dart';
 import 'package:flutter/foundation.dart';
-import 'package:http/http.dart';
+import 'package:isar/isar.dart';
+import 'package:stackwallet/db/isar/main_db.dart';
+import 'package:stackwallet/models/isar/models/isar_models.dart';
 import 'package:stackwallet/networking/http.dart';
 import 'package:stackwallet/services/price.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
@@ -20,7 +22,9 @@ import 'package:tuple/tuple.dart';
 
 class PriceService extends ChangeNotifier {
   late final String baseTicker;
-  final Set<String> tokenContractAddressesToCheck = {};
+  Future<Set<String>> get tokenContractAddressesToCheck async =>
+      (await MainDB.instance.getEthContracts().addressProperty().findAll())
+          .toSet();
   final Duration updateInterval = const Duration(seconds: 60);
 
   Timer? _timer;
@@ -52,9 +56,11 @@ class PriceService extends ChangeNotifier {
       }
     }
 
-    if (tokenContractAddressesToCheck.isNotEmpty) {
+    final _tokenContractAddressesToCheck = await tokenContractAddressesToCheck;
+
+    if (_tokenContractAddressesToCheck.isNotEmpty) {
       final tokenPriceMap = await _priceAPI.getPricesAnd24hChangeForEthTokens(
-        contractAddresses: tokenContractAddressesToCheck,
+        contractAddresses: _tokenContractAddressesToCheck,
         baseCurrency: baseTicker,
       );
 
diff --git a/lib/services/wallets.dart b/lib/services/wallets.dart
index c1124b05f..b56a6b090 100644
--- a/lib/services/wallets.dart
+++ b/lib/services/wallets.dart
@@ -25,6 +25,7 @@ import 'package:stackwallet/utilities/prefs.dart';
 import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
 import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
 import 'package:stackwallet/wallets/wallet/wallet.dart';
+import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
 
 class Wallets {
   Wallets._private();
@@ -192,8 +193,7 @@ class Wallets {
           final shouldSetAutoSync = shouldAutoSyncAll ||
               walletIdsToEnableAutoSync.contains(walletInfo.walletId);
 
-          if (walletInfo.coin == Coin.monero ||
-              walletInfo.coin == Coin.wownero) {
+          if (wallet is CwBasedInterface) {
             // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
           } else {
             walletInitFutures.add(wallet.init().then((_) {
@@ -230,6 +230,7 @@ class Wallets {
   Future<void> loadAfterStackRestore(
     Prefs prefs,
     List<Wallet> wallets,
+    bool isDesktop,
   ) async {
     List<Future<void>> walletInitFutures = [];
     List<({Wallet wallet, bool shouldAutoSync})> walletsToInitLinearly = [];
@@ -259,15 +260,16 @@ class Wallets {
         final shouldSetAutoSync = shouldAutoSyncAll ||
             walletIdsToEnableAutoSync.contains(wallet.walletId);
 
-        if (wallet.info.coin == Coin.monero ||
-            wallet.info.coin == Coin.wownero) {
-          // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
-        } else {
-          walletInitFutures.add(wallet.init().then((value) {
-            if (shouldSetAutoSync) {
-              wallet.shouldAutoSync = true;
-            }
-          }));
+        if (isDesktop) {
+          if (wallet is CwBasedInterface) {
+            // walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
+          } else {
+            walletInitFutures.add(wallet.init().then((value) {
+              if (shouldSetAutoSync) {
+                wallet.shouldAutoSync = true;
+              }
+            }));
+          }
         }
 
         _wallets[wallet.walletId] = wallet;
@@ -278,15 +280,17 @@ class Wallets {
       }
     }
 
-    if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) {
-      await Future.wait([
-        _initLinearly(walletsToInitLinearly),
-        ...walletInitFutures,
-      ]);
-    } else if (walletInitFutures.isNotEmpty) {
-      await Future.wait(walletInitFutures);
-    } else if (walletsToInitLinearly.isNotEmpty) {
-      await _initLinearly(walletsToInitLinearly);
+    if (isDesktop) {
+      if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) {
+        await Future.wait([
+          _initLinearly(walletsToInitLinearly),
+          ...walletInitFutures,
+        ]);
+      } else if (walletInitFutures.isNotEmpty) {
+        await Future.wait(walletInitFutures);
+      } else if (walletsToInitLinearly.isNotEmpty) {
+        await _initLinearly(walletsToInitLinearly);
+      }
     }
   }
 
diff --git a/lib/wallets/wallet/impl/epiccash_wallet.dart b/lib/wallets/wallet/impl/epiccash_wallet.dart
index fba66845c..3ef3e1026 100644
--- a/lib/wallets/wallet/impl/epiccash_wallet.dart
+++ b/lib/wallets/wallet/impl/epiccash_wallet.dart
@@ -484,6 +484,11 @@ class EpiccashWallet extends Bip39Wallet {
   FilterOperation? get receivingAddressFilterOperation =>
       FilterGroup.and(standardReceivingAddressFilters);
 
+  @override
+  Future<void> checkSaveInitialReceivingAddress() async {
+     // epiccash seems ok with nothing here?
+  }
+
   @override
   Future<void> init({bool? isRestore}) async {
     if (isRestore != true) {
diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart
index fae9f040f..0037ff1d5 100644
--- a/lib/wallets/wallet/impl/ethereum_wallet.dart
+++ b/lib/wallets/wallet/impl/ethereum_wallet.dart
@@ -86,27 +86,11 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface {
     _credentials = web3.EthPrivateKey.fromHex(privateKey);
   }
 
-  Future<void> _generateAndSaveAddress(
-    String mnemonic,
-    String mnemonicPassphrase,
-  ) async {
-    await _initCredentials(mnemonic, mnemonicPassphrase);
-
-    final address = Address(
-      walletId: walletId,
-      value: _credentials.address.hexEip55,
-      publicKey: [], // maybe store address bytes here? seems a waste of space though
-      derivationIndex: 0,
-      derivationPath: DerivationPath()..value = "$hdPathEthereum/0",
-      type: AddressType.ethereum,
-      subType: AddressSubType.receiving,
-    );
-
-    await mainDB.updateOrPutAddresses([address]);
-  }
-
   // ==================== Overrides ============================================
 
+  @override
+  int get isarTransactionVersion => 2;
+
   @override
   FilterOperation? get transactionFilterOperation => FilterGroup.not(
         const FilterCondition.equalTo(
@@ -124,15 +108,27 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface {
       FilterGroup.and(standardReceivingAddressFilters);
 
   @override
-  Future<void> init({bool? isRestore}) async {
+  Future<void> checkSaveInitialReceivingAddress() async {
     final address = await getCurrentReceivingAddress();
     if (address == null) {
-      await _generateAndSaveAddress(
+      await _initCredentials(
         await getMnemonic(),
         await getMnemonicPassphrase(),
       );
+
+      final address = Address(
+        walletId: walletId,
+        value: _credentials.address.hexEip55,
+        publicKey: [],
+        // maybe store address bytes here? seems a waste of space though
+        derivationIndex: 0,
+        derivationPath: DerivationPath()..value = "$hdPathEthereum/0",
+        type: AddressType.ethereum,
+        subType: AddressSubType.receiving,
+      );
+
+      await mainDB.updateOrPutAddresses([address]);
     }
-    return super.init();
   }
 
   @override
@@ -266,6 +262,10 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface {
       for (final tuple in allTxs) {
         final element = tuple.item1;
 
+        if (element.hasToken && !element.isError) {
+          continue;
+        }
+
         //Calculate fees (GasLimit * gasPrice)
         // int txFee = element.gasPrice * element.gasUsed;
         final Amount txFee = element.gasCost;
@@ -468,17 +468,11 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface {
     await refreshMutex.protect(() async {
       if (isRescan) {
         await mainDB.deleteWalletBlockchainData(walletId);
-        await _generateAndSaveAddress(
-          await getMnemonic(),
-          await getMnemonicPassphrase(),
-        );
+        await checkSaveInitialReceivingAddress();
         await updateBalance();
         await updateTransactions(isRescan: true);
       } else {
-        await _generateAndSaveAddress(
-          await getMnemonic(),
-          await getMnemonicPassphrase(),
-        );
+        await checkSaveInitialReceivingAddress();
         unawaited(updateBalance());
         unawaited(updateTransactions());
       }
diff --git a/lib/wallets/wallet/impl/monero_wallet.dart b/lib/wallets/wallet/impl/monero_wallet.dart
index deba5a4b9..46b64403e 100644
--- a/lib/wallets/wallet/impl/monero_wallet.dart
+++ b/lib/wallets/wallet/impl/monero_wallet.dart
@@ -461,6 +461,7 @@ class MoneroWallet extends CryptonoteWallet with CwBasedInterface {
             output.sendAll = isSendAll;
             String amountToSend = recipient.amount.decimal.toString();
             output.setCryptoAmount(amountToSend);
+            outputs.add(output);
           }
 
           final tmp =
diff --git a/lib/wallets/wallet/impl/stellar_wallet.dart b/lib/wallets/wallet/impl/stellar_wallet.dart
index 06a2a638a..d078dd98e 100644
--- a/lib/wallets/wallet/impl/stellar_wallet.dart
+++ b/lib/wallets/wallet/impl/stellar_wallet.dart
@@ -111,7 +111,7 @@ class StellarWallet extends Bip39Wallet<Stellar> {
       FilterGroup.and(standardReceivingAddressFilters);
 
   @override
-  Future<void> init() async {
+  Future<void> checkSaveInitialReceivingAddress() async {
     try {
       final address = await getCurrentReceivingAddress();
       if (address == null) {
@@ -121,11 +121,10 @@ class StellarWallet extends Bip39Wallet<Stellar> {
     } catch (e, s) {
       // do nothing, still allow user into wallet
       Logging.instance.log(
-        "$runtimeType init() failed: $e\n$s",
+        "$runtimeType  checkSaveInitialReceivingAddress() failed: $e\n$s",
         level: LogLevel.Error,
       );
     }
-    return super.init();
   }
 
   @override
diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
index 573ef5608..8244c5fd9 100644
--- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
+++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart
@@ -527,4 +527,9 @@ class EthTokenWallet extends Wallet {
           value: TransactionSubType.ethToken,
         ),
       ]);
+
+  @override
+  Future<void> checkSaveInitialReceivingAddress() async {
+    await ethWallet.checkSaveInitialReceivingAddress();
+  }
 }
diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart
index fa48d70af..1bde36803 100644
--- a/lib/wallets/wallet/impl/tezos_wallet.dart
+++ b/lib/wallets/wallet/impl/tezos_wallet.dart
@@ -145,7 +145,7 @@ class TezosWallet extends Bip39Wallet<Tezos> {
   // ===========================================================================
 
   @override
-  Future<void> init() async {
+  Future<void> checkSaveInitialReceivingAddress() async {
     try {
       final _address = await getCurrentReceivingAddress();
       if (_address == null) {
@@ -155,12 +155,10 @@ class TezosWallet extends Bip39Wallet<Tezos> {
     } catch (e, s) {
       // do nothing, still allow user into wallet
       Logging.instance.log(
-        "$runtimeType init() failed: $e\n$s",
+        "$runtimeType  checkSaveInitialReceivingAddress() failed: $e\n$s",
         level: LogLevel.Error,
       );
     }
-
-    await super.init();
   }
 
   @override
diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart
index d94265e50..a0df9e2e2 100644
--- a/lib/wallets/wallet/impl/wownero_wallet.dart
+++ b/lib/wallets/wallet/impl/wownero_wallet.dart
@@ -506,6 +506,7 @@ class WowneroWallet extends CryptonoteWallet with CwBasedInterface {
             output.sendAll = isSendAll;
             String amountToSend = recipient.amount.decimal.toString();
             output.setCryptoAmount(amountToSend);
+            outputs.add(output);
           }
 
           final tmp =
diff --git a/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart b/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart
index 7bb795016..8d352811b 100644
--- a/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart
+++ b/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart
@@ -61,6 +61,20 @@ abstract class Bip39HDWallet<T extends Bip39HDCurrency> extends Bip39Wallet<T>
     await mainDB.updateOrPutAddresses([address]);
   }
 
+  @override
+  Future<void> checkSaveInitialReceivingAddress() async {
+    final current = await getCurrentChangeAddress();
+    if (current == null) {
+      final address = await _generateAddress(
+        chain: 0, // receiving
+        index: 0, // initial index
+        derivePathType: DerivePathTypeExt.primaryFor(info.coin),
+      );
+
+      await mainDB.updateOrPutAddresses([address]);
+    }
+  }
+
   // ========== Subclasses may override ========================================
 
   /// To be overridden by crypto currencies that do extra address conversions
diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart
index 1059b12cf..26f557dba 100644
--- a/lib/wallets/wallet/wallet.dart
+++ b/lib/wallets/wallet/wallet.dart
@@ -435,6 +435,8 @@ abstract class Wallet<T extends CryptoCurrency> {
 
   Future<bool> pingCheck();
 
+  Future<void> checkSaveInitialReceivingAddress();
+
   //===========================================
   /// add transaction to local db temporarily. Used for quickly updating ui
   /// before refresh can fetch data from server
@@ -600,6 +602,7 @@ abstract class Wallet<T extends CryptoCurrency> {
 
   @mustCallSuper
   Future<void> init() async {
+    await checkSaveInitialReceivingAddress();
     final address = await getCurrentReceivingAddress();
     if (address != null) {
       await info.updateReceivingAddress(
@@ -607,9 +610,6 @@ abstract class Wallet<T extends CryptoCurrency> {
         isar: mainDB.isar,
       );
     }
-
-    // TODO: make sure subclasses override this if they require some set up
-    // especially xmr/wow/epiccash
   }
 
   // ===========================================================================
diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart
index f6bfbdcf2..19faf7465 100644
--- a/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart
+++ b/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart
@@ -179,6 +179,11 @@ mixin CwBasedInterface<T extends CryptonoteCurrency> on CryptonoteWallet<T>
     }
   }
 
+  @override
+  Future<void> checkSaveInitialReceivingAddress() async {
+    // this doesn't work without opening the wallet first which takes a while
+  }
+
   // ============ Interface ====================================================
 
   Future<Amount> get availableBalance;
diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart
index 17a1b49de..4257c0f7c 100644
--- a/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart
+++ b/lib/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart
@@ -1,11 +1,9 @@
 import 'dart:async';
-import 'dart:convert';
 import 'dart:math';
 
 import 'package:bip47/src/util.dart';
 import 'package:bitcoindart/bitcoindart.dart' as bitcoindart;
 import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib;
-import 'package:decimal/decimal.dart';
 import 'package:isar/isar.dart';
 import 'package:stackwallet/electrumx_rpc/cached_electrumx_client.dart';
 import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
@@ -831,55 +829,6 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
     }
   }
 
-  Future<List<({Transaction transaction, Address address})>>
-      fetchTransactionsV1({
-    required List<Address> addresses,
-    required int currentChainHeight,
-  }) async {
-    final List<({String txHash, int height, String address})> allTxHashes =
-        (await fetchHistory(addresses.map((e) => e.value).toList()))
-            .map(
-              (e) => (
-                txHash: e["tx_hash"] as String,
-                height: e["height"] as int,
-                address: e["address"] as String,
-              ),
-            )
-            .toList();
-
-    List<Map<String, dynamic>> allTransactions = [];
-
-    for (final data in allTxHashes) {
-      final tx = await electrumXCachedClient.getTransaction(
-        txHash: data.txHash,
-        verbose: true,
-        coin: cryptoCurrency.coin,
-      );
-
-      // check for duplicates before adding to list
-      if (allTransactions
-              .indexWhere((e) => e["txid"] == tx["txid"] as String) ==
-          -1) {
-        tx["address"] = addresses.firstWhere((e) => e.value == data.address);
-        tx["height"] = data.height;
-        allTransactions.add(tx);
-      }
-    }
-
-    final List<({Transaction transaction, Address address})> txnsData = [];
-
-    for (final txObject in allTransactions) {
-      final data = await _parseTransactionV1(
-        txObject,
-        addresses,
-      );
-
-      txnsData.add(data);
-    }
-
-    return txnsData;
-  }
-
   Future<ElectrumXNode> getCurrentElectrumXNode() async {
     final node = getCurrentNode();
 
@@ -1185,257 +1134,6 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
     return utxo;
   }
 
-  Future<({Transaction transaction, Address address})> _parseTransactionV1(
-    Map<String, dynamic> txData,
-    List<Address> myAddresses,
-  ) async {
-    Set<String> receivingAddresses = myAddresses
-        .where((e) =>
-            e.subType == AddressSubType.receiving ||
-            e.subType == AddressSubType.paynymReceive ||
-            e.subType == AddressSubType.paynymNotification)
-        .map((e) => e.value)
-        .toSet();
-    Set<String> changeAddresses = myAddresses
-        .where((e) => e.subType == AddressSubType.change)
-        .map((e) => e.value)
-        .toSet();
-
-    Set<String> inputAddresses = {};
-    Set<String> outputAddresses = {};
-
-    Amount totalInputValue = Amount(
-      rawValue: BigInt.zero,
-      fractionDigits: cryptoCurrency.coin.decimals,
-    );
-    Amount totalOutputValue = Amount(
-      rawValue: BigInt.zero,
-      fractionDigits: cryptoCurrency.coin.decimals,
-    );
-
-    Amount amountSentFromWallet = Amount(
-      rawValue: BigInt.zero,
-      fractionDigits: cryptoCurrency.coin.decimals,
-    );
-    Amount amountReceivedInWallet = Amount(
-      rawValue: BigInt.zero,
-      fractionDigits: cryptoCurrency.coin.decimals,
-    );
-    Amount changeAmount = Amount(
-      rawValue: BigInt.zero,
-      fractionDigits: cryptoCurrency.coin.decimals,
-    );
-
-    // parse inputs
-    for (final input in txData["vin"] as List) {
-      final prevTxid = input["txid"] as String;
-      final prevOut = input["vout"] as int;
-
-      // fetch input tx to get address
-      final inputTx = await electrumXCachedClient.getTransaction(
-        txHash: prevTxid,
-        coin: cryptoCurrency.coin,
-      );
-
-      for (final output in inputTx["vout"] as List) {
-        // check matching output
-        if (prevOut == output["n"]) {
-          // get value
-          final value = Amount.fromDecimal(
-            Decimal.parse(output["value"].toString()),
-            fractionDigits: cryptoCurrency.coin.decimals,
-          );
-
-          // add value to total
-          totalInputValue += value;
-
-          // get input(prevOut) address
-          final address = output["scriptPubKey"]?["addresses"]?[0] as String? ??
-              output["scriptPubKey"]?["address"] as String?;
-
-          if (address != null) {
-            inputAddresses.add(address);
-
-            // if input was from my wallet, add value to amount sent
-            if (receivingAddresses.contains(address) ||
-                changeAddresses.contains(address)) {
-              amountSentFromWallet += value;
-            }
-          }
-        }
-      }
-    }
-
-    // parse outputs
-    for (final output in txData["vout"] as List) {
-      // get value
-      final value = Amount.fromDecimal(
-        Decimal.parse(output["value"].toString()),
-        fractionDigits: cryptoCurrency.coin.decimals,
-      );
-
-      // add value to total
-      totalOutputValue += value;
-
-      // get output address
-      final address = output["scriptPubKey"]?["addresses"]?[0] as String? ??
-          output["scriptPubKey"]?["address"] as String?;
-      if (address != null) {
-        outputAddresses.add(address);
-
-        // if output was to my wallet, add value to amount received
-        if (receivingAddresses.contains(address)) {
-          amountReceivedInWallet += value;
-        } else if (changeAddresses.contains(address)) {
-          changeAmount += value;
-        }
-      }
-    }
-
-    final mySentFromAddresses = [
-      ...receivingAddresses.intersection(inputAddresses),
-      ...changeAddresses.intersection(inputAddresses)
-    ];
-    final myReceivedOnAddresses =
-        receivingAddresses.intersection(outputAddresses);
-    final myChangeReceivedOnAddresses =
-        changeAddresses.intersection(outputAddresses);
-
-    final fee = totalInputValue - totalOutputValue;
-
-    // this is the address initially used to fetch the txid
-    Address transactionAddress = txData["address"] as Address;
-
-    TransactionType type;
-    Amount amount;
-    if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) {
-      // tx is sent to self
-      type = TransactionType.sentToSelf;
-
-      // should be 0
-      amount =
-          amountSentFromWallet - amountReceivedInWallet - fee - changeAmount;
-    } else if (mySentFromAddresses.isNotEmpty) {
-      // outgoing tx
-      type = TransactionType.outgoing;
-      amount = amountSentFromWallet - changeAmount - fee;
-
-      // non wallet addresses found in tx outputs
-      final nonWalletOutAddresses = outputAddresses.difference(
-        myChangeReceivedOnAddresses,
-      );
-
-      if (nonWalletOutAddresses.isNotEmpty) {
-        final possible = nonWalletOutAddresses.first;
-
-        if (transactionAddress.value != possible) {
-          transactionAddress = Address(
-            walletId: myAddresses.first.walletId,
-            value: possible,
-            derivationIndex: -1,
-            derivationPath: null,
-            subType: AddressSubType.nonWallet,
-            type: AddressType.nonWallet,
-            publicKey: [],
-          );
-        }
-      } else {
-        // some other type of tx where the receiving address is
-        // one of my change addresses
-
-        type = TransactionType.sentToSelf;
-        amount = changeAmount;
-      }
-    } else {
-      // incoming tx
-      type = TransactionType.incoming;
-      amount = amountReceivedInWallet;
-    }
-
-    List<Output> outs = [];
-    List<Input> ins = [];
-
-    for (final json in txData["vin"] as List) {
-      bool isCoinBase = json['coinbase'] != null;
-      String? witness;
-      if (json['witness'] != null && json['witness'] is String) {
-        witness = json['witness'] as String;
-      } else if (json['txinwitness'] != null) {
-        if (json['txinwitness'] is List) {
-          witness = jsonEncode(json['txinwitness']);
-        }
-      }
-      final input = Input(
-        txid: json['txid'] as String,
-        vout: json['vout'] as int? ?? -1,
-        scriptSig: json['scriptSig']?['hex'] as String?,
-        scriptSigAsm: json['scriptSig']?['asm'] as String?,
-        isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?,
-        sequence: json['sequence'] as int?,
-        innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?,
-        witness: witness,
-      );
-      ins.add(input);
-    }
-
-    for (final json in txData["vout"] as List) {
-      final output = Output(
-        scriptPubKey: json['scriptPubKey']?['hex'] as String?,
-        scriptPubKeyAsm: json['scriptPubKey']?['asm'] as String?,
-        scriptPubKeyType: json['scriptPubKey']?['type'] as String?,
-        scriptPubKeyAddress:
-            json["scriptPubKey"]?["addresses"]?[0] as String? ??
-                json['scriptPubKey']?['type'] as String? ??
-                "",
-        value: Amount.fromDecimal(
-          Decimal.parse(json["value"].toString()),
-          fractionDigits: cryptoCurrency.coin.decimals,
-        ).raw.toInt(),
-      );
-      outs.add(output);
-    }
-
-    TransactionSubType txSubType = TransactionSubType.none;
-    if (this is PaynymInterface && outs.length > 1 && ins.isNotEmpty) {
-      for (int i = 0; i < outs.length; i++) {
-        List<String>? scriptChunks = outs[i].scriptPubKeyAsm?.split(" ");
-        if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") {
-          final blindedPaymentCode = scriptChunks![1];
-          final bytes = blindedPaymentCode.fromHex;
-
-          // https://en.bitcoin.it/wiki/BIP_0047#Sending
-          if (bytes.length == 80 && bytes.first == 1) {
-            txSubType = TransactionSubType.bip47Notification;
-          }
-        }
-      }
-    }
-
-    final tx = Transaction(
-      walletId: myAddresses.first.walletId,
-      txid: txData["txid"] as String,
-      timestamp: txData["blocktime"] as int? ??
-          (DateTime.now().millisecondsSinceEpoch ~/ 1000),
-      type: type,
-      subType: txSubType,
-      // amount may overflow. Deprecated. Use amountString
-      amount: amount.raw.toInt(),
-      amountString: amount.toJsonString(),
-      fee: fee.raw.toInt(),
-      height: txData["height"] as int?,
-      isCancelled: false,
-      isLelantus: false,
-      slateId: null,
-      otherData: null,
-      nonce: null,
-      inputs: ins,
-      outputs: outs,
-      numberOfMessages: null,
-    );
-
-    return (transaction: tx, address: transactionAddress);
-  }
-
   //============================================================================
 
   @override
@@ -1993,12 +1691,15 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
     }
   }
 
+  @override
+  Future<void> checkSaveInitialReceivingAddress() async {}
+
   @override
   Future<void> init() async {
     try {
       final features = await electrumXClient
           .getServerFeatures()
-          .timeout(const Duration(seconds: 2));
+          .timeout(const Duration(seconds: 4));
 
       Logging.instance.log("features: $features", level: LogLevel.Info);
 
diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart
index b0cfd72b2..d655b3e97 100644
--- a/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart
+++ b/lib/wallets/wallet/wallet_mixin_interfaces/nano_interface.dart
@@ -315,22 +315,20 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
   }
 
   @override
-  Future<void> init() async {
+  Future<void> checkSaveInitialReceivingAddress() async {
     try {
       _cachedAddress = await getCurrentReceivingAddress();
       if (_cachedAddress == null) {
         _cachedAddress = await _getAddressFromMnemonic();
-        await mainDB.putAddress(_cachedAddress!);
+        await mainDB.updateOrPutAddresses([_cachedAddress!]);
       }
     } catch (e, s) {
       // do nothing, still allow user into wallet
       Logging.instance.log(
-        "$runtimeType init() failed: $e\n$s",
+        "$runtimeType  checkSaveInitialReceivingAddress() failed: $e\n$s",
         level: LogLevel.Error,
       );
     }
-
-    return super.init();
   }
 
   @override
diff --git a/lib/widgets/wallet_card.dart b/lib/widgets/wallet_card.dart
index 4225d7c39..bc1c80aa4 100644
--- a/lib/widgets/wallet_card.dart
+++ b/lib/widgets/wallet_card.dart
@@ -93,17 +93,20 @@ class SimpleWalletCard extends ConsumerWidget {
     final nav = Navigator.of(context);
 
     final wallet = ref.read(pWallets).getWallet(walletId);
-    await wallet.init();
 
     if (context.mounted) {
+      final Future<void> loadFuture;
       if (wallet is CwBasedInterface) {
-        await showLoading(
-          whileFuture: wallet.open(),
-          context: context,
-          message: 'Opening ${wallet.info.name}',
-          isDesktop: Util.isDesktop,
-        );
+        loadFuture = wallet.init().then((value) async => await (wallet).open());
+      } else {
+        loadFuture = wallet.init();
       }
+      await showLoading(
+        whileFuture: loadFuture,
+        context: context,
+        message: 'Opening ${wallet.info.name}',
+        isDesktop: Util.isDesktop,
+      );
       if (popPrevious) nav.pop();
 
       if (desktopNavigatorState != null) {