public CryptoStatus getCryptoStatus(String transactionHash)
      throws OutgoingIntraActorCantGetCryptoStatusException {
    try {
      DatabaseTable transactionTable =
          this.database.getTable(
              OutgoingDraftTransactionDatabaseConstants.OUTGOING_DRAFT_TABLE_NAME);
      transactionTable.addStringFilter(
          OutgoingDraftTransactionDatabaseConstants.OUTGOING_DRAFT_TRANSACTION_HASH_COLUMN_NAME,
          transactionHash,
          DatabaseFilterType.EQUAL);
      transactionTable.loadToMemory();
      List<DatabaseTableRecord> records = transactionTable.getRecords();
      transactionTable.clearAllFilters();

      return CryptoStatus.getByCode(
          records
              .get(0)
              .getStringValue(
                  OutgoingDraftTransactionDatabaseConstants
                      .OUTGOING_DRAFT_CRYPTO_STATUS_COLUMN_NAME));
    } catch (InvalidParameterException | CantLoadTableToMemoryException e) {
      throw new OutgoingIntraActorCantGetCryptoStatusException("An exception happened", e, "", "");
    } catch (Exception e) {
      throw new OutgoingIntraActorCantGetCryptoStatusException(
          "An unexpected exception happened", FermatException.wrapException(e), "", "");
    }
  }
  /**
   * Creates a incoming or outgoing CryptoTransaction object from a database record
   *
   * @param transactionType
   * @param record
   * @return
   */
  private CryptoTransaction getCryptoTransactionFromRecord(
      TransactionTypes transactionType, DatabaseTableRecord record) {
    String addressFromColumnName,
        addressToColumnName,
        transactionHashColumnName,
        valueColumnName,
        cryptoStatusColumnName;
    if (transactionType == TransactionTypes.INCOMING) {
      transactionHashColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_HASH_COLUMN_NAME;
      addressFromColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_ADDRESS_FROM_COLUMN_NAME;
      addressToColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_ADDRESS_TO_COLUMN_NAME;
      valueColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_VALUE_COLUMN_NAME;
      cryptoStatusColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME;
    } else {
      transactionHashColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_HASH_COLUMN_NAME;
      addressFromColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_ADDRESS_FROM_COLUMN_NAME;
      addressToColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_ADDRESS_TO_COLUMN_NAME;
      valueColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_VALUE_COLUMN_NAME;
      cryptoStatusColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME;
    }

    CryptoTransaction cryptoTransaction = new CryptoTransaction();
    cryptoTransaction.setTransactionHash(record.getStringValue(transactionHashColumnName));
    cryptoTransaction.setCryptoCurrency(CryptoCurrency.BITCOIN);
    try {
      cryptoTransaction.setCryptoStatus(
          CryptoStatus.getByCode(record.getStringValue(cryptoStatusColumnName)));
    } catch (InvalidParameterException e) {
      e.printStackTrace();
    }
    cryptoTransaction.setCryptoAmount(record.getLongValue(valueColumnName));
    cryptoTransaction.setAddressFrom(
        new CryptoAddress(record.getStringValue(addressFromColumnName), CryptoCurrency.BITCOIN));
    cryptoTransaction.setAddressTo(
        new CryptoAddress(record.getStringValue(addressToColumnName), CryptoCurrency.BITCOIN));

    // todo define how to get the Op_Return value
    return cryptoTransaction;
  }
  /**
   * Gets the crypto Status list that are in pending status from the specified table.
   *
   * @param transactionType
   * @return
   */
  public Set<CryptoStatus> getPendingCryptoStatus(TransactionTypes transactionType)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable;
    String cryptoStatusColumnName;
    Set<CryptoStatus> cryptoStatuses = new HashSet<>();

    /** Will set up filters and column names depending on the transaction type. */
    if (transactionType == TransactionTypes.OUTGOING) {
      databaseTable =
          database.getTable(BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_TABLE_NAME);
      databaseTable.setStringFilter(
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_PROTOCOL_STATUS_COLUMN_NAME,
          ProtocolStatus.TO_BE_NOTIFIED.getCode(),
          DatabaseFilterType.EQUAL);
      cryptoStatusColumnName =
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME;
    } else {
      databaseTable =
          database.getTable(BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_TABLE_NAME);
      databaseTable.setStringFilter(
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_PROTOCOL_STATUS_COLUMN_NAME,
          ProtocolStatus.TO_BE_NOTIFIED.getCode(),
          DatabaseFilterType.EQUAL);
      cryptoStatusColumnName =
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME;
    }

    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    /** get all the CryptoStatus and remove duplicates as Im storing them in a set. */
    for (DatabaseTableRecord record : databaseTable.getRecords()) {
      try {
        CryptoStatus cryptoStatus =
            CryptoStatus.getByCode(record.getStringValue(cryptoStatusColumnName));
        cryptoStatuses.add(cryptoStatus);
      } catch (InvalidParameterException e) {
        e.printStackTrace();
      }
    }

    return cryptoStatuses;
  }
  /**
   * Gets the incoming transaction data and forms the CryptoTransaction object
   *
   * @param txHash
   * @return
   * @throws CantExecuteDatabaseOperationException
   */
  public List<CryptoTransaction> getIncomingCryptoTransaction(String txHash)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        database.getTable(BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_TABLE_NAME);
    databaseTable.setStringFilter(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_HASH_COLUMN_NAME,
        txHash,
        DatabaseFilterType.EQUAL);

    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    List<CryptoTransaction> cryptoTransactions = new ArrayList<>();
    for (DatabaseTableRecord record : databaseTable.getRecords()) {

      /** Gets all the values */
      CryptoAddress addressFrom = new CryptoAddress();
      addressFrom.setAddress(
          record.getStringValue(
              BitcoinCryptoNetworkDatabaseConstants
                  .INCOMING_TRANSACTIONS_ADDRESS_FROM_COLUMN_NAME));
      addressFrom.setCryptoCurrency(CryptoCurrency.BITCOIN);

      CryptoAddress addressTo = new CryptoAddress();
      addressFrom.setAddress(
          record.getStringValue(
              BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_ADDRESS_TO_COLUMN_NAME));
      addressFrom.setCryptoCurrency(CryptoCurrency.BITCOIN);

      long amount =
          record.getLongValue(
              BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_VALUE_COLUMN_NAME);

      CryptoStatus cryptoStatus = null;
      try {
        cryptoStatus =
            CryptoStatus.getByCode(
                record.getStringValue(
                    BitcoinCryptoNetworkDatabaseConstants
                        .INCOMING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME));
      } catch (InvalidParameterException e) {
        e.printStackTrace();
      }

      String op_Return =
          record.getStringValue(
              BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_OP_RETURN_COLUMN_NAME);

      /** Forms the CryptoTransaction object */
      CryptoTransaction cryptoTransaction = new CryptoTransaction();
      cryptoTransaction.setTransactionHash(txHash);
      cryptoTransaction.setAddressTo(addressTo);
      cryptoTransaction.setAddressFrom(addressFrom);
      cryptoTransaction.setCryptoAmount(amount);
      cryptoTransaction.setCryptoCurrency(CryptoCurrency.BITCOIN);
      cryptoTransaction.setCryptoStatus(cryptoStatus);
      cryptoTransaction.setOp_Return(op_Return);

      /** adds it to the list */
      cryptoTransactions.add(cryptoTransaction);
    }

    return cryptoTransactions;
  }
  /**
   * Will get the last current Crypto Status recorded from the given outgoing or incoming
   * transaction
   *
   * @param transactionType
   * @param txHash
   * @return
   */
  public CryptoStatus getStoredTransactionCryptoStatus(
      TransactionTypes transactionType, String txHash)
      throws CantExecuteDatabaseOperationException {
    /** I will define the outgoing or incoming table, the filter and the sort order */
    DatabaseTable databaseTable = null;
    if (transactionType == TransactionTypes.OUTGOING) {
      databaseTable =
          database.getTable(BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_TABLE_NAME);
      databaseTable.setStringFilter(
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_HASH_COLUMN_NAME,
          txHash,
          DatabaseFilterType.EQUAL);
      databaseTable.setFilterOrder(
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_LAST_UPDATE_COLUMN_NAME,
          DatabaseFilterOrder.DESCENDING);
    } else {
      databaseTable =
          database.getTable(BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_TABLE_NAME);
      databaseTable.setStringFilter(
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_HASH_COLUMN_NAME,
          txHash,
          DatabaseFilterType.EQUAL);
      databaseTable.setFilterOrder(
          BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_LAST_UPDATE_COLUMN_NAME,
          DatabaseFilterOrder.DESCENDING);
    }

    /** Wil load the table into memory */
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    /**
     * Since Im ordering by update date, I will only get the fist record retrieved to form the
     * crypto status
     */
    DatabaseTableRecord record = databaseTable.getRecords().get(0);
    CryptoStatus cryptoStatus = null;

    /** will get and form the crypto status */
    try {
      if (transactionType == TransactionTypes.OUTGOING)
        cryptoStatus =
            CryptoStatus.getByCode(
                record.getStringValue(
                    BitcoinCryptoNetworkDatabaseConstants
                        .OUTGOING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME));
      else
        cryptoStatus =
            CryptoStatus.getByCode(
                record.getStringValue(
                    BitcoinCryptoNetworkDatabaseConstants
                        .INCOMING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME));
    } catch (InvalidParameterException e) {
      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          "Cant load the crypto status from the database.",
          "database error");
    }

    return cryptoStatus;
  }