import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:decimal/decimal.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
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/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/price.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:tuple/tuple.dart';

import 'firo_wallet_test.mocks.dart';
import 'firo_wallet_test_parameters.dart';
import 'sample_data/get_anonymity_set_sample_data.dart';
import 'sample_data/get_used_serials_sample_data.dart';
import 'sample_data/get_utxos_sample_data.dart';
import 'sample_data/gethistory_samples.dart';
import 'sample_data/transaction_data_samples.dart';

@GenerateMocks(
    [ElectrumX, CachedElectrumX, PriceAPI, TransactionNotificationTracker])
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 txData = TransactionData.fromJson(dateTimeChunksJson);
      final Map setData = {};
      setData[1] = GetAnonymitySetSampleData.data;
      final usedSerials = GetUsedSerialsSampleData.serials["serials"] as List;

      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash8,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData8;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash9,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData9;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash7,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData7;
      });

      final message = await isolateRestore(
        TEST_MNEMONIC,
        Coin.firo,
        1,
        setData,
        usedSerials,
        firoNetwork,
      );
      final result = await staticProcessRestore(txData, message);

      expect(result, isA<Map<String, dynamic>>());
      expect(result["mintIndex"], 8);
      expect(result["jindex"], [2, 4, 6]);
      expect(
          result["_lelantus_coins"], isA<List<Map<dynamic, LelantusCoin>>>());
      expect(result["newTxMap"], isA<Map<String, Transaction>>());
    });

    test("isolateRestore throws", () async {
      final Map setData = {};
      final usedSerials = [];

      expect(
          () => isolateRestore(
                TEST_MNEMONIC,
                Coin.firo,
                1,
                setData,
                usedSerials,
                firoNetwork,
              ),
          throwsA(isA<Error>()));
    });

    test("isolateCreateJoinSplitTransaction not enough funds", () async {
      final result = await isolateCreateJoinSplitTransaction(
        100,
        "aNmsUtzPzQ3SKWNjEH48GacMQJXWN5Rotm",
        false,
        TEST_MNEMONIC,
        2,
        Decimal.ten,
        [],
        459185,
        Coin.firo,
        firoNetwork,
        [GetAnonymitySetSampleData.data],
        "en_US",
      );

      expect(result, 1);
    });

    // test("isolateCreateJoinSplitTransaction success", () async {
    //   final result = await isolateCreateJoinSplitTransaction(
    //     9000,
    //     "aNmsUtzPzQ3SKWNjEH48GacMQJXWN5Rotm",
    //     true,
    //     TEST_MNEMONIC,
    //     2,
    //     Decimal.ten,
    //     SampleLelantus.lelantusEntries,
    //     459185,
    //     Coin.firo,
    //     firoNetwork,
    //     [GetAnonymitySetSampleData.data],
    //     "en_US",
    //   );
    //
    //   expect(result, isA<Map<String, dynamic>>());
    // });

    test("isolateEstimateJoinSplitFee", () async {
      final result = await isolateEstimateJoinSplitFee(
        1000,
        false,
        SampleLelantus.lelantusEntries,
        Coin.firo,
      );

      expect(result, isA<LelantusFeeData>());
    });

    test("call getIsolate with missing args", () async {
      final receivePort = await getIsolate({
        "function": "estimateJoinSplit",
        "subtractFeeFromAmount": true,
      });
      expect(await receivePort.first, "Error");
    });

    test("call getIsolate with bad args", () async {
      final receivePort = await getIsolate({
        "function": "estimateJoinSplit",
        "spendAmount": "spendAmount",
        "subtractFeeFromAmount": true,
        "lelantusEntries": MockCachedElectrumX(),
      });
      expect(await receivePort.first, "Error");
    });
  });

  group("Other standalone functions in firo_wallet.dart", () {
    test("Firo main net parameters", () {
      expect(firoNetwork.messagePrefix, '\x18Zcoin Signed Message:\n');
      expect(firoNetwork.bech32, 'bc');
      expect(firoNetwork.bip32.private, 0x0488ade4);
      expect(firoNetwork.bip32.public, 0x0488b21e);
      expect(firoNetwork.pubKeyHash, 0x52);
      expect(firoNetwork.scriptHash, 0x07);
      expect(firoNetwork.wif, 0xd2);
    });

    test("Firo test net parameters", () {
      expect(firoTestNetwork.messagePrefix, '\x18Zcoin Signed Message:\n');
      expect(firoTestNetwork.bech32, 'bc');
      expect(firoTestNetwork.bip32.private, 0x04358394);
      expect(firoTestNetwork.bip32.public, 0x043587cf);
      expect(firoTestNetwork.pubKeyHash, 0x41);
      expect(firoTestNetwork.scriptHash, 0xb2);
      expect(firoTestNetwork.wif, 0xb9);
    });

    test("getBip32Node", () {
      final node = getBip32Node(0, 3, Bip32TestParams.mnemonic, firoNetwork);
      expect(node.index, 3);
      expect(node.chainCode.toList(), Bip32TestParams.chainCodeList);
      expect(node.depth, 5);
      expect(node.toBase58(), Bip32TestParams.base58);
      expect(node.publicKey.toList(), Bip32TestParams.publicKeyList);
      expect(node.privateKey!.toList(), Bip32TestParams.privateKeyList);
      expect(node.parentFingerprint, Bip32TestParams.parentFingerprint);
      expect(node.fingerprint.toList(), Bip32TestParams.fingerprintList);
    });

    // group("getJMintTransactions", () {
    //   test(
    //       "getJMintTransactions throws Error due to some invalid transactions passed to this function",
    //       () {
    //     final cachedClient = MockCachedElectrumX();
    //     final priceAPI = MockPriceAPI();
    //
    //     // mock price calls
    // when(priceAPI.getPricesAnd24hChange( baseCurrency: "USD"))
    //     .thenAnswer((_) async => {Coin.firo : Tuple2(Decimal.fromInt(10), 1.0)});
    //
    //     // 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);
    //
    //     final transactions = [
    //       SampleGetTransactionData.txHash0,
    //       SampleGetTransactionData.txHash1,
    //       SampleGetTransactionData.txHash2,
    //       SampleGetTransactionData.txHash3,
    //       SampleGetTransactionData.txHash4,
    //       SampleGetTransactionData.txHash5,
    //     ];
    //
    //     expect(
    //         () async => await getJMintTransactions(
    //               cachedClient,
    //               transactions,
    //               "USD",
    //               "Firo",
    //               false,
    //               Decimal.ten,
    //               "en_US",
    //             ),
    //         throwsA(isA<Error>()));
    //   });
    //
    //   test("getJMintTransactions success", () async {
    //     final cachedClient = MockCachedElectrumX();
    //     final priceAPI = MockPriceAPI();
    //
    //     // mock price calls
    // when(priceAPI.getPricesAnd24hChange( baseCurrency: "USD"))
    //     .thenAnswer((_) async => {Coin.firo : Tuple2(Decimal.fromInt(10), 1.0)});
    //
    //     // mock transaction calls
    //     when(cachedClient.getTransaction(
    //             txHash: SampleGetTransactionData.txHash0,
    //             coin: Coin.firo,
    //             ))
    //         .thenAnswer((_) async => SampleGetTransactionData.txData0);
    //
    //     when(cachedClient.getTransaction(
    //             txHash: SampleGetTransactionData.txHash2,
    //             coin: Coin.firo,
    //             ))
    //         .thenAnswer((_) async => SampleGetTransactionData.txData2);
    //
    //     when(cachedClient.getTransaction(
    //             txHash: SampleGetTransactionData.txHash4,
    //             coin: Coin.firo,
    //             ))
    //         .thenAnswer((_) async => SampleGetTransactionData.txData4);
    //
    //     when(cachedClient.getTransaction(
    //             txHash: SampleGetTransactionData.txHash6,
    //             coin: Coin.firo,
    //             ))
    //         .thenAnswer((_) async => SampleGetTransactionData.txData6);
    //
    //     final transactions = [
    //       SampleGetTransactionData.txHash0,
    //       SampleGetTransactionData.txHash2,
    //       SampleGetTransactionData.txHash4,
    //       SampleGetTransactionData.txHash6,
    //     ];
    //
    //     final result = await getJMintTransactions(
    //       cachedClient,
    //       transactions,
    //       "USD",
    //       "Firo",
    //       false,
    //       Decimal.ten,
    //       "en_US",
    //     );
    //
    //     expect(result, isA<List<Transaction>>());
    //     expect(result.length, 4);
    //   });
    // });
    //
    // test("getAnonymitySet", () async {
    //   final cachedClient = MockCachedElectrumX();
    //   when(cachedClient.getAnonymitySet(
    //           groupId: "1", coin: Coin.firo, ))
    //       .thenAnswer((_) async => {
    //             "blockHash":
    //                 "c8e0ee6b8f7c1c85973e2b09321dc8644483f19dd7677ab0f33f7ffb1c6a0ec1",
    //             "setHash":
    //                 "3d67502ae9e9d21d452dbbad1d961c6fcf594a3e44e9ca7b874f991a4c0e2f2d",
    //             "serializedCoins": [
    //               "388b82fdc27fd4a64c3290578d00b210bf9aa0bd9e4b08be1913bf95877bead00100",
    //               "a554e4b700c161adefbe7933c6e2784cc029a590d75c7ad35407323e7579e8680100",
    //               "162ec5f41380f590462514615fae016ff674e3e07513039d16f90161d88d83220000",
    //               "... ~50000 more strings ...",
    //               "6482f50f21b38246f3f9f074cbf61b00ad175b63a946467a85bd22fe1a89825b0100",
    //               "7a9e57560d4abc384a48bf850a12df94e83d33496bb456aad26e7317921845330000",
    //               "a7a8ddf79fdaf6846c0c19eb00ba7a95713a1a62df91761cb74b122606385fb80000"
    //             ]
    //           });
    //
    //   final result =
    //       await getAnonymitySet(cachedClient, "", "1", false, "Firo");
    //
    //   expect(result, isA<Map<String, dynamic>>());
    //   expect(result["blockHash"],
    //       "c8e0ee6b8f7c1c85973e2b09321dc8644483f19dd7677ab0f33f7ffb1c6a0ec1");
    //   expect(result["setHash"],
    //       "3d67502ae9e9d21d452dbbad1d961c6fcf594a3e44e9ca7b874f991a4c0e2f2d");
    //   expect(result["serializedCoins"], isA<List<String>>());
    // });

    test("getBlockHead", () async {
      final client = MockElectrumX();
      when(client.getBlockHeadTip()).thenAnswer(
          (_) async => {"height": 4359032, "hex": "... some block hex ..."});

      int result = await getBlockHead(client);
      expect(result, 4359032);
    });
  });

  group("validate firo addresses", () {
    test("check valid firo main net address", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"), true);
    });

    test("check invalid firo main net address", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("sDda3fsd4af"), false);
    });

    test("check valid firo test net address against main net", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("THqfkegzJjpF4PQFAWPhJWMWagwHecfqva"), false);
    });

    test("check valid firo test net address", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firoTestNet,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("THqfkegzJjpF4PQFAWPhJWMWagwHecfqva"), true);
    });

    test("check invalid firo test net address", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firoTestNet,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("sDda3fsd4af"), false);
    });

    test("check valid firo address against test net", () async {
      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firoTestNet,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.validateAddress("a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"), false);
    });
  });

  group("testNetworkConnection", () {
    test("attempted connection fails due to server error", () async {
      final client = MockElectrumX();
      when(client.ping()).thenAnswer((_) async => false);

      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firo,
        client: client,
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );
      final bool result = await firo.testNetworkConnection();

      expect(result, false);
    });

    test("attempted connection fails due to exception", () async {
      final client = MockElectrumX();
      when(client.ping()).thenThrow(Exception);

      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firo,
        client: client,
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );
      final bool result = await firo.testNetworkConnection();

      expect(result, false);
    });

    test("attempted connection test success", () async {
      final client = MockElectrumX();
      when(client.ping()).thenAnswer((_) async => true);

      final firo = FiroWallet(
        walletName: 'unit test',
        walletId: 'some id',
        coin: Coin.firoTestNet,
        client: client,
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );
      final bool result = await firo.testNetworkConnection();

      expect(result, true);
    });
  });

  group("FiroWallet service class functions that depend on shared storage", () {
    const testWalletId = "testWalletID";
    const testWalletName = "Test Wallet";
    bool hiveAdaptersRegistered = false;

    setUp(() async {
      await setUpTestHive();

      if (!hiveAdaptersRegistered) {
        hiveAdaptersRegistered = true;

        // Registering Transaction Model Adapters
        Hive.registerAdapter(TransactionDataAdapter());
        Hive.registerAdapter(TransactionChunkAdapter());
        Hive.registerAdapter(TransactionAdapter());
        Hive.registerAdapter(InputAdapter());
        Hive.registerAdapter(OutputAdapter());

        // Registering Utxo Model Adapters
        Hive.registerAdapter(UtxoDataAdapter());
        Hive.registerAdapter(UtxoObjectAdapter());
        Hive.registerAdapter(StatusAdapter());

        // Registering Lelantus Model Adapters
        Hive.registerAdapter(LelantusCoinAdapter());
      }

      final wallets = await Hive.openBox('wallets');
      await wallets.put('currentWalletName', testWalletName);
    });

    // test("initializeWallet no network", () async {
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => false);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet no net",
    //     client: client,coin: Coin.firo,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   expect(await firo.initializeNew(), false);
    // });

    // test("initializeWallet no network exception", () async {
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   when(client.ping()).thenThrow(Exception("Network connection failed"));
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: "${testWalletId}initializeWallet no net exception",
    //     client: client,
    //     coin: Coin.firo,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   expect(await firo.initializeWallet(), false);
    // });
    //
    // test("initializeWallet throws bad network on testnet", () async {
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   when(client.ping()).thenAnswer((_) async => true);
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_MAINNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet bad net testnet",
    //     coin: Coin.firoTestNet,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   expect(() => firo.initializeWallet(), throwsA(isA<Exception>()));
    // });
    //
    // test("initializeWallet throws bad network on mainnet", () async {
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   when(client.ping()).thenAnswer((_) async => true);
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_TESTNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet bad net mainnet",
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   expect(() => firo.initializeWallet(), throwsA(isA<Exception>()));
    // });
    //
    // test("initializeWallet new test net wallet", () async {
    //   TestWidgetsFlutterBinding.ensureInitialized();
    //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
    //       .setMockMethodCallHandler((methodCall) async => 'en_US');
    //
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //   when(priceAPI.getPrice(ticker: "tFIRO", baseCurrency: "USD"))
    //       .thenAnswer((_) async => Decimal.fromInt(-1));
    //
    //   when(client.ping()).thenAnswer((_) async => true);
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_TESTNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   final List<Map<String, dynamic>> emptyList = [];
    //
    //   when(client.getUTXOs(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //   when(client.getHistory(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet testnet",
    //     coin: Coin.firoTestNet,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   await firo.initializeWallet();
    //
    //   final wallet =
    //       await Hive.openBox(testWalletId + "initializeWallet testnet");
    //
    //   expect(await wallet.get("addressBookEntries"), {});
    //
    //   expect(await wallet.get("blocked_tx_hashes"), ["0xdefault"]);
    //
    //   final result = await wallet.get("changeAddresses");
    //   expect(result, isA<List<String>>());
    //   expect(result.length, 1);
    //
    //   expect(await wallet.get("changeIndex"), 0);
    //
    //   expect(await wallet.get("id"), testWalletId + "initializeWallet testnet");
    //
    //   expect(await wallet.get("jindex"), []);
    //
    //   expect(await wallet.get("mintIndex"), 0);
    //
    //
    //   final currentReceivingAddress = await firo.currentReceivingAddress;
    //   expect(currentReceivingAddress, isA<String>());
    //
    //   expect(await wallet.get("receivingIndex"), 0);
    // });
    //
    // test("initializeWallet an already existing test net wallet", () async {
    //   TestWidgetsFlutterBinding.ensureInitialized();
    //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
    //       .setMockMethodCallHandler((methodCall) async => 'en_US');
    //
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //   // when(priceAPI.getPrice(ticker: "tFIRO", baseCurrency: "USD"))
    //   //     .thenAnswer((_) async => Decimal.fromInt(-1));
    //
    //   when(client.ping()).thenAnswer((_) async => true);
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_TESTNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   final List<Map<String, dynamic>> emptyList = [];
    //
    //   when(client.getUTXOs(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //   when(client.getHistory(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet existing",
    //     coin: Coin.firoTestNet,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   // 1st call to create wallet
    //   await firo.initializeWallet();
    //
    //   final wallet =
    //       await Hive.openBox(testWalletId + "initializeWallet existing");
    //
    //   expect(await wallet.get("addressBookEntries"), {});
    //
    //   expect(await wallet.get("blocked_tx_hashes"), ["0xdefault"]);
    //
    //   final result = await wallet.get("changeAddresses");
    //   expect(result, isA<List<String>>());
    //   expect(result.length, 1);
    //
    //   expect(await wallet.get("changeIndex"), 0);
    //
    //   expect(
    //       await wallet.get("id"), testWalletId + "initializeWallet existing");
    //
    //   expect(await wallet.get("jindex"), []);
    //
    //   expect(await wallet.get("mintIndex"), 0);
    //
    //   expect(firo.fiatCurrency, "USD");
    //
    //   final currentReceivingAddress = await firo.currentReceivingAddress;
    //   expect(currentReceivingAddress, isA<String>());
    //
    //   expect(await wallet.get("receivingIndex"), 0);
    //
    //   // second call to test initialization of existing wallet;
    //   await firo.initializeWallet();
    //
    //   final wallet2 =
    //       await Hive.openBox(testWalletId + "initializeWallet existing");
    //
    //   expect(await wallet2.get("addressBookEntries"), {});
    //
    //   expect(await wallet2.get("blocked_tx_hashes"), ["0xdefault"]);
    //
    //   final result2 = await wallet2.get("changeAddresses");
    //   expect(result2, isA<List<String>>());
    //   expect(result2.length, 1);
    //
    //   expect(await wallet2.get("changeIndex"), 0);
    //
    //   expect(
    //       await wallet2.get("id"), testWalletId + "initializeWallet existing");
    //
    //   expect(await wallet2.get("jindex"), []);
    //
    //   expect(await wallet2.get("mintIndex"), 0);
    //
    //   expect(firo.fiatCurrency, "USD");
    //
    //   final cra = await wallet2.get("receivingAddresses");
    //   expect(cra, isA<List<String>>());
    //   expect(cra.length, 1);
    //
    //   expect(await wallet2.get("receivingIndex"), 0);
    // });
    //
    // test("initializeWallet new main net wallet", () async {
    //   TestWidgetsFlutterBinding.ensureInitialized();
    //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
    //       .setMockMethodCallHandler((methodCall) async => 'en_US');
    //
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //   // mock price calls
    //       when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
    //           (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});
    //
    //   when(client.ping()).thenAnswer((_) async => true);
    //
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_MAINNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   final List<Map<String, dynamic>> emptyList = [];
    //
    //   when(client.getUTXOs(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //   when(client.getHistory(scripthash: anyNamed("scripthash")))
    //       .thenAnswer((_) async => emptyList);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: testWalletId + "initializeWallet",
    //     coin: Coin.firo,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   expect(await firo.initializeWallet(), true);
    //
    //   final wallet = await Hive.openBox(testWalletId + "initializeWallet");
    //
    //   var result = await wallet.get("addressBookEntries");
    //   expect(result, {});
    //
    //   result = await wallet.get("blocked_tx_hashes");
    //   expect(result, ["0xdefault"]);
    //
    //   result = await wallet.get("changeAddresses");
    //   expect(result, isA<List<String>>());
    //   expect(result.length, 1);
    //
    //   result = await wallet.get("changeIndex");
    //   expect(result, 0);
    //
    //   result = await wallet.get("id");
    //   expect(result, testWalletId + "initializeWallet");
    //
    //   result = await wallet.get("jindex");
    //   expect(result, []);
    //
    //   result = await wallet.get("mintIndex");
    //   expect(result, 0);
    //
    //   result = await wallet.get("preferredFiatCurrency");
    //   expect(result, null);
    //
    //   result = await wallet.get("receivingAddresses");
    //   expect(result, isA<List<String>>());
    //   expect(result.length, 1);
    //
    //   result = await wallet.get("receivingIndex");
    //   expect(result, 0);
    // });

    // test("getAllTxsToWatch", () async {
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //   final tracker = MockTransactionNotificationTracker();
    //
    //   await Hive.openBox<dynamic>(DB.boxNamePrefs);
    //   await Prefs.instance.init();
    //
    //   when(tracker.wasNotifiedPending(
    //           "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e"))
    //       .thenAnswer((realInvocation) => false);
    //   when(tracker.wasNotifiedPending(
    //           "FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
    //       .thenAnswer((realInvocation) => false);
    //   when(tracker.wasNotifiedPending(
    //           "ac0322cfdd008fa2a79bec525468fd05cf51a5a4e2c2e9c15598b659ec71ac68"))
    //       .thenAnswer((realInvocation) => false);
    //   when(tracker.wasNotifiedPending(
    //           "395f382ed5a595e116d5226e3cb5b664388363b6c171118a26ca729bf314c9fc"))
    //       .thenAnswer((realInvocation) => false);
    //   when(tracker.wasNotifiedPending(
    //           "ea77e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
    //       .thenAnswer((realInvocation) => false);
    //   when(tracker.wasNotifiedPending(
    //           "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
    //       .thenAnswer((realInvocation) => true);
    //   when(tracker.wasNotifiedPending(
    //           "e8e4bfc080bd6133d38263d2ac7ef6f60dfd73eb29b464e34766ebb5a0d27dd8"))
    //       .thenAnswer((realInvocation) => true);
    //   when(tracker.wasNotifiedConfirmed(
    //           "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
    //       .thenAnswer((realInvocation) => true);
    //   when(tracker.wasNotifiedConfirmed(
    //           "e8e4bfc080bd6133d38263d2ac7ef6f60dfd73eb29b464e34766ebb5a0d27dd8"))
    //       .thenAnswer((realInvocation) => true);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: "${testWalletId}getAllTxsToWatch",
    //     coin: Coin.firo,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: tracker,
    //   );
    //
    //TODO: mock NotificationAPI
    //   await firo.getAllTxsToWatch(txData, lTxData);
    //
    //
    //   // expect(firo.unconfirmedTxs, {
    //   //   "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e",
    //   //   'FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35',
    //   //   "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"
    //   // });
    // });

    group("refreshIfThereIsNewData", () {
      test("refreshIfThereIsNewData with no unconfirmed transactions",
          () async {
        TestWidgetsFlutterBinding.ensureInitialized();
        const MethodChannel('uk.spiralarm.flutter/devicelocale')
            .setMockMethodCallHandler((methodCall) async => 'en_US');

        final client = MockElectrumX();
        final cachedClient = MockCachedElectrumX();
        final secureStore = FakeSecureStorage();
        final priceAPI = MockPriceAPI();
        final tracker = MockTransactionNotificationTracker();

        // mock price calls
        when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
            (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

        when(tracker.pendings).thenAnswer((realInvocation) => [
              "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e",
              "FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35",
              "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"
            ]);
        when(tracker.wasNotifiedPending(
                "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e"))
            .thenAnswer((realInvocation) => true);
        when(tracker.wasNotifiedPending(
                "FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
            .thenAnswer((realInvocation) => true);
        when(tracker.wasNotifiedPending(
                "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
            .thenAnswer((realInvocation) => true);

        when(tracker.wasNotifiedConfirmed(
                "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e"))
            .thenAnswer((realInvocation) => true);
        when(tracker.wasNotifiedConfirmed(
                "FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
            .thenAnswer((realInvocation) => true);
        when(tracker.wasNotifiedConfirmed(
                "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
            .thenAnswer((realInvocation) => true);

        when(client.getBatchHistory(args: batchHistoryRequest0))
            .thenAnswer((realInvocation) async => batchHistoryResponse0);

        // 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);

        final firo = FiroWallet(
          walletName: testWalletName,
          walletId: "${testWalletId}refreshIfThereIsNewData",
          coin: Coin.firo,
          client: client,
          cachedClient: cachedClient,
          secureStore: secureStore,
          priceAPI: priceAPI,
          tracker: tracker,
        );

        // firo.unconfirmedTxs = {};

        final wallet =
            await Hive.openBox(testWalletId + "refreshIfThereIsNewData");
        await wallet.put('receivingAddresses', [
          "a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg",
          "aPjLWDTPQsoPHUTxKBNRzoebDALj3eTcfh",
          "aKmXfS7nEZdqWBGRdAXcyMoEoKhZQDPBoq",
        ]);

        await wallet.put('changeAddresses', [
          "a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w",
        ]);

        final result = await firo.refreshIfThereIsNewData();
        expect(result, false);
      });

      //   TODO: mock NotificationAPI
      //   test("refreshIfThereIsNewData with two unconfirmed transactions",
      //       () async {
      //     final client = MockElectrumX();
      //     final cachedClient = MockCachedElectrumX();
      //     final secureStore = FakeSecureStorage();
      //     final priceAPI = MockPriceAPI();
      //     final tracker = MockTransactionNotificationTracker();
      //
      //     when(client.getTransaction(txHash: SampleGetTransactionData.txHash6))
      //         .thenAnswer((_) async => SampleGetTransactionData.txData6);
      //
      //     when(client.getTransaction(
      //             txHash:
      //                 "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
      //         .thenAnswer((_) async => SampleGetTransactionData.txData7);
      //
      //     when(tracker.wasNotifiedPending(
      //             "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e"))
      //         .thenAnswer((realInvocation) => true);
      //     when(tracker.wasNotifiedPending(
      //             "FF7e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
      //         .thenAnswer((realInvocation) => false);
      //     when(tracker.wasNotifiedPending(
      //             "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218"))
      //         .thenAnswer((realInvocation) => false);
      //     when(tracker.wasNotifiedPending(
      //             "e8e4bfc080bd6133d38263d2ac7ef6f60dfd73eb29b464e34766ebb5a0d27dd8"))
      //         .thenAnswer((realInvocation) => false);
      //     when(tracker.wasNotifiedPending(
      //             "ac0322cfdd008fa2a79bec525468fd05cf51a5a4e2c2e9c15598b659ec71ac68"))
      //         .thenAnswer((realInvocation) => false);
      //     when(tracker.wasNotifiedPending(
      //             "ea77e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35"))
      //         .thenAnswer((realInvocation) => false);
      //     when(tracker.wasNotifiedPending(
      //             "395f382ed5a595e116d5226e3cb5b664388363b6c171118a26ca729bf314c9fc"))
      //         .thenAnswer((realInvocation) => false);
      //
      //     final firo = FiroWallet(
      //       walletName: testWalletName,
      //       walletId: testWalletId + "refreshIfThereIsNewData",
      //       coin: Coin.firo,
      //       client: client,
      //       cachedClient: cachedClient,
      //       secureStore: secureStore,
      //       priceAPI: priceAPI,
      //       tracker: tracker,
      //     );
      //
      //     await firo.getAllTxsToWatch(txData, lTxData);
      //
      //     final result = await firo.refreshIfThereIsNewData();
      //
      //     expect(result, true);
      //   });
    });

    test("submitHexToNetwork", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      when(client.broadcastTransaction(
              rawTx:
                  "0200000001ddba3ce3a3ab07d342183fa6743d3b620149c1db26efa239323384d82f9e2859010000006a47304402207d4982586eb4b0de17ee88f8eae4aaf7bc68590ae048e67e75932fe84a73f7f3022011392592558fb39d8c132234ad34a2c7f5071d2dab58d8c9220d343078413497012102f123ab9dbd627ab572de7cd77eda6e3781213a2ef4ab5e0d6e87f1c0d944b2caffffffff01e42e000000000000a5c5bc76bae786dc3a7d939757c34e15994d403bdaf418f9c9fa6eb90ac6e8ffc3550100772ad894f285988789669acd69ba695b9485c90141d7833209d05bcdad1b898b0000f5cba1a513dd97d81f89159f2be6eb012e987335fffa052c1fbef99550ba488fb6263232e7a0430c0a3ca8c728a5d8c8f2f985c8b586024a0f488c73130bd5ec9e7c23571f23c2d34da444ecc2fb65a12cee2ad3b8d3fcc337a2c2a45647eb43cff50600"))
          .thenAnswer((_) async =>
              "b36161c6e619395b3d40a851c45c1fef7a5c541eed911b5524a66c5703a689c9");

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}submitHexToNetwork",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      final txid = await firo.submitHexToNetwork(
          "0200000001ddba3ce3a3ab07d342183fa6743d3b620149c1db26efa239323384d82f9e2859010000006a47304402207d4982586eb4b0de17ee88f8eae4aaf7bc68590ae048e67e75932fe84a73f7f3022011392592558fb39d8c132234ad34a2c7f5071d2dab58d8c9220d343078413497012102f123ab9dbd627ab572de7cd77eda6e3781213a2ef4ab5e0d6e87f1c0d944b2caffffffff01e42e000000000000a5c5bc76bae786dc3a7d939757c34e15994d403bdaf418f9c9fa6eb90ac6e8ffc3550100772ad894f285988789669acd69ba695b9485c90141d7833209d05bcdad1b898b0000f5cba1a513dd97d81f89159f2be6eb012e987335fffa052c1fbef99550ba488fb6263232e7a0430c0a3ca8c728a5d8c8f2f985c8b586024a0f488c73130bd5ec9e7c23571f23c2d34da444ecc2fb65a12cee2ad3b8d3fcc337a2c2a45647eb43cff50600");

      expect(txid,
          "b36161c6e619395b3d40a851c45c1fef7a5c541eed911b5524a66c5703a689c9");
    });

    test("fillAddresses", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}fillAddresses",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        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();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      List<UtxoObject> utxos = [
        UtxoObject(
          txid: BuildMintTxTestParams.utxoInfo["txid"] as String,
          vout: BuildMintTxTestParams.utxoInfo["vout"] as int,
          value: BuildMintTxTestParams.utxoInfo["value"] as int,
          txName: '',
          status: Status(
              confirmed: false,
              blockHash: "",
              blockHeight: -1,
              blockTime: 42,
              confirmations: 0),
          isCoinbase: false,
          blocked: false,
          fiatWorth: '',
        )
      ];
      const sats = 9658;
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();

      await secureStore.write(
          key: "${testWalletId}buildMintTransaction_mnemonic",
          value: BuildMintTxTestParams.mnemonic);

      when(cachedClient.getTransaction(
        txHash: BuildMintTxTestParams.utxoInfo["txid"] as String,
        coin: Coin.firo,
      )).thenAnswer((_) async => BuildMintTxTestParams.cachedClientResponse);

      when(client.getBlockHeadTip()).thenAnswer(
          (_) async => {"height": 455873, "hex": "this value not used here"});

      final priceAPI = MockPriceAPI();
      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}buildMintTransaction",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox("${testWalletId}buildMintTransaction");

      await wallet.put("mintIndex", 0);

      await secureStore.write(
          key: "${testWalletId}buildMintTransaction_receiveDerivations",
          value: jsonEncode(BuildMintTxTestParams.receiveDerivations));
      await secureStore.write(
          key: "${testWalletId}buildMintTransaction_changeDerivations",
          value: jsonEncode(BuildMintTxTestParams.changeDerivations));

      List<Map<String, dynamic>> mintsWithoutFee =
          await firo.createMintsFromAmount(sats);

      final result =
          await firo.buildMintTransaction(utxos, sats, mintsWithoutFee);

      expect(result["txHex"], isA<String>());
    });

    test("recoverFromMnemonic succeeds", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_MAINNET,
            "hash_function": "sha256",
            "services": []
          });

      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      when(cachedClient.getUsedCoinSerials(
        coin: Coin.firo,
      )).thenAnswer(
          (_) async => GetUsedSerialsSampleData.serials["serials"] as List);

      when(cachedClient.getAnonymitySet(
        groupId: "1",
        coin: Coin.firo,
      )).thenAnswer(
        (_) async => GetAnonymitySetSampleData.data,
      );

      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash0,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData0;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash1,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData1;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash2,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData2;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash3,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData3;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash4,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData4;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash5,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData5;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash6,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData6;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash8,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData8;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash9,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData9;
      });
      when(cachedClient.getTransaction(
        txHash: SampleGetTransactionData.txHash7,
        coin: Coin.firo,
      )).thenAnswer((_) async {
        return SampleGetTransactionData.txData7;
      });

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}recoverFromMnemonic",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      // pre grab derivations in order to set up mock calls needed later on
      await firo.fillAddresses(TEST_MNEMONIC);
      final wallet =
          await Hive.openBox<dynamic>("${testWalletId}recoverFromMnemonic");

      final rcv = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_receiveDerivations");
      final chg = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_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);
      }

      when(client.getBatchHistory(args: {
        "0": [SampleGetHistoryData.scripthash0],
        "1": [SampleGetHistoryData.scripthash3]
      })).thenAnswer((realInvocation) async => {
            "0": SampleGetHistoryData.data0,
            "1": SampleGetHistoryData.data3,
          });

      await firo.recoverFromMnemonic(
          mnemonic: TEST_MNEMONIC,
          maxUnusedAddressGap: 20,
          height: 0,
          maxNumberOfIndexesToCheck: 1000);

      final receivingAddresses = await wallet.get('receivingAddresses');
      expect(receivingAddresses, ["a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"]);

      final changeAddresses = await wallet.get('changeAddresses');
      expect(changeAddresses, ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);

      final receivingIndex = await wallet.get('receivingIndex');
      expect(receivingIndex, 0);

      final changeIndex = await wallet.get('changeIndex');
      expect(changeIndex, 0);

      final _rcv = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_receiveDerivations");
      final _chg = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_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.length, 190);
      // expect(_changeDerivations.length, 190);
      expect(_receiveDerivations.length, 80);
      expect(_changeDerivations.length, 80);

      final mintIndex = await wallet.get('mintIndex');
      expect(mintIndex, 8);

      final lelantusCoins = await wallet.get('_lelantus_coins') as List;
      expect(lelantusCoins.length, 7);
      final lcoin = lelantusCoins
          .firstWhere((element) =>
              (Map<String, LelantusCoin>.from(element as Map))
                  .values
                  .first
                  .txId ==
              "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232")
          .values
          .first as LelantusCoin;
      expect(lcoin.index, 1);
      expect(lcoin.value, 9658);
      expect(lcoin.publicCoin,
          "7fd927efbea0a9e4ba299209aaee610c63359857596be0a2da276011a0baa84a0000");
      expect(lcoin.txId,
          "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232");
      expect(lcoin.anonymitySetId, 1);
      expect(lcoin.isUsed, true);

      final jIndex = await wallet.get('jindex');
      expect(jIndex, [2, 4, 6]);

      final lelantusTxModel = await wallet.get('latest_lelantus_tx_model');
      expect(lelantusTxModel.getAllTransactions().length, 5);
    }, timeout: const Timeout(Duration(minutes: 5)));

    test("fullRescan succeeds", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      await secureStore.write(
          key: '${testWalletId}fullRescan_mnemonic', value: TEST_MNEMONIC);

      // mock electrumx client calls
      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      // when(client.getCoinsForRecovery(setId: 1))
      //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
      when(client.getUsedCoinSerials(startNumber: 0))
          .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(cachedClient.getAnonymitySet(
              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);

      when(cachedClient.clearSharedTransactionCache(coin: Coin.firo))
          .thenAnswer((_) async => {});

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}fullRescan",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      // pre grab derivations in order to set up mock calls needed later on
      await firo.fillAddresses(TEST_MNEMONIC);
      final wallet = await Hive.openBox(testWalletId + "fullRescan");

      final rcv = await secureStore.read(
          key: "${testWalletId}fullRescan_receiveDerivations");
      final chg = await secureStore.read(
          key: "${testWalletId}fullRescan_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);
      }

      when(client.getBatchHistory(args: {
        "0": [SampleGetHistoryData.scripthash0],
        "1": [SampleGetHistoryData.scripthash3]
      })).thenAnswer((realInvocation) async => {
            "0": SampleGetHistoryData.data0,
            "1": SampleGetHistoryData.data3,
          });

      // 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);

      await firo.fullRescan(20, 1000);

      final receivingAddresses = await wallet.get('receivingAddresses');
      expect(receivingAddresses, ["a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"]);

      final changeAddresses = await wallet.get('changeAddresses');
      expect(changeAddresses, ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);

      final receivingIndex = await wallet.get('receivingIndex');
      expect(receivingIndex, 0);

      final changeIndex = await wallet.get('changeIndex');
      expect(changeIndex, 0);

      final _rcv = await secureStore.read(
          key: "${testWalletId}fullRescan_receiveDerivations");
      final _chg = await secureStore.read(
          key: "${testWalletId}fullRescan_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.length, 150);
      // expect(_changeDerivations.length, 150);
      expect(_receiveDerivations.length, 40);
      expect(_changeDerivations.length, 40);

      final mintIndex = await wallet.get('mintIndex');
      expect(mintIndex, 8);

      final lelantusCoins = await wallet.get('_lelantus_coins') as List;
      expect(lelantusCoins.length, 7);
      final lcoin = lelantusCoins
          .firstWhere((element) =>
              (Map<String, LelantusCoin>.from(element as Map))
                  .values
                  .first
                  .txId ==
              "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232")
          .values
          .first as LelantusCoin;
      expect(lcoin.index, 1);
      expect(lcoin.value, 9658);
      expect(lcoin.publicCoin,
          "7fd927efbea0a9e4ba299209aaee610c63359857596be0a2da276011a0baa84a0000");
      expect(lcoin.txId,
          "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232");
      expect(lcoin.anonymitySetId, 1);
      expect(lcoin.isUsed, true);

      final jIndex = await wallet.get('jindex');
      expect(jIndex, [2, 4, 6]);

      final lelantusTxModel = await wallet.get('latest_lelantus_tx_model');
      expect(lelantusTxModel.getAllTransactions().length, 5);
    }, timeout: const Timeout(Duration(minutes: 3)));

    test("fullRescan fails", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      await secureStore.write(
          key: '${testWalletId}fullRescan_mnemonic', value: TEST_MNEMONIC);

      // mock electrumx client calls
      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      // when(client.getCoinsForRecovery(setId: 1))
      //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
      when(client.getUsedCoinSerials(startNumber: 0))
          .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(cachedClient.clearSharedTransactionCache(coin: Coin.firo))
          .thenAnswer((_) async => {});

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}fullRescan",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      // pre grab derivations in order to set up mock calls needed later on
      await firo.fillAddresses(TEST_MNEMONIC);
      final wallet = await Hive.openBox<dynamic>("${testWalletId}fullRescan");

      final rcv = await secureStore.read(
          key: "${testWalletId}fullRescan_receiveDerivations");
      final chg = await secureStore.read(
          key: "${testWalletId}fullRescan_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);
      }

      when(client.getLatestCoinId()).thenThrow(Exception());

      bool didThrow = false;
      try {
        await firo.fullRescan(20, 1000);
      } catch (e) {
        didThrow = true;
      }
      expect(didThrow, true);

      final receivingAddresses = await wallet.get('receivingAddresses');
      expect(receivingAddresses, null);

      final changeAddresses = await wallet.get('changeAddresses');
      expect(changeAddresses, null);

      final receivingIndex = await wallet.get('receivingIndex');
      expect(receivingIndex, null);

      final changeIndex = await wallet.get('changeIndex');
      expect(changeIndex, null);

      final _rcv = await secureStore.read(
          key: "${testWalletId}fullRescan_receiveDerivations");
      final _chg = await secureStore.read(
          key: "${testWalletId}fullRescan_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.length, 40);
      expect(_changeDerivations.length, 40);

      final mintIndex = await wallet.get('mintIndex');
      expect(mintIndex, null);

      final lelantusCoins = await wallet.get('_lelantus_coins');
      expect(lelantusCoins, null);

      final jIndex = await wallet.get('jindex');
      expect(jIndex, null);

      final lelantusTxModel = await wallet.get('latest_lelantus_tx_model');
      expect(lelantusTxModel, null);
    }, timeout: const Timeout(Duration(minutes: 3)));

    test("recoverFromMnemonic then fullRescan", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_MAINNET,
            "hash_function": "sha256",
            "services": []
          });

      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      // when(client.getCoinsForRecovery(setId: 1))
      //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
      when(client.getUsedCoinSerials(startNumber: 0))
          .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(cachedClient.clearSharedTransactionCache(coin: Coin.firo))
          .thenAnswer((_) async => {});

      when(cachedClient.getAnonymitySet(
              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);
      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}recoverFromMnemonic",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      // pre grab derivations in order to set up mock calls needed later on
      await firo.fillAddresses(TEST_MNEMONIC);
      final wallet =
          await Hive.openBox<dynamic>("${testWalletId}recoverFromMnemonic");

      final rcv = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_receiveDerivations");
      final chg = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_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);
      }

      when(client.getBatchHistory(args: {
        "0": [SampleGetHistoryData.scripthash0],
        "1": [SampleGetHistoryData.scripthash3]
      })).thenAnswer((realInvocation) async => {
            "0": SampleGetHistoryData.data0,
            "1": SampleGetHistoryData.data3,
          });

      // 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);

      await firo.recoverFromMnemonic(
          mnemonic: TEST_MNEMONIC,
          maxUnusedAddressGap: 20,
          maxNumberOfIndexesToCheck: 1000,
          height: 0);

      final receivingAddresses = await wallet.get('receivingAddresses');
      expect(receivingAddresses, ["a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"]);

      final changeAddresses = await wallet.get('changeAddresses');
      expect(changeAddresses, ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);

      final receivingIndex = await wallet.get('receivingIndex');
      expect(receivingIndex, 0);

      final changeIndex = await wallet.get('changeIndex');
      expect(changeIndex, 0);

      final _rcv = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_receiveDerivations");
      final _chg = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_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.length, 190);
      // expect(_changeDerivations.length, 190);
      expect(_receiveDerivations.length, 80);
      expect(_changeDerivations.length, 80);

      final mintIndex = await wallet.get('mintIndex');
      expect(mintIndex, 8);

      final lelantusCoins = await wallet.get('_lelantus_coins') as List;
      expect(lelantusCoins.length, 7);
      final lcoin = lelantusCoins
          .firstWhere((element) =>
              (Map<String, LelantusCoin>.from(element as Map))
                  .values
                  .first
                  .txId ==
              "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232")
          .values
          .first as LelantusCoin;
      expect(lcoin.index, 1);
      expect(lcoin.value, 9658);
      expect(lcoin.publicCoin,
          "7fd927efbea0a9e4ba299209aaee610c63359857596be0a2da276011a0baa84a0000");
      expect(lcoin.txId,
          "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232");
      expect(lcoin.anonymitySetId, 1);
      expect(lcoin.isUsed, true);

      final jIndex = await wallet.get('jindex');
      expect(jIndex, [2, 4, 6]);

      final lelantusTxModel = await wallet.get('latest_lelantus_tx_model');
      expect(lelantusTxModel.getAllTransactions().length, 5);

      await firo.fullRescan(20, 1000);

      final _receivingAddresses = await wallet.get('receivingAddresses');
      expect(_receivingAddresses, ["a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg"]);

      final _changeAddresses = await wallet.get('changeAddresses');
      expect(_changeAddresses, ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);

      final _receivingIndex = await wallet.get('receivingIndex');
      expect(_receivingIndex, 0);

      final _changeIndex = await wallet.get('changeIndex');
      expect(_changeIndex, 0);

      final __rcv = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_receiveDerivations");
      final __chg = await secureStore.read(
          key: "${testWalletId}recoverFromMnemonic_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.length, 150);
      // expect(__changeDerivations.length, 150);
      expect(__receiveDerivations.length, 40);
      expect(__changeDerivations.length, 40);

      final _mintIndex = await wallet.get('mintIndex');
      expect(_mintIndex, 8);

      final _lelantusCoins = await wallet.get('_lelantus_coins') as List;
      expect(_lelantusCoins.length, 7);
      final _lcoin = _lelantusCoins
          .firstWhere((element) =>
              (Map<String, LelantusCoin>.from(element as Map))
                  .values
                  .first
                  .txId ==
              "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232")
          .values
          .first as LelantusCoin;
      expect(_lcoin.index, 1);
      expect(_lcoin.value, 9658);
      expect(_lcoin.publicCoin,
          "7fd927efbea0a9e4ba299209aaee610c63359857596be0a2da276011a0baa84a0000");
      expect(_lcoin.txId,
          "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232");
      expect(_lcoin.anonymitySetId, 1);
      expect(_lcoin.isUsed, true);

      final _jIndex = await wallet.get('jindex');
      expect(_jIndex, [2, 4, 6]);

      final _lelantusTxModel = await wallet.get('latest_lelantus_tx_model');
      expect(_lelantusTxModel.getAllTransactions().length, 5);
    }, timeout: const Timeout(Duration(minutes: 6)));

    test("recoverFromMnemonic fails testnet", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_MAINNET,
            "hash_function": "sha256",
            "services": []
          });

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}recoverFromMnemonic fails testnet",
        coin: Coin.firoTestNet,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      expect(
          () async => await firo.recoverFromMnemonic(
              mnemonic: TEST_MNEMONIC,
              maxUnusedAddressGap: 20,
              maxNumberOfIndexesToCheck: 1000,
              height: 0),
          throwsA(isA<Exception>()));
    }, timeout: const Timeout(Duration(minutes: 3)));

    test("recoverFromMnemonic fails mainnet", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_TESTNET,
            "hash_function": "sha256",
            "services": []
          });

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: testWalletId + "recoverFromMnemonic fails mainnet",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      expect(
          () async => await firo.recoverFromMnemonic(
              mnemonic: TEST_MNEMONIC,
              maxUnusedAddressGap: 20,
              height: 0,
              maxNumberOfIndexesToCheck: 1000),
          throwsA(isA<Exception>()));
    });

    test("incrementAddressIndexForChain receiving", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}incrementAddressIndexForChain receiving",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}incrementAddressIndexForChain receiving");
      await wallet.put("receivingIndex", 1);

      await expectLater(() async => await firo.incrementAddressIndexForChain(0),
          returnsNormally);

      expect(wallet.get("receivingIndex"), 2);
    });

    test("incrementAddressIndexForChain change", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}incrementAddressIndexForChain change",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox(
          "${testWalletId}incrementAddressIndexForChain change");
      await wallet.put("changeIndex", 1);

      await expectLater(() async => await firo.incrementAddressIndexForChain(1),
          returnsNormally);

      expect(wallet.get("changeIndex"), 2);
    });

    test("addToAddressesArrayForChain receiving", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}addToAddressesArrayForChain receiving",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}addToAddressesArrayForChain receiving");

      await expectLater(
          () async =>
              await firo.addToAddressesArrayForChain("Some Address String", 0),
          returnsNormally);

      expect(wallet.get("receivingAddresses"), ["Some Address String"]);
    });

    test("addToAddressesArrayForChain change", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}addToAddressesArrayForChain change",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}addToAddressesArrayForChain change");
      await wallet.put("changeAddresses", ["some address A"]);

      await expectLater(
          () async =>
              await firo.addToAddressesArrayForChain("Some Address B", 1),
          returnsNormally);

      expect(
          wallet.get("changeAddresses"), ["some address A", "Some Address B"]);
    });

    test("checkReceivingAddressForTransactions fails", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}checkReceivingAddressForTransactions fails",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      bool didThrow = false;
      try {
        await firo.checkReceivingAddressForTransactions();
      } catch (_) {
        didThrow = true;
      }
      expect(didThrow, true);
    });

    test("checkReceivingAddressForTransactions numtxs >= 1", () async {
      final client = MockElectrumX();
      final secureStore = FakeSecureStorage();

      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);

      final firo = FiroWallet(
        walletId:
            "${testWalletId}checkReceivingAddressForTransactions numtxs >= 1",
        walletName: testWalletName,
        coin: Coin.firo,
        client: client,
        cachedClient: MockCachedElectrumX(),
        secureStore: secureStore,
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}checkReceivingAddressForTransactions numtxs >= 1");
      await secureStore.write(
          key:
              "${testWalletId}checkReceivingAddressForTransactions numtxs >= 1_mnemonic",
          value: TEST_MNEMONIC);
      await wallet
          .put("receivingAddresses", ["aPjLWDTPQsoPHUTxKBNRzoebDALj3eTcfh"]);

      await wallet.put("receivingIndex", 1);

      await firo.checkReceivingAddressForTransactions();

      expect(await wallet.get("receivingIndex"), 2);
      expect((await wallet.get("receivingAddresses")).length, 2);
    });

    test("getLatestSetId", () async {
      final client = MockElectrumX();

      when(client.getLatestCoinId()).thenAnswer((_) async => 1);

      final firo = FiroWallet(
        walletId: testWalletId + "exit",
        walletName: testWalletName,
        coin: Coin.firo,
        client: client,
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final setId = await firo.getLatestSetId();
      expect(setId, 1);
    });

    // test("getSetData", () async {
    //   final client = MockElectrumX();
    //
    //   when(client.getCoinsForRecovery(setId: 1))
    //       .thenAnswer((_) async => getCoinsForRecoveryResponse);
    //
    //   final firo = FiroWallet(
    //     walletId: testWalletId + "exit",
    //     walletName: testWalletName,
    //     networkType: firoNetworkType,
    //     client: client,
    //     cachedClient: MockCachedElectrumX(),
    //     secureStore: FakeSecureStorage(),
    //     priceAPI: MockPriceAPI(),
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   final setData = await firo.getSetData(1);
    //   expect(setData, getCoinsForRecoveryResponse);
    // });

    test("getUsedCoinSerials", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();

      // when(client.getUsedCoinSerials(startNumber: 0))
      //     .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(cachedClient.getAnonymitySet(
              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);

      final firo = FiroWallet(
        walletId: testWalletId + "getUsedCoinSerials",
        walletName: testWalletName,
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      final serials = await firo.getUsedCoinSerials();
      expect(serials, GetUsedSerialsSampleData.serials['serials']);
    });

    test("firo refresh", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // set mnemonic
      await secureStore.write(
          key: "${testWalletId}refresh_mnemonic",
          value: RefreshTestParams.mnemonic);

      when(client.getBatchUTXOs(args: batchUtxoRequest))
          .thenAnswer((realInvocation) async => {});

      when(client.getBatchHistory(args: {
        "0": [SampleGetHistoryData.scripthash1],
        "1": [SampleGetHistoryData.scripthash0],
        "2": [SampleGetHistoryData.scripthash2],
        "3": [SampleGetHistoryData.scripthash3],
      })).thenAnswer((realInvocation) async => {
            "0": SampleGetHistoryData.data1,
            "1": SampleGetHistoryData.data0,
            "2": SampleGetHistoryData.data2,
            "3": SampleGetHistoryData.data3,
          });

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_MAINNET,
            "hash_function": "sha256",
            "services": []
          });

      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      // when(client.getCoinsForRecovery(setId: 1))
      //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
      when(client.getUsedCoinSerials(startNumber: 0))
          .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(client.estimateFee(blocks: 1))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));
      when(client.estimateFee(blocks: 5))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));
      when(client.estimateFee(blocks: 20))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));

      // mock history calls
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0))
          .thenAnswer((_) async => SampleGetHistoryData.data0);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2))
          .thenAnswer((_) async => SampleGetHistoryData.data2);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3))
          .thenAnswer((_) async => SampleGetHistoryData.data3);

      // 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);

      // mock utxo calls
      when(client.getUTXOs(scripthash: anyNamed("scripthash")))
          .thenAnswer((_) async => []);

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}refresh",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox<dynamic>("${testWalletId}refresh");
      await wallet.put(
          'receivingAddresses', RefreshTestParams.receivingAddresses);
      await wallet.put('changeAddresses', RefreshTestParams.changeAddresses);

      // set timer to non null so a periodic timer isn't created
      firo.timer = Timer(const Duration(), () {});

      await firo.refresh();

      // kill timer and listener
      await firo.exit();
    }, timeout: const Timeout(Duration(minutes: 3)));

    // test("send succeeds", () async {
    //   TestWidgetsFlutterBinding.ensureInitialized();
    //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
    //       .setMockMethodCallHandler((methodCall) async => 'en_US');
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   String expectedTxid = "-1";
    //   when(client.getLatestCoinId()).thenAnswer((_) async => 1);
    //   when(client.getBlockHeadTip()).thenAnswer(
    //       (_) async => {"height": 459185, "hex": "... some block hex ..."});
    //
    //   when(client.broadcastTransaction(rawTx: anyNamed("rawTx")))
    //       .thenAnswer((realInvocation) async {
    //     final rawTx = realInvocation.namedArguments[Symbol("rawTx")] as String;
    //     final rawTxData = Format.stringToUint8List(rawTx);
    //
    //     final hash = sha256
    //         .convert(sha256.convert(rawTxData.toList(growable: false)).bytes);
    //
    //     final reversedBytes =
    //         Uint8List.fromList(hash.bytes.reversed.toList(growable: false));
    //
    //     final txid = Format.uint8listToString(reversedBytes);
    //     expectedTxid = txid;
    //     return txid;
    //   });
    //
    //   when(cachedClient.getAnonymitySet(
    //     groupId: "1",
    //     coin: Coin.firo,
    //   )).thenAnswer((_) async => GetAnonymitySetSampleData.data);
    //
    //   // mock price calls
    //   when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
    //       (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});
    //
    //   // 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",
    //     walletName: testWalletName,
    //     coin: Coin.firo,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     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"]);
    //
    //   final result = await firo.send(
    //       toAddress: "aHZJsucDrhr4Uzzx6XXrKnaTgLxsEAokvV", amount: 100);
    //
    //   expect(result, isA<String>());
    //   expect(result, expectedTxid);
    //   expect(result.length, 64);
    // }, timeout: const Timeout(Duration(minutes: 3)));

    test("send fails due to insufficient balance", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();
      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      when(client.getBlockHeadTip()).thenAnswer(
          (_) async => {"height": 459185, "hex": "... some block hex ..."});

      when(client.broadcastTransaction(rawTx: anyNamed("rawTx")))
          .thenAnswer((realInvocation) async {
        final rawTx =
            realInvocation.namedArguments[const Symbol("rawTx")] as String;
        final rawTxData = Format.stringToUint8List(rawTx);

        final hash = sha256
            .convert(sha256.convert(rawTxData.toList(growable: false)).bytes);

        final reversedBytes =
            Uint8List.fromList(hash.bytes.reversed.toList(growable: false));

        final txid = Format.uint8listToString(reversedBytes);
        return txid;
      });
      when(client.getBatchHistory(args: batchHistoryRequest0))
          .thenAnswer((realInvocation) async => batchHistoryResponse0);

      when(cachedClient.getAnonymitySet(
        groupId: "1",
        coin: Coin.firo,
      )).thenAnswer((_) async => GetAnonymitySetSampleData.data);

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      // 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,
        priceAPI: priceAPI,
        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', []);
      await wallet.put('jindex', []);
      await wallet.put('mintIndex', 0);
      await wallet.put('receivingAddresses', [
        "a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg",
        "aPjLWDTPQsoPHUTxKBNRzoebDALj3eTcfh",
        "aKmXfS7nEZdqWBGRdAXcyMoEoKhZQDPBoq"
      ]);
      await wallet
          .put('changeAddresses', ["a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w"]);

      expect(
          () async => await firo.send(
              toAddress: "aHZJsucDrhr4Uzzx6XXrKnaTgLxsEAokvV", amount: 100),
          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();
      final priceAPI = MockPriceAPI();
      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 price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      // 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,
        priceAPI: priceAPI,
        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"]);

      expect(
          () async => await firo.send(
              toAddress: "aHZJsucDrhr4Uzzx6XXrKnaTgLxsEAokvV", amount: 100),
          throwsA(isA<Exception>()));
    }, timeout: const Timeout(Duration(minutes: 3)));

    test("wallet balances", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final priceAPI = MockPriceAPI();
      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      // mock history calls
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0))
          .thenAnswer((_) async => SampleGetHistoryData.data0);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2))
          .thenAnswer((_) async => SampleGetHistoryData.data2);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3))
          .thenAnswer((_) async => SampleGetHistoryData.data3);

      when(client.getBatchHistory(args: batchHistoryRequest0))
          .thenAnswer((realInvocation) async => batchHistoryResponse0);

      when(client.getBatchUTXOs(args: batchUtxoRequest))
          .thenAnswer((realInvocation) async => {});

      // 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);

      final firo = FiroWallet(
        walletId: "${testWalletId}wallet balances",
        walletName: "pendingBalance wallet name",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: FakeSecureStorage(),
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet =
          await Hive.openBox<dynamic>("${testWalletId}wallet balances");
      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",
      ]);

      expect(await firo.pendingBalance, Decimal.zero);
      expect(await firo.availableBalance, Decimal.parse("0.00021594"));
      expect(await firo.totalBalance, Decimal.parse("0.00021594"));
    });

    test("wallet balance minus maxfee - wallet balance is zero", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final priceAPI = MockPriceAPI();
      final secureStore = FakeSecureStorage();

      when(client.getBatchHistory(args: batchHistoryRequest0))
          .thenAnswer((realInvocation) async => batchHistoryResponse0);

      when(client.getBatchUTXOs(args: batchUtxoRequest))
          .thenAnswer((realInvocation) async => {});

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      // mock history calls
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0))
          .thenAnswer((_) async => SampleGetHistoryData.data0);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2))
          .thenAnswer((_) async => SampleGetHistoryData.data2);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3))
          .thenAnswer((_) async => SampleGetHistoryData.data3);

      // 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);

      final firo = FiroWallet(
        walletId: "${testWalletId}wallet balance minus maxfee",
        walletName: "pendingBalance wallet name",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      await secureStore.write(
          key: "${testWalletId}wallet balance minus maxfee_mnemonic",
          value: TEST_MNEMONIC);

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}wallet balance minus maxfee");
      await wallet.put('receivingAddresses', [
        "a8VV7vMzJdTQj1eLEJNskhLEBUxfNWhpAg",
        "aPjLWDTPQsoPHUTxKBNRzoebDALj3eTcfh",
        "aKmXfS7nEZdqWBGRdAXcyMoEoKhZQDPBoq",
      ]);

      await wallet.put('changeAddresses', [
        "a5V5r6We6mNZzWJwGwEeRML3mEYLjvK39w",
      ]);

      expect(await firo.maxFee, 0); // ???

      expect(await firo.balanceMinusMaxFee, Decimal.parse("0"));
    });

    test("wallet balance minus maxfee - wallet balance is not zero", () async {
      TestWidgetsFlutterBinding.ensureInitialized();
      const MethodChannel('uk.spiralarm.flutter/devicelocale')
          .setMockMethodCallHandler((methodCall) async => 'en_US');

      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final priceAPI = MockPriceAPI();
      final secureStore = FakeSecureStorage();

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      // mock history calls
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0))
          .thenAnswer((_) async => SampleGetHistoryData.data0);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2))
          .thenAnswer((_) async => SampleGetHistoryData.data2);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3))
          .thenAnswer((_) async => SampleGetHistoryData.data3);

      when(client.getBatchHistory(args: batchHistoryRequest0))
          .thenAnswer((realInvocation) async => batchHistoryResponse0);

      when(client.getBatchUTXOs(args: batchUtxoRequest))
          .thenAnswer((realInvocation) async => {});

      // 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}wallet balance minus maxfee",
        walletName: "pendingBalance wallet name",
        client: client,
        coin: Coin.firo,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      await secureStore.write(
          key: "${testWalletId}wallet balance minus maxfee_mnemonic",
          value: TEST_MNEMONIC);

      final wallet = await Hive.openBox<dynamic>(
          "${testWalletId}wallet balance minus maxfee");
      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",
      ]);

      expect(await firo.maxFee, 8914);

      expect(await firo.balanceMinusMaxFee, Decimal.parse("0.0001268"));
    });

    test("get transactionData", () async {
      final client = MockElectrumX();
      final cachedClient = MockCachedElectrumX();
      final secureStore = FakeSecureStorage();
      final priceAPI = MockPriceAPI();

      // set mnemonic
      await secureStore.write(
          key: "${testWalletId}transactionData_mnemonic",
          value: RefreshTestParams.mnemonic);

      // mock electrumx client calls
      when(client.getServerFeatures()).thenAnswer((_) async => {
            "hosts": {},
            "pruning": null,
            "server_version": "Unit tests",
            "protocol_min": "1.4",
            "protocol_max": "1.4.2",
            "genesis_hash": GENESIS_HASH_MAINNET,
            "hash_function": "sha256",
            "services": []
          });

      when(client.getLatestCoinId()).thenAnswer((_) async => 1);
      // when(client.getCoinsForRecovery(setId: 1))
      //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
      when(client.getUsedCoinSerials(startNumber: 0))
          .thenAnswer((_) async => GetUsedSerialsSampleData.serials);

      when(client.estimateFee(blocks: 1))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));
      when(client.estimateFee(blocks: 5))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));
      when(client.estimateFee(blocks: 20))
          .thenAnswer((_) async => Decimal.parse("0.00001000"));

      // mock history calls
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0))
          .thenAnswer((_) async => SampleGetHistoryData.data0);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1))
          .thenAnswer((_) async => SampleGetHistoryData.data1);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2))
          .thenAnswer((_) async => SampleGetHistoryData.data2);
      when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3))
          .thenAnswer((_) async => SampleGetHistoryData.data3);

      // 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);

      // mock utxo calls
      when(client.getUTXOs(scripthash: anyNamed("scripthash")))
          .thenAnswer((_) async => []);

      // mock price calls
      when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
          (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});

      final firo = FiroWallet(
        walletName: testWalletName,
        walletId: "${testWalletId}transactionData",
        coin: Coin.firo,
        client: client,
        cachedClient: cachedClient,
        secureStore: secureStore,
        priceAPI: priceAPI,
        tracker: MockTransactionNotificationTracker(),
      );

      final wallet = await Hive.openBox(testWalletId + "transactionData");
      await wallet.put(
          'receivingAddresses', RefreshTestParams.receivingAddresses);
      await wallet.put('changeAddresses', RefreshTestParams.changeAddresses);

      final txData = await firo.transactionData;

      expect(txData, isA<TransactionData>());

      // kill timer and listener
      await firo.exit();
    });

    // test("autoMint", () async {
    //   TestWidgetsFlutterBinding.ensureInitialized();
    //   const MethodChannel('uk.spiralarm.flutter/devicelocale')
    //       .setMockMethodCallHandler((methodCall) async => 'en_US');
    //
    //   final client = MockElectrumX();
    //   final cachedClient = MockCachedElectrumX();
    //   final secureStore = FakeSecureStorage();
    //   final priceAPI = MockPriceAPI();
    //
    //   // mock electrumx client calls
    //   when(client.getServerFeatures()).thenAnswer((_) async => {
    //         "hosts": {},
    //         "pruning": null,
    //         "server_version": "Unit tests",
    //         "protocol_min": "1.4",
    //         "protocol_max": "1.4.2",
    //         "genesis_hash": GENESIS_HASH_MAINNET,
    //         "hash_function": "sha256",
    //         "services": []
    //       });
    //
    //   when(client.getBlockHeadTip()).thenAnswer(
    //       (_) async => {"height": 465873, "hex": "this value not used here"});
    //
    //   when(client.broadcastTransaction(rawTx: anyNamed("rawTx")))
    //       .thenAnswer((realInvocation) async {
    //     final rawTx =
    //         realInvocation.namedArguments[const Symbol("rawTx")] as String;
    //     final rawTxData = Format.stringToUint8List(rawTx);
    //
    //     final hash = sha256
    //         .convert(sha256.convert(rawTxData.toList(growable: false)).bytes);
    //
    //     final reversedBytes =
    //         Uint8List.fromList(hash.bytes.reversed.toList(growable: false));
    //
    //     final txid = Format.uint8listToString(reversedBytes);
    //
    //     return txid;
    //   });
    //
    //   when(client.estimateFee(blocks: 1))
    //       .thenAnswer((_) async => Decimal.parse("0.00001000"));
    //   when(client.estimateFee(blocks: 5))
    //       .thenAnswer((_) async => Decimal.parse("0.00001000"));
    //   when(client.estimateFee(blocks: 20))
    //       .thenAnswer((_) async => Decimal.parse("0.00001000"));
    //
    //   when(cachedClient.getAnonymitySet(
    //           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);
    //
    //   when(client.getLatestCoinId()).thenAnswer((_) async => 1);
    //   // when(client.getCoinsForRecovery(setId: 1))
    //   //     .thenAnswer((_) async => getCoinsForRecoveryResponse);
    //   when(client.getUsedCoinSerials(startNumber: 0))
    //       .thenAnswer((_) async => GetUsedSerialsSampleData.serials);
    //
    //   // mock price calls
    //   when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer(
    //       (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)});
    //
    //   // 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);
    //   when(cachedClient.getTransaction(
    //     txHash: SampleGetTransactionData.txHash11,
    //     coin: Coin.firo,
    //   )).thenAnswer((_) async => SampleGetTransactionData.txData11);
    //   when(cachedClient.getTransaction(
    //     txHash: SampleGetTransactionData.txHash12,
    //     coin: Coin.firo,
    //   )).thenAnswer((_) async => SampleGetTransactionData.txData12);
    //
    //   final firo = FiroWallet(
    //     walletName: testWalletName,
    //     walletId: "${testWalletId}autoMint",
    //     coin: Coin.firo,
    //     client: client,
    //     cachedClient: cachedClient,
    //     secureStore: secureStore,
    //     priceAPI: priceAPI,
    //     tracker: MockTransactionNotificationTracker(),
    //   );
    //
    //   // pre grab derivations in order to set up mock calls needed later on
    //   await firo.fillAddresses(TEST_MNEMONIC);
    //   final wallet = await Hive.openBox<dynamic>("${testWalletId}autoMint");
    //   await wallet.put(
    //       'receivingAddresses', RefreshTestParams.receivingAddresses);
    //   await wallet.put('changeAddresses', RefreshTestParams.changeAddresses);
    //
    //   final rcv = await secureStore.read(
    //       key: "${testWalletId}autoMint_receiveDerivations");
    //   final chg = await secureStore.read(
    //       key: "${testWalletId}autoMint_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);
    //   }
    //
    //   when(client.getUTXOs(scripthash: GetUtxoSampleData.scriptHash0))
    //       .thenAnswer((_) async => GetUtxoSampleData.utxos0);
    //   when(client.getUTXOs(scripthash: GetUtxoSampleData.scriptHash1))
    //       .thenAnswer((_) async => GetUtxoSampleData.utxos1);
    //
    //   await firo.recoverFromMnemonic(
    //       mnemonic: TEST_MNEMONIC,
    //       maxUnusedAddressGap: 20,
    //       height: 0,
    //       maxNumberOfIndexesToCheck: 1000);
    //
    //   firo.timer = Timer(const Duration(minutes: 3), () {});
    //
    //   await firo.refresh();
    //
    //   bool flag = false;
    //   try {
    //     await firo.autoMint();
    //   } catch (_) {
    //     flag = true;
    //   }
    //   expect(flag, false);
    //
    //   await firo.exit();
    // }, timeout: const Timeout(Duration(minutes: 3)));

    test("exit", () async {
      final firo = FiroWallet(
        walletId: "${testWalletId}exit",
        walletName: testWalletName,
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      firo.timer = Timer(const Duration(seconds: 2), () {});

      bool flag = false;
      try {
        await firo.exit();
      } catch (_) {
        flag = true;
      }
      expect(flag, false);
      expect(firo.timer, null);
    });

    tearDown(() async {
      await tearDownTestHive();
    });
  });

  group("simple getters", () {
    group("fees", () {
      test("get fees succeeds", () async {
        final client = MockElectrumX();

        when(client.estimateFee(blocks: 1))
            .thenAnswer((_) async => Decimal.parse("0.00001000"));
        when(client.estimateFee(blocks: 5))
            .thenAnswer((_) async => Decimal.parse("0.00001000"));
        when(client.estimateFee(blocks: 20))
            .thenAnswer((_) async => Decimal.parse("0.00001000"));

        final firo = FiroWallet(
          walletId: "some id",
          walletName: "some name",
          coin: Coin.firo,
          client: client,
          cachedClient: MockCachedElectrumX(),
          secureStore: FakeSecureStorage(),
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );

        expect((await firo.fees).fast, 1000);
        expect((await firo.fees).medium, 1000);
        expect((await firo.fees).slow, 1000);
      });

      test("get fees throws", () {
        final client = MockElectrumX();

        when(client.estimateFee(blocks: 1))
            .thenThrow(Exception("Some exception"));

        final firo = FiroWallet(
          walletId: "some id",
          walletName: "some name",
          coin: Coin.firo,
          client: client,
          cachedClient: MockCachedElectrumX(),
          secureStore: FakeSecureStorage(),
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );

        expect(firo.fees, throwsA(isA<Exception>()));
      });
    });

    group("coin", () {
      test("get main net coinTicker", () {
        final firo = FiroWallet(
          walletId: "some id",
          walletName: "some name",
          coin: Coin.firo,
          client: MockElectrumX(),
          cachedClient: MockCachedElectrumX(),
          secureStore: FakeSecureStorage(),
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );

        expect(firo.coin, Coin.firo);
      });

      test("get test net coin", () {
        final firo = FiroWallet(
          walletId: "some id",
          walletName: "some name",
          coin: Coin.firoTestNet,
          client: MockElectrumX(),
          cachedClient: MockCachedElectrumX(),
          secureStore: FakeSecureStorage(),
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );

        expect(firo.coin, Coin.firoTestNet);
      });
    });

    group("mnemonic", () {
      test("fetch and convert properly stored mnemonic to list of words",
          () async {
        final store = FakeSecureStorage();
        store.write(
            key: "some id_mnemonic",
            value: "some test mnemonic string of words");

        final firo = FiroWallet(
          walletName: 'unit test',
          walletId: 'some id',
          coin: Coin.firoTestNet,
          client: MockElectrumX(),
          cachedClient: MockCachedElectrumX(),
          secureStore: store,
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );
        final List<String> result = await firo.mnemonic;

        expect(result, [
          "some",
          "test",
          "mnemonic",
          "string",
          "of",
          "words",
        ]);
      });

      test("attempt fetch and convert non existent mnemonic to list of words",
          () async {
        final store = FakeSecureStorage();
        store.write(
            key: "some id_mnemonic",
            value: "some test mnemonic string of words");

        final firo = FiroWallet(
          walletName: 'unit test',
          walletId: 'some other id',
          coin: Coin.firoTestNet,
          client: MockElectrumX(),
          cachedClient: MockCachedElectrumX(),
          secureStore: store,
          priceAPI: MockPriceAPI(),
          tracker: MockTransactionNotificationTracker(),
        );
        final mnemonic = await firo.mnemonic;
        expect(mnemonic, <String>[]);
      });
    });

    test("walletName", () {
      final firo = FiroWallet(
        walletId: "some id",
        walletName: "some name",
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.walletName, "some name");

      firo.walletName = "new name";
      expect(firo.walletName, "new name");
    });

    test("walletId", () {
      final firo = FiroWallet(
        walletId: "some id",
        walletName: "some name",
        coin: Coin.firo,
        client: MockElectrumX(),
        cachedClient: MockCachedElectrumX(),
        secureStore: FakeSecureStorage(),
        priceAPI: MockPriceAPI(),
        tracker: MockTransactionNotificationTracker(),
      );

      expect(firo.walletId, "some id");
    });
  });
}