From f4738baef78fc8ca6987f79af91fad62d33c0514 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sat, 15 Dec 2018 10:49:50 -0700 Subject: [PATCH] server: Update playsonify to 2.0.0 --- .../explorer/data/BalanceDataHandler.scala | 3 ++- .../xsn/explorer/data/BlockDataHandler.scala | 3 ++- .../data/TransactionDataHandler.scala | 3 ++- .../anorm/BalancePostgresDataHandler.scala | 6 ++--- .../data/anorm/BlockPostgresDataHandler.scala | 6 ++--- .../TransactionPostgresDataHandler.scala | 5 ++-- .../data/anorm/dao/BalancePostgresDAO.scala | 7 +++--- .../data/anorm/dao/BlockPostgresDAO.scala | 7 +++--- .../anorm/dao/TransactionPostgresDAO.scala | 7 +++--- .../interpreters/ColumnNameResolver.scala | 19 --------------- .../FieldOrderingSQLInterpreter.scala | 23 ------------------- .../data/async/BalanceFutureDataHandler.scala | 6 ++--- .../data/async/BlockFutureDataHandler.scala | 10 ++++---- .../async/TransactionFutureDataHandler.scala | 7 +++--- .../xsn/explorer/errors/addressErrors.scala | 6 ++--- .../xsn/explorer/errors/balanceErrors.scala | 8 ++++--- .../com/xsn/explorer/errors/blockErrors.scala | 15 ++++++------ .../xsn/explorer/errors/ipAddressErrors.scala | 6 ++--- .../xsn/explorer/errors/ledgerErrors.scala | 4 ++-- .../explorer/errors/masternodeErrors.scala | 6 ++--- .../xsn/explorer/errors/orderingErrors.scala | 14 +++++------ .../xsn/explorer/errors/postgresErrors.scala | 4 +++- .../explorer/errors/transactionErrors.scala | 22 ++++++++++-------- .../com/xsn/explorer/errors/xsnErrors.scala | 16 +++++++------ .../app/com/xsn/explorer/models/Address.scala | 3 +-- .../explorer/models/fields/BalanceField.scala | 2 +- .../explorer/models/fields/BlockField.scala | 2 +- .../models/fields/TransactionField.scala | 2 +- .../app/com/xsn/explorer/models/package.scala | 15 ++++++++++++ .../parsers/BalanceOrderingParser.scala | 2 +- .../parsers/MasternodeOrderingParser.scala | 2 +- .../parsers/TransactionOrderingParser.scala | 2 +- .../explorer/play/MyHttpErrorHandler.scala | 7 +++--- .../explorer/services/BalanceService.scala | 6 ++--- .../explorer/services/MasternodeService.scala | 6 ++--- .../services/TransactionService.scala | 5 ++-- .../app/controllers/AddressesController.scala | 16 +++++++------ .../app/controllers/BalancesController.scala | 12 ++++++---- server/app/controllers/BlocksController.scala | 18 ++++++++------- .../controllers/MasternodesController.scala | 14 ++++++----- .../controllers/StatisticsController.scala | 5 ++-- .../controllers/TransactionsController.scala | 14 +++++------ server/app/controllers/common/Codecs.scala | 13 +++++++++++ .../common/MyAuthenticatorService.scala | 4 ++-- .../controllers/common/MyJsonController.scala | 23 ++++++++----------- .../common/MyJsonControllerComponents.scala | 4 ++-- server/build.sbt | 11 ++++++--- .../data/BalancePostgresDataHandlerSpec.scala | 5 ++-- .../data/BlockPostgresDataHandlerSpec.scala | 5 ++-- .../data/LedgerPostgresDataHandlerSpec.scala | 2 +- .../StatisticsPostgresDataHandlerSpec.scala | 2 +- .../TransactionPostgresDataHandlerSpec.scala | 5 ++-- .../helpers/BalanceDummyDataHandler.scala | 3 ++- .../helpers/TransactionDummyDataHandler.scala | 3 ++- .../LedgerSynchronizerServiceSpec.scala | 2 +- .../controllers/AddressesControllerSpec.scala | 5 ++-- .../controllers/BalancesControllerSpec.scala | 3 ++- .../controllers/BlocksControllerSpec.scala | 5 ++-- .../MasternodesControllerSpec.scala | 2 +- .../TransactionsControllerSpec.scala | 2 +- 60 files changed, 231 insertions(+), 214 deletions(-) delete mode 100644 server/app/com/xsn/explorer/data/anorm/interpreters/ColumnNameResolver.scala delete mode 100644 server/app/com/xsn/explorer/data/anorm/interpreters/FieldOrderingSQLInterpreter.scala create mode 100644 server/app/com/xsn/explorer/models/package.scala diff --git a/server/app/com/xsn/explorer/data/BalanceDataHandler.scala b/server/app/com/xsn/explorer/data/BalanceDataHandler.scala index 2ee3364..edd3982 100644 --- a/server/app/com/xsn/explorer/data/BalanceDataHandler.scala +++ b/server/app/com/xsn/explorer/data/BalanceDataHandler.scala @@ -1,7 +1,8 @@ package com.xsn.explorer.data import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.models.fields.BalanceField import com.xsn.explorer.models.{Address, Balance} diff --git a/server/app/com/xsn/explorer/data/BlockDataHandler.scala b/server/app/com/xsn/explorer/data/BlockDataHandler.scala index 4f3aceb..ae25552 100644 --- a/server/app/com/xsn/explorer/data/BlockDataHandler.scala +++ b/server/app/com/xsn/explorer/data/BlockDataHandler.scala @@ -1,7 +1,8 @@ package com.xsn.explorer.data import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.models.fields.BlockField import com.xsn.explorer.models.rpc.Block import com.xsn.explorer.models.{Blockhash, Height} diff --git a/server/app/com/xsn/explorer/data/TransactionDataHandler.scala b/server/app/com/xsn/explorer/data/TransactionDataHandler.scala index f5b29b1..30896c3 100644 --- a/server/app/com/xsn/explorer/data/TransactionDataHandler.scala +++ b/server/app/com/xsn/explorer/data/TransactionDataHandler.scala @@ -1,7 +1,8 @@ package com.xsn.explorer.data import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField import org.scalactic.Every diff --git a/server/app/com/xsn/explorer/data/anorm/BalancePostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/BalancePostgresDataHandler.scala index 91acf75..f98a006 100644 --- a/server/app/com/xsn/explorer/data/anorm/BalancePostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/BalancePostgresDataHandler.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.data.anorm -import javax.inject.Inject - import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.BalanceBlockingDataHandler import com.xsn.explorer.data.anorm.dao.BalancePostgresDAO import com.xsn.explorer.errors.BalanceUnknownError import com.xsn.explorer.models.fields.BalanceField import com.xsn.explorer.models.{Address, Balance} +import javax.inject.Inject import org.scalactic.{Good, One, Or} import play.api.db.Database diff --git a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala index 2ff4245..425ecbd 100644 --- a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala @@ -1,15 +1,15 @@ package com.xsn.explorer.data.anorm -import javax.inject.Inject - import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.BlockBlockingDataHandler import com.xsn.explorer.data.anorm.dao.BlockPostgresDAO import com.xsn.explorer.errors._ import com.xsn.explorer.models.fields.BlockField import com.xsn.explorer.models.rpc.Block import com.xsn.explorer.models.{Blockhash, Height} +import javax.inject.Inject import org.scalactic.{Good, One, Or} import play.api.db.Database diff --git a/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala index 394a034..373890d 100644 --- a/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala @@ -1,12 +1,13 @@ package com.xsn.explorer.data.anorm -import javax.inject.Inject import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.data.anorm.dao.TransactionPostgresDAO import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField +import javax.inject.Inject import org.scalactic.{Every, Good} import play.api.db.Database diff --git a/server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala index 9a9c801..82a9adf 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/BalancePostgresDAO.scala @@ -1,14 +1,15 @@ package com.xsn.explorer.data.anorm.dao import java.sql.Connection -import javax.inject.Inject import anorm._ -import com.alexitc.playsonify.models.{Count, FieldOrdering, PaginatedQuery} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery} +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.parsers.BalanceParsers._ import com.xsn.explorer.models.fields.BalanceField import com.xsn.explorer.models.{Address, Balance} +import javax.inject.Inject import org.slf4j.LoggerFactory class BalancePostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderingSQLInterpreter) { diff --git a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala index 9633af0..4c56b08 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala @@ -1,15 +1,16 @@ package com.xsn.explorer.data.anorm.dao import java.sql.Connection -import javax.inject.Inject import anorm._ -import com.alexitc.playsonify.models._ -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter +import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition} +import com.alexitc.playsonify.models.pagination.{Count, Limit, Offset, PaginatedQuery} +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.parsers.BlockParsers._ import com.xsn.explorer.models.fields.BlockField import com.xsn.explorer.models.rpc.Block import com.xsn.explorer.models.{Blockhash, Height} +import javax.inject.Inject class BlockPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderingSQLInterpreter) { diff --git a/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala index ba8f9c8..d57748a 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala @@ -2,13 +2,14 @@ package com.xsn.explorer.data.anorm.dao import java.sql.Connection -import javax.inject.Inject import anorm._ -import com.alexitc.playsonify.models.{Count, FieldOrdering, PaginatedQuery} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery} +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.parsers.TransactionParsers._ import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField +import javax.inject.Inject import org.scalactic.Every class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderingSQLInterpreter) { diff --git a/server/app/com/xsn/explorer/data/anorm/interpreters/ColumnNameResolver.scala b/server/app/com/xsn/explorer/data/anorm/interpreters/ColumnNameResolver.scala deleted file mode 100644 index 169099c..0000000 --- a/server/app/com/xsn/explorer/data/anorm/interpreters/ColumnNameResolver.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.xsn.explorer.data.anorm.interpreters - -import scala.annotation.implicitNotFound - -@implicitNotFound( - "No column name resolver found for type ${A}. Try to implement an implicit ColumnNameResolver for this type." -) -trait ColumnNameResolver[A] { - - /** - * Maps a field to the column name on the sql schema. - */ - def getColumnName(field: A): String - - /** - * This is used to break ties while sorting by non-unique fields, - */ - def getUniqueColumnName: String -} diff --git a/server/app/com/xsn/explorer/data/anorm/interpreters/FieldOrderingSQLInterpreter.scala b/server/app/com/xsn/explorer/data/anorm/interpreters/FieldOrderingSQLInterpreter.scala deleted file mode 100644 index 162d7ca..0000000 --- a/server/app/com/xsn/explorer/data/anorm/interpreters/FieldOrderingSQLInterpreter.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.xsn.explorer.data.anorm.interpreters - -import com.alexitc.playsonify.models.{FieldOrdering, OrderingCondition} - -class FieldOrderingSQLInterpreter { - - def toOrderByClause[A](fieldOrdering: FieldOrdering[A])(implicit columnNameResolver: ColumnNameResolver[A]) = { - val field = columnNameResolver.getColumnName(fieldOrdering.field) - val condition = getCondition(fieldOrdering.orderingCondition) - val uniqueField = columnNameResolver.getUniqueColumnName - - if (field == uniqueField) { - s"ORDER BY $field $condition" - } else { - s"ORDER BY $field $condition, $uniqueField" - } - } - - private def getCondition(ordering: OrderingCondition) = ordering match { - case OrderingCondition.AscendingOrder => "ASC" - case OrderingCondition.DescendingOrder => "DESC" - } -} diff --git a/server/app/com/xsn/explorer/data/async/BalanceFutureDataHandler.scala b/server/app/com/xsn/explorer/data/async/BalanceFutureDataHandler.scala index 3f050d4..18fd167 100644 --- a/server/app/com/xsn/explorer/data/async/BalanceFutureDataHandler.scala +++ b/server/app/com/xsn/explorer/data/async/BalanceFutureDataHandler.scala @@ -1,13 +1,13 @@ package com.xsn.explorer.data.async -import javax.inject.Inject - import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.PaginatedQuery import com.xsn.explorer.data.{BalanceBlockingDataHandler, BalanceDataHandler} import com.xsn.explorer.executors.DatabaseExecutionContext import com.xsn.explorer.models.fields.BalanceField import com.xsn.explorer.models.{Address, Balance} +import javax.inject.Inject import scala.concurrent.Future diff --git a/server/app/com/xsn/explorer/data/async/BlockFutureDataHandler.scala b/server/app/com/xsn/explorer/data/async/BlockFutureDataHandler.scala index 5864799..dc2e45a 100644 --- a/server/app/com/xsn/explorer/data/async/BlockFutureDataHandler.scala +++ b/server/app/com/xsn/explorer/data/async/BlockFutureDataHandler.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.data.async -import javax.inject.Inject - -import com.alexitc.playsonify.core.FutureApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.PaginatedQuery import com.xsn.explorer.data.{BlockBlockingDataHandler, BlockDataHandler} import com.xsn.explorer.executors.DatabaseExecutionContext import com.xsn.explorer.models.fields.BlockField import com.xsn.explorer.models.rpc.Block import com.xsn.explorer.models.{Blockhash, Height} +import javax.inject.Inject import scala.concurrent.Future @@ -25,7 +25,7 @@ class BlockFutureDataHandler @Inject() ( blockBlockingDataHandler.getBy(height) } - override def getBy(paginatedQuery: PaginatedQuery, ordering: FieldOrdering[BlockField]): FutureApplicationResult[PaginatedResult[Block]] = Future { + override def getBy(paginatedQuery: PaginatedQuery, ordering: FieldOrdering[BlockField]): FuturePaginatedResult[Block] = Future { blockBlockingDataHandler.getBy(paginatedQuery, ordering) } diff --git a/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala b/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala index 8a0dc42..2654850 100644 --- a/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala +++ b/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala @@ -1,12 +1,13 @@ package com.xsn.explorer.data.async -import javax.inject.Inject import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.PaginatedQuery import com.xsn.explorer.data.{TransactionBlockingDataHandler, TransactionDataHandler} import com.xsn.explorer.executors.DatabaseExecutionContext import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField +import javax.inject.Inject import org.scalactic.Every import scala.concurrent.Future @@ -31,7 +32,7 @@ class TransactionFutureDataHandler @Inject() ( override def getByBlockhash( blockhash: Blockhash, paginatedQuery: PaginatedQuery, - ordering: FieldOrdering[TransactionField]): FutureApplicationResult[PaginatedResult[TransactionWithValues]] = Future { + ordering: FieldOrdering[TransactionField]): FuturePaginatedResult[TransactionWithValues] = Future { blockingDataHandler.getByBlockhash(blockhash, paginatedQuery, ordering) } diff --git a/server/app/com/xsn/explorer/errors/addressErrors.scala b/server/app/com/xsn/explorer/errors/addressErrors.scala index f90eedc..54b6afa 100644 --- a/server/app/com/xsn/explorer/errors/addressErrors.scala +++ b/server/app/com/xsn/explorer/errors/addressErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models.{FieldValidationError, InputValidationError, PublicError} -import play.api.i18n.{Lang, MessagesApi} sealed trait AddressError case object AddressFormatError extends AddressError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.address.format") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.address.format") val error = FieldValidationError("address", message) List(error) } diff --git a/server/app/com/xsn/explorer/errors/balanceErrors.scala b/server/app/com/xsn/explorer/errors/balanceErrors.scala index 4cfaa9e..7c9c04d 100644 --- a/server/app/com/xsn/explorer/errors/balanceErrors.scala +++ b/server/app/com/xsn/explorer/errors/balanceErrors.scala @@ -1,13 +1,15 @@ package com.xsn.explorer.errors -import com.alexitc.playsonify.models.{PublicError, ServerError} -import play.api.i18n.{Lang, MessagesApi} +import com.alexitc.playsonify.core.I18nService +import com.alexitc.playsonify.models.{ErrorId, PublicError, ServerError} sealed trait BalanceError case object BalanceUnknownError extends BalanceError with ServerError { + val id = ErrorId.create + override def cause: Option[Throwable] = None - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = List.empty + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = List.empty } diff --git a/server/app/com/xsn/explorer/errors/blockErrors.scala b/server/app/com/xsn/explorer/errors/blockErrors.scala index a008e65..26aff64 100644 --- a/server/app/com/xsn/explorer/errors/blockErrors.scala +++ b/server/app/com/xsn/explorer/errors/blockErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors -import com.alexitc.playsonify.models.{FieldValidationError, InputValidationError, PublicError, ServerError} -import play.api.i18n.{Lang, MessagesApi} +import com.alexitc.playsonify.core.I18nService +import com.alexitc.playsonify.models._ sealed trait BlockError case object BlockhashFormatError extends BlockError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.block.format") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.block.format") val error = FieldValidationError("blockhash", message) List(error) } @@ -16,14 +16,15 @@ case object BlockhashFormatError extends BlockError with InputValidationError { case object BlockNotFoundError extends BlockError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.block.notFound") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.block.notFound") val error = FieldValidationError("blockhash", message) List(error) } } case object BlockUnknownError extends BlockError with ServerError { + val id = ErrorId.create override def cause: Option[Throwable] = None - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = List.empty + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = List.empty } diff --git a/server/app/com/xsn/explorer/errors/ipAddressErrors.scala b/server/app/com/xsn/explorer/errors/ipAddressErrors.scala index 96af5b2..8c3199f 100644 --- a/server/app/com/xsn/explorer/errors/ipAddressErrors.scala +++ b/server/app/com/xsn/explorer/errors/ipAddressErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models.{FieldValidationError, InputValidationError, PublicError} -import play.api.i18n.{Lang, MessagesApi} trait IPAddressError case object IPAddressFormatError extends IPAddressError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.ipAddress.invalid") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.ipAddress.invalid") val error = FieldValidationError("ip", message) List(error) } diff --git a/server/app/com/xsn/explorer/errors/ledgerErrors.scala b/server/app/com/xsn/explorer/errors/ledgerErrors.scala index 0bf3e2a..6913efc 100644 --- a/server/app/com/xsn/explorer/errors/ledgerErrors.scala +++ b/server/app/com/xsn/explorer/errors/ledgerErrors.scala @@ -1,11 +1,11 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models.{ApplicationError, PublicError} -import play.api.i18n.{Lang, MessagesApi} trait LedgerError extends ApplicationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = List.empty + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = List.empty } case object PreviousBlockMissingError extends LedgerError diff --git a/server/app/com/xsn/explorer/errors/masternodeErrors.scala b/server/app/com/xsn/explorer/errors/masternodeErrors.scala index c5f53e3..b2dcd0d 100644 --- a/server/app/com/xsn/explorer/errors/masternodeErrors.scala +++ b/server/app/com/xsn/explorer/errors/masternodeErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models.{FieldValidationError, NotFoundError, PublicError} -import play.api.i18n.{Lang, MessagesApi} trait MasternodeError case object MasternodeNotFoundError extends MasternodeError with NotFoundError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.masternode.notFound") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.masternode.notFound") val error = FieldValidationError("ip", message) List(error) } diff --git a/server/app/com/xsn/explorer/errors/orderingErrors.scala b/server/app/com/xsn/explorer/errors/orderingErrors.scala index 1ed05fe..72330fc 100644 --- a/server/app/com/xsn/explorer/errors/orderingErrors.scala +++ b/server/app/com/xsn/explorer/errors/orderingErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models.{FieldValidationError, InputValidationError, PublicError} -import play.api.i18n.{Lang, MessagesApi} sealed trait OrderingError case object UnknownOrderingFieldError extends OrderingError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.ordering.unknownField") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.ordering.unknownField") val error = FieldValidationError("orderBy", message) List(error) @@ -17,8 +17,8 @@ case object UnknownOrderingFieldError extends OrderingError with InputValidation case object InvalidOrderingConditionError extends OrderingError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.ordering.unknownCondition") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.ordering.unknownCondition") val error = FieldValidationError("orderBy", message) List(error) @@ -27,8 +27,8 @@ case object InvalidOrderingConditionError extends OrderingError with InputValida case object InvalidOrderingError extends OrderingError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.ordering.invalid") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.ordering.invalid") val error = FieldValidationError("orderBy", message) List(error) diff --git a/server/app/com/xsn/explorer/errors/postgresErrors.scala b/server/app/com/xsn/explorer/errors/postgresErrors.scala index ebf1d9f..3bb4ce1 100644 --- a/server/app/com/xsn/explorer/errors/postgresErrors.scala +++ b/server/app/com/xsn/explorer/errors/postgresErrors.scala @@ -1,10 +1,12 @@ package com.xsn.explorer.errors -import com.alexitc.playsonify.models.ServerError +import com.alexitc.playsonify.models.{ErrorId, ServerError} import org.postgresql.util.PSQLException sealed trait PostgresError extends ServerError { + val id = ErrorId.create + def psqlException: PSQLException override def cause: Option[Throwable] = Option(psqlException) diff --git a/server/app/com/xsn/explorer/errors/transactionErrors.scala b/server/app/com/xsn/explorer/errors/transactionErrors.scala index 42a2364..9c53803 100644 --- a/server/app/com/xsn/explorer/errors/transactionErrors.scala +++ b/server/app/com/xsn/explorer/errors/transactionErrors.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.errors +import com.alexitc.playsonify.core.I18nService import com.alexitc.playsonify.models._ -import play.api.i18n.{Lang, MessagesApi} sealed trait TransactionError case object TransactionFormatError extends TransactionError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.transaction.format") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.transaction.format") val error = FieldValidationError("transactionId", message) List(error) } @@ -16,8 +16,8 @@ case object TransactionFormatError extends TransactionError with InputValidation case object TransactionNotFoundError extends TransactionError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.transaction.notFound") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.transaction.notFound") val error = FieldValidationError("transactionId", message) List(error) } @@ -25,15 +25,17 @@ case object TransactionNotFoundError extends TransactionError with InputValidati case object TransactionUnknownError extends TransactionError with ServerError { + val id = ErrorId.create + override def cause: Option[Throwable] = None - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = List.empty + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = List.empty } case object InvalidRawTransactionError extends TransactionError with InputValidationError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.rawTransaction.invalid") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.rawTransaction.invalid") val error = FieldValidationError("hex", message) List(error) } @@ -41,8 +43,8 @@ case object InvalidRawTransactionError extends TransactionError with InputValida case object RawTransactionAlreadyExistsError extends TransactionError with ConflictError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("error.rawTransaction.repeated") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("error.rawTransaction.repeated") val error = FieldValidationError("hex", message) List(error) } diff --git a/server/app/com/xsn/explorer/errors/xsnErrors.scala b/server/app/com/xsn/explorer/errors/xsnErrors.scala index d3c7e2b..ee1056b 100644 --- a/server/app/com/xsn/explorer/errors/xsnErrors.scala +++ b/server/app/com/xsn/explorer/errors/xsnErrors.scala @@ -1,16 +1,18 @@ package com.xsn.explorer.errors -import com.alexitc.playsonify.models.{GenericPublicError, PublicError, ServerError} -import play.api.i18n.{Lang, MessagesApi} +import com.alexitc.playsonify.core.I18nService +import com.alexitc.playsonify.models.{ErrorId, GenericPublicError, PublicError, ServerError} sealed trait XSNServerError extends ServerError { + val id = ErrorId.create + override def cause: Option[Throwable] = Option.empty } case class XSNMessageError(message: String) extends XSNServerError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { val error = GenericPublicError(message) List(error) } @@ -18,16 +20,16 @@ case class XSNMessageError(message: String) extends XSNServerError { case object XSNUnexpectedResponseError extends XSNServerError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("xsn.server.unexpectedError") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("xsn.server.unexpectedError") val error = GenericPublicError(message) List(error) } } case object XSNWorkQueueDepthExceeded extends XSNServerError { - override def toPublicErrorList(messagesApi: MessagesApi)(implicit lang: Lang): List[PublicError] = { - val message = messagesApi("xsn.server.unexpectedError") + override def toPublicErrorList[L](i18nService: I18nService[L])(implicit lang: L): List[PublicError] = { + val message = i18nService.render("xsn.server.unexpectedError") val error = GenericPublicError(message) List(error) } diff --git a/server/app/com/xsn/explorer/models/Address.scala b/server/app/com/xsn/explorer/models/Address.scala index 8337c61..9c2d96f 100644 --- a/server/app/com/xsn/explorer/models/Address.scala +++ b/server/app/com/xsn/explorer/models/Address.scala @@ -1,8 +1,7 @@ package com.xsn.explorer.models -import javax.xml.bind.DatatypeConverter - import com.alexitc.playsonify.models.WrappedString +import javax.xml.bind.DatatypeConverter import play.api.libs.json._ import scala.util.Try diff --git a/server/app/com/xsn/explorer/models/fields/BalanceField.scala b/server/app/com/xsn/explorer/models/fields/BalanceField.scala index 9090093..3db7e65 100644 --- a/server/app/com/xsn/explorer/models/fields/BalanceField.scala +++ b/server/app/com/xsn/explorer/models/fields/BalanceField.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.models.fields -import com.xsn.explorer.data.anorm.interpreters.ColumnNameResolver +import com.alexitc.playsonify.sql.ColumnNameResolver import enumeratum._ sealed abstract class BalanceField(override val entryName: String) extends EnumEntry diff --git a/server/app/com/xsn/explorer/models/fields/BlockField.scala b/server/app/com/xsn/explorer/models/fields/BlockField.scala index dfcb58d..c045cdb 100644 --- a/server/app/com/xsn/explorer/models/fields/BlockField.scala +++ b/server/app/com/xsn/explorer/models/fields/BlockField.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.models.fields -import com.xsn.explorer.data.anorm.interpreters.ColumnNameResolver +import com.alexitc.playsonify.sql.ColumnNameResolver import enumeratum.{Enum, EnumEntry} sealed abstract class BlockField(override val entryName: String) extends EnumEntry diff --git a/server/app/com/xsn/explorer/models/fields/TransactionField.scala b/server/app/com/xsn/explorer/models/fields/TransactionField.scala index 671fd7c..ca11c3d 100644 --- a/server/app/com/xsn/explorer/models/fields/TransactionField.scala +++ b/server/app/com/xsn/explorer/models/fields/TransactionField.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.models.fields -import com.xsn.explorer.data.anorm.interpreters.ColumnNameResolver +import com.alexitc.playsonify.sql.ColumnNameResolver import enumeratum._ sealed abstract class TransactionField(override val entryName: String) extends EnumEntry diff --git a/server/app/com/xsn/explorer/models/package.scala b/server/app/com/xsn/explorer/models/package.scala new file mode 100644 index 0000000..78fc664 --- /dev/null +++ b/server/app/com/xsn/explorer/models/package.scala @@ -0,0 +1,15 @@ +package com.xsn.explorer + +import _root_.play.api.libs.json.{JsNumber, JsString, Writes} +import com.alexitc.playsonify.models.{WrappedInt, WrappedString} + +package object models { + + implicit val stringWrites: Writes[WrappedString] = Writes { obj => + JsString(obj.string) + } + + implicit val numberWrites: Writes[WrappedInt] = Writes { obj => + JsNumber(obj.int) + } +} diff --git a/server/app/com/xsn/explorer/parsers/BalanceOrderingParser.scala b/server/app/com/xsn/explorer/parsers/BalanceOrderingParser.scala index 1cdc049..2675dae 100644 --- a/server/app/com/xsn/explorer/parsers/BalanceOrderingParser.scala +++ b/server/app/com/xsn/explorer/parsers/BalanceOrderingParser.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.parsers -import com.alexitc.playsonify.models.OrderingCondition +import com.alexitc.playsonify.models.ordering.OrderingCondition import com.alexitc.playsonify.parsers.FieldOrderingParser import com.xsn.explorer.models.fields.BalanceField diff --git a/server/app/com/xsn/explorer/parsers/MasternodeOrderingParser.scala b/server/app/com/xsn/explorer/parsers/MasternodeOrderingParser.scala index 686c98a..7e3f18c 100644 --- a/server/app/com/xsn/explorer/parsers/MasternodeOrderingParser.scala +++ b/server/app/com/xsn/explorer/parsers/MasternodeOrderingParser.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.parsers -import com.alexitc.playsonify.models.OrderingCondition +import com.alexitc.playsonify.models.ordering.OrderingCondition import com.alexitc.playsonify.parsers.FieldOrderingParser import com.xsn.explorer.models.fields.MasternodeField diff --git a/server/app/com/xsn/explorer/parsers/TransactionOrderingParser.scala b/server/app/com/xsn/explorer/parsers/TransactionOrderingParser.scala index 7cf368a..427507a 100644 --- a/server/app/com/xsn/explorer/parsers/TransactionOrderingParser.scala +++ b/server/app/com/xsn/explorer/parsers/TransactionOrderingParser.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.parsers -import com.alexitc.playsonify.models.OrderingCondition +import com.alexitc.playsonify.models.ordering.OrderingCondition import com.alexitc.playsonify.parsers.FieldOrderingParser import com.xsn.explorer.models.fields.TransactionField diff --git a/server/app/com/xsn/explorer/play/MyHttpErrorHandler.scala b/server/app/com/xsn/explorer/play/MyHttpErrorHandler.scala index 11ff514..de2bfed 100644 --- a/server/app/com/xsn/explorer/play/MyHttpErrorHandler.scala +++ b/server/app/com/xsn/explorer/play/MyHttpErrorHandler.scala @@ -1,9 +1,8 @@ package com.xsn.explorer.play +import com.alexitc.playsonify.models.{ErrorId, InternalError, PublicError} +import com.alexitc.playsonify.play.PublicErrorRenderer import javax.inject.Inject - -import com.alexitc.playsonify.PublicErrorRenderer -import com.alexitc.playsonify.models.{ErrorId, PublicError} import org.slf4j.LoggerFactory import play.api.http.HttpErrorHandler import play.api.libs.json.Json @@ -29,7 +28,7 @@ class MyHttpErrorHandler @Inject() (errorRenderer: PublicErrorRenderer) extends def onServerError(request: RequestHeader, exception: Throwable) = { val errorId = ErrorId.create - val error = errorRenderer.renderPrivateError(errorId) + val error = errorRenderer.renderPublicError(InternalError(errorId, "Internal error")) val json = Json.obj( "errors" -> Json.arr(error) ) diff --git a/server/app/com/xsn/explorer/services/BalanceService.scala b/server/app/com/xsn/explorer/services/BalanceService.scala index d8f5981..bdb5446 100644 --- a/server/app/com/xsn/explorer/services/BalanceService.scala +++ b/server/app/com/xsn/explorer/services/BalanceService.scala @@ -1,14 +1,14 @@ package com.xsn.explorer.services -import javax.inject.Inject - import com.alexitc.playsonify.core.FutureOr.Implicits.{FutureOps, OrOps} import com.alexitc.playsonify.core.FuturePaginatedResult -import com.alexitc.playsonify.models.{OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.PaginatedQuery import com.alexitc.playsonify.validators.PaginatedQueryValidator import com.xsn.explorer.data.async.BalanceFutureDataHandler import com.xsn.explorer.models.Balance import com.xsn.explorer.parsers.BalanceOrderingParser +import javax.inject.Inject import scala.concurrent.ExecutionContext diff --git a/server/app/com/xsn/explorer/services/MasternodeService.scala b/server/app/com/xsn/explorer/services/MasternodeService.scala index 0f78458..3f2a279 100644 --- a/server/app/com/xsn/explorer/services/MasternodeService.scala +++ b/server/app/com/xsn/explorer/services/MasternodeService.scala @@ -1,16 +1,16 @@ package com.xsn.explorer.services -import javax.inject.Inject - import com.alexitc.playsonify.core.FutureOr.Implicits.{FutureOps, OrOps} import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} -import com.alexitc.playsonify.models._ +import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition, OrderingQuery} +import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery, PaginatedResult} import com.alexitc.playsonify.validators.PaginatedQueryValidator import com.xsn.explorer.errors.IPAddressFormatError import com.xsn.explorer.models.IPAddress import com.xsn.explorer.models.fields.MasternodeField import com.xsn.explorer.models.rpc.Masternode import com.xsn.explorer.parsers.MasternodeOrderingParser +import javax.inject.Inject import org.scalactic.{Bad, Good} import scala.concurrent.ExecutionContext diff --git a/server/app/com/xsn/explorer/services/TransactionService.scala b/server/app/com/xsn/explorer/services/TransactionService.scala index fa7200c..9922074 100644 --- a/server/app/com/xsn/explorer/services/TransactionService.scala +++ b/server/app/com/xsn/explorer/services/TransactionService.scala @@ -1,15 +1,16 @@ package com.xsn.explorer.services -import javax.inject.Inject import com.alexitc.playsonify.core.FutureOr.Implicits.{FutureListOps, FutureOps, OrOps} import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} -import com.alexitc.playsonify.models.{OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.PaginatedQuery import com.alexitc.playsonify.validators.PaginatedQueryValidator import com.xsn.explorer.data.async.TransactionFutureDataHandler import com.xsn.explorer.errors._ import com.xsn.explorer.models._ import com.xsn.explorer.models.rpc.TransactionVIN import com.xsn.explorer.parsers.TransactionOrderingParser +import javax.inject.Inject import org.scalactic._ import play.api.libs.json.{JsObject, JsString, JsValue} diff --git a/server/app/controllers/AddressesController.scala b/server/app/controllers/AddressesController.scala index 766abc5..adbf371 100644 --- a/server/app/controllers/AddressesController.scala +++ b/server/app/controllers/AddressesController.scala @@ -1,12 +1,12 @@ package controllers -import javax.inject.Inject - -import com.alexitc.playsonify.models.{Limit, Offset, OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} import com.xsn.explorer.models.Transaction import com.xsn.explorer.services.{AddressService, TransactionService} import com.xsn.explorer.util.Extensions.BigDecimalExt -import controllers.common.{MyJsonController, MyJsonControllerComponents} +import controllers.common.{Codecs, MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject import play.api.libs.json._ class AddressesController @Inject() ( @@ -15,11 +15,13 @@ class AddressesController @Inject() ( cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def getBy(address: String) = publicNoInput { _ => + import Codecs._ + + def getBy(address: String) = public { _ => addressService.getBy(address) } - def getTransactions(address: String, offset: Int, limit: Int, ordering: String) = publicNoInput { _ => + def getTransactions(address: String, offset: Int, limit: Int, ordering: String) = public { _ => val paginatedQuery = PaginatedQuery(Offset(offset), Limit(limit)) transactionService.getTransactions(address, paginatedQuery, OrderingQuery(ordering)) @@ -40,7 +42,7 @@ class AddressesController @Inject() ( JsObject.apply(values) } - def getUnspentOutputs(address: String) = publicNoInput { _ => + def getUnspentOutputs(address: String) = public { _ => addressService.getUnspentOutputs(address) } } diff --git a/server/app/controllers/BalancesController.scala b/server/app/controllers/BalancesController.scala index 7c1f9e9..5fed0b0 100644 --- a/server/app/controllers/BalancesController.scala +++ b/server/app/controllers/BalancesController.scala @@ -1,17 +1,19 @@ package controllers -import javax.inject.Inject - -import com.alexitc.playsonify.models.{Limit, Offset, OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} import com.xsn.explorer.services.BalanceService -import controllers.common.{MyJsonController, MyJsonControllerComponents} +import controllers.common.{Codecs, MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject class BalancesController @Inject() ( balanceService: BalanceService, cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def get(offset: Int, limit: Int, ordering: String) = publicNoInput { _ => + import Codecs._ + + def get(offset: Int, limit: Int, ordering: String) = public { _ => val paginatedQuery = PaginatedQuery(Offset(offset), Limit(limit)) val orderingQuery = OrderingQuery(ordering) diff --git a/server/app/controllers/BlocksController.scala b/server/app/controllers/BlocksController.scala index ac2c45b..7dc7e7c 100644 --- a/server/app/controllers/BlocksController.scala +++ b/server/app/controllers/BlocksController.scala @@ -1,11 +1,11 @@ package controllers -import javax.inject.Inject - -import com.alexitc.playsonify.models.{Limit, Offset, OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} import com.xsn.explorer.models.Height import com.xsn.explorer.services.{BlockService, TransactionService} -import controllers.common.{MyJsonController, MyJsonControllerComponents} +import controllers.common.{Codecs, MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject import scala.util.Try @@ -15,7 +15,9 @@ class BlocksController @Inject() ( cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def getLatestBlocks() = publicNoInput { _ => + import Codecs._ + + def getLatestBlocks() = public { _ => blockService.getLatestBlocks() } @@ -24,21 +26,21 @@ class BlocksController @Inject() ( * is not a valid height, we assume it might be a blockhash and try to * retrieve the block by blockhash. */ - def getDetails(query: String) = publicNoInput { _ => + def getDetails(query: String) = public { _ => Try(query.toInt) .map(Height.apply) .map(blockService.getDetails) .getOrElse(blockService.getDetails(query)) } - def getRawBlock(query: String) = publicNoInput { _ => + def getRawBlock(query: String) = public { _ => Try(query.toInt) .map(Height.apply) .map(blockService.getRawBlock) .getOrElse(blockService.getRawBlock(query)) } - def getTransactions(blockhash: String, offset: Int, limit: Int, orderBy: String) = publicNoInput { _ => + def getTransactions(blockhash: String, offset: Int, limit: Int, orderBy: String) = public { _ => val query = PaginatedQuery(Offset(offset), Limit(limit)) val ordering = OrderingQuery(orderBy) transactionService.getByBlockhash(blockhash, query, ordering) diff --git a/server/app/controllers/MasternodesController.scala b/server/app/controllers/MasternodesController.scala index f54dab0..d49ed88 100644 --- a/server/app/controllers/MasternodesController.scala +++ b/server/app/controllers/MasternodesController.scala @@ -1,24 +1,26 @@ package controllers -import javax.inject.Inject - -import com.alexitc.playsonify.models.{Limit, Offset, OrderingQuery, PaginatedQuery} +import com.alexitc.playsonify.models.ordering.OrderingQuery +import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} import com.xsn.explorer.services.MasternodeService -import controllers.common.{MyJsonController, MyJsonControllerComponents} +import controllers.common.{Codecs, MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject class MasternodesController @Inject() ( masternodeService: MasternodeService, cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def get(offset: Int, limit: Int, ordering: String) = publicNoInput { _ => + import Codecs._ + + def get(offset: Int, limit: Int, ordering: String) = public { _ => val paginatedQuery = PaginatedQuery(Offset(offset), Limit(limit)) val orderingQuery = OrderingQuery(ordering) masternodeService.getMasternodes(paginatedQuery, orderingQuery) } - def getBy(ipAddress: String) = publicNoInput { _ => + def getBy(ipAddress: String) = public { _ => masternodeService.getMasternode(ipAddress) } } diff --git a/server/app/controllers/StatisticsController.scala b/server/app/controllers/StatisticsController.scala index 7ac9923..70ac2f5 100644 --- a/server/app/controllers/StatisticsController.scala +++ b/server/app/controllers/StatisticsController.scala @@ -1,16 +1,15 @@ package controllers -import javax.inject.Inject - import com.xsn.explorer.services.StatisticsService import controllers.common.{MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject class StatisticsController @Inject() ( statisticsService: StatisticsService, cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def getStatus() = publicNoInput { _ => + def getStatus() = public { _ => statisticsService.getStatistics() } } diff --git a/server/app/controllers/TransactionsController.scala b/server/app/controllers/TransactionsController.scala index acd7f54..5f9110d 100644 --- a/server/app/controllers/TransactionsController.scala +++ b/server/app/controllers/TransactionsController.scala @@ -1,30 +1,30 @@ package controllers -import javax.inject.Inject - -import com.alexitc.playsonify.models.PublicContextWithModel import com.xsn.explorer.models.request.{GetLatestTransactionRequest, SendRawTransactionRequest} import com.xsn.explorer.services.TransactionService import controllers.common.{MyJsonController, MyJsonControllerComponents} +import javax.inject.Inject class TransactionsController @Inject() ( transactionService: TransactionService, cc: MyJsonControllerComponents) extends MyJsonController(cc) { - def getTransaction(txid: String) = publicNoInput { _ => + import Context._ + + def getTransaction(txid: String) = public { _ => transactionService.getTransactionDetails(txid) } - def getRawTransaction(txid: String) = publicNoInput { _ => + def getRawTransaction(txid: String) = public { _ => transactionService.getRawTransaction(txid) } - def sendRawTransaction() = publicWithInput { ctx: PublicContextWithModel[SendRawTransactionRequest] => + def sendRawTransaction() = publicInput { ctx: HasModel[SendRawTransactionRequest] => transactionService.sendRawTransaction(ctx.model.hex) } - def getLatestByAddresses() = publicWithInput { ctx: PublicContextWithModel[GetLatestTransactionRequest] => + def getLatestByAddresses() = publicInput { ctx: HasModel[GetLatestTransactionRequest] => transactionService.getLatestTransactionBy(ctx.model.addresses) } } diff --git a/server/app/controllers/common/Codecs.scala b/server/app/controllers/common/Codecs.scala index 4346198..d872689 100644 --- a/server/app/controllers/common/Codecs.scala +++ b/server/app/controllers/common/Codecs.scala @@ -1,10 +1,13 @@ package controllers.common +import com.alexitc.playsonify.models.pagination.PaginatedResult +import com.xsn.explorer.models._ import org.scalactic.Every import play.api.libs.json._ object Codecs { + implicit def everyReads[T](implicit readsT: Reads[T]): Reads[Every[T]] = Reads[Every[T]] { json => json .validate[List[T]] @@ -16,4 +19,14 @@ object Codecs { } } } + + + implicit def paginatedResultWrites[T](implicit writesT: Writes[T]): Writes[PaginatedResult[T]] = OWrites[PaginatedResult[T]] { result => + Json.obj( + "offset" -> result.offset, + "limit" -> result.limit, + "total" -> result.total, + "data" -> result.data + ) + } } \ No newline at end of file diff --git a/server/app/controllers/common/MyAuthenticatorService.scala b/server/app/controllers/common/MyAuthenticatorService.scala index 37a4e98..10c4dba 100644 --- a/server/app/controllers/common/MyAuthenticatorService.scala +++ b/server/app/controllers/common/MyAuthenticatorService.scala @@ -1,7 +1,7 @@ package controllers.common -import com.alexitc.playsonify.AbstractAuthenticatorService import com.alexitc.playsonify.core.FutureApplicationResult +import com.alexitc.playsonify.play.AbstractAuthenticatorService import org.scalactic.Good import play.api.libs.json.JsValue import play.api.mvc.Request @@ -11,6 +11,6 @@ import scala.concurrent.Future class MyAuthenticatorService extends AbstractAuthenticatorService[Nothing] { override def authenticate(request: Request[JsValue]): FutureApplicationResult[Nothing] = { - Future.successful(Good(???)) + Future.successful(Good(throw new RuntimeException("Not implemented"))) } } diff --git a/server/app/controllers/common/MyJsonController.scala b/server/app/controllers/common/MyJsonController.scala index bcdf3d3..ae97442 100644 --- a/server/app/controllers/common/MyJsonController.scala +++ b/server/app/controllers/common/MyJsonController.scala @@ -1,25 +1,20 @@ package controllers.common -import com.alexitc.playsonify.AbstractJsonController -import com.alexitc.playsonify.models.{ErrorId, ServerError} +import com.alexitc.playsonify.models.ServerError +import com.alexitc.playsonify.play.AbstractJsonController import org.slf4j.LoggerFactory abstract class MyJsonController(cc: MyJsonControllerComponents) extends AbstractJsonController[Nothing](cc) { protected val logger = LoggerFactory.getLogger(this.getClass) - override def onServerError(error: ServerError, errorId: ErrorId): Unit = { - val message = s"Unexpected server error, id = ${errorId.string}, error = $error" + override protected def onServerError(error: ServerError): Unit = { + error.cause match { + case Some(cause) => + logger.error(s"Unexpected internal error, id = ${error.id.string}, error = $error", cause) - error - .cause - .orElse { - logger.warn(message) - None - } - .foreach { cause => - // we'll log as error when there is an exception involved - logger.error(message, cause) - } + case None => + logger.error(s"Unexpected internal error, id = ${error.id.string}, error = $error}") + } } } diff --git a/server/app/controllers/common/MyJsonControllerComponents.scala b/server/app/controllers/common/MyJsonControllerComponents.scala index 4d48efa..e08659a 100644 --- a/server/app/controllers/common/MyJsonControllerComponents.scala +++ b/server/app/controllers/common/MyJsonControllerComponents.scala @@ -1,8 +1,7 @@ package controllers.common +import com.alexitc.playsonify.play.{I18nPlayService, JsonControllerComponents, PublicErrorRenderer} import javax.inject.Inject - -import com.alexitc.playsonify.{JsonControllerComponents, PublicErrorRenderer} import play.api.mvc.MessagesControllerComponents import scala.concurrent.ExecutionContext @@ -11,5 +10,6 @@ class MyJsonControllerComponents @Inject() ( override val messagesControllerComponents: MessagesControllerComponents, override val executionContext: ExecutionContext, override val publicErrorRenderer: PublicErrorRenderer, + override val i18nService: I18nPlayService, override val authenticatorService: MyAuthenticatorService) extends JsonControllerComponents[Nothing] diff --git a/server/build.sbt b/server/build.sbt index af67b96..a5095f0 100644 --- a/server/build.sbt +++ b/server/build.sbt @@ -22,7 +22,7 @@ scalacOptions ++= Seq( ) -val playsonifyVersion = "1.2.0" +val playsonifyVersion = "2.0.0" lazy val root = (project in file(".")) .enablePlugins(PlayScala) @@ -32,7 +32,13 @@ coverageExcludedPackages := ";Reverse.*;router\\.*" libraryDependencies ++= Seq(guice, evolutions, jdbc, ws) -libraryDependencies += "com.alexitc" %% "playsonify" % playsonifyVersion +libraryDependencies ++= Seq( + "com.alexitc" %% "playsonify-core" % playsonifyVersion, + "com.alexitc" %% "playsonify-play" % playsonifyVersion, + "com.alexitc" %% "playsonify-sql" % playsonifyVersion, + "com.alexitc" %% "playsonify-play-test" % playsonifyVersion % Test +) + libraryDependencies += "com.google.inject" % "guice" % "4.1.0" libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.4" libraryDependencies += "org.playframework.anorm" %% "anorm" % "2.6.1" @@ -48,7 +54,6 @@ libraryDependencies ++= Seq( ) libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.0" % Test -libraryDependencies += "com.alexitc" %% "playsonifytest" % playsonifyVersion % Test libraryDependencies += "org.mockito" % "mockito-core" % "2.15.0" % Test libraryDependencies ++= Seq( diff --git a/server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala index 1fa413b..f584c9f 100644 --- a/server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/BalancePostgresDataHandlerSpec.scala @@ -1,9 +1,10 @@ package com.xsn.explorer.data -import com.alexitc.playsonify.models._ +import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition} +import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.BalancePostgresDataHandler import com.xsn.explorer.data.anorm.dao.BalancePostgresDAO -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.common.PostgresDataHandlerSpec import com.xsn.explorer.helpers.DataHelper import com.xsn.explorer.models.Balance diff --git a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala index 574e74e..43ebdec 100644 --- a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala @@ -1,9 +1,10 @@ package com.xsn.explorer.data -import com.alexitc.playsonify.models._ +import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition} +import com.alexitc.playsonify.models.pagination.{Count, Limit, Offset, PaginatedQuery} +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.BlockPostgresDataHandler import com.xsn.explorer.data.anorm.dao.BlockPostgresDAO -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.common.PostgresDataHandlerSpec import com.xsn.explorer.errors.BlockNotFoundError import com.xsn.explorer.helpers.BlockLoader diff --git a/server/test/com/xsn/explorer/data/LedgerPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/LedgerPostgresDataHandlerSpec.scala index 9e82608..d05b429 100644 --- a/server/test/com/xsn/explorer/data/LedgerPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/LedgerPostgresDataHandlerSpec.scala @@ -1,8 +1,8 @@ package com.xsn.explorer.data +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.LedgerPostgresDataHandler import com.xsn.explorer.data.anorm.dao.{BalancePostgresDAO, BlockPostgresDAO, TransactionPostgresDAO} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.common.PostgresDataHandlerSpec import com.xsn.explorer.errors.{PreviousBlockMissingError, RepeatedBlockHeightError} import com.xsn.explorer.helpers.{BlockLoader, TransactionLoader} diff --git a/server/test/com/xsn/explorer/data/StatisticsPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/StatisticsPostgresDataHandlerSpec.scala index 3d69c0e..6d49661 100644 --- a/server/test/com/xsn/explorer/data/StatisticsPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/StatisticsPostgresDataHandlerSpec.scala @@ -1,7 +1,7 @@ package com.xsn.explorer.data +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.dao.{BalancePostgresDAO, StatisticsPostgresDAO} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.{BalancePostgresDataHandler, StatisticsPostgresDataHandler} import com.xsn.explorer.data.common.PostgresDataHandlerSpec import com.xsn.explorer.helpers.DataHelper diff --git a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala index b0e2b71..e8f4f57 100644 --- a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala @@ -1,8 +1,9 @@ package com.xsn.explorer.data -import com.alexitc.playsonify.models._ +import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition} +import com.alexitc.playsonify.models.pagination._ +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.dao.{BalancePostgresDAO, BlockPostgresDAO, TransactionPostgresDAO} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.{BlockPostgresDataHandler, LedgerPostgresDataHandler, TransactionPostgresDataHandler} import com.xsn.explorer.data.common.PostgresDataHandlerSpec import com.xsn.explorer.errors.{BlockNotFoundError, TransactionNotFoundError} diff --git a/server/test/com/xsn/explorer/helpers/BalanceDummyDataHandler.scala b/server/test/com/xsn/explorer/helpers/BalanceDummyDataHandler.scala index a29341c..866a2ac 100644 --- a/server/test/com/xsn/explorer/helpers/BalanceDummyDataHandler.scala +++ b/server/test/com/xsn/explorer/helpers/BalanceDummyDataHandler.scala @@ -1,7 +1,8 @@ package com.xsn.explorer.helpers import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.BalanceBlockingDataHandler import com.xsn.explorer.models.fields.BalanceField import com.xsn.explorer.models.{Address, Balance} diff --git a/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala b/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala index 8d8b6c2..3a5b0a4 100644 --- a/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala +++ b/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala @@ -1,7 +1,8 @@ package com.xsn.explorer.helpers import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField diff --git a/server/test/com/xsn/explorer/services/LedgerSynchronizerServiceSpec.scala b/server/test/com/xsn/explorer/services/LedgerSynchronizerServiceSpec.scala index feaa755..9f23769 100644 --- a/server/test/com/xsn/explorer/services/LedgerSynchronizerServiceSpec.scala +++ b/server/test/com/xsn/explorer/services/LedgerSynchronizerServiceSpec.scala @@ -1,9 +1,9 @@ package com.xsn.explorer.services import com.alexitc.playsonify.core.FutureApplicationResult +import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.alexitc.playsonify.validators.PaginatedQueryValidator import com.xsn.explorer.data.anorm.dao.{BalancePostgresDAO, BlockPostgresDAO, TransactionPostgresDAO} -import com.xsn.explorer.data.anorm.interpreters.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.{BlockPostgresDataHandler, LedgerPostgresDataHandler, TransactionPostgresDataHandler} import com.xsn.explorer.data.async.{BlockFutureDataHandler, LedgerFutureDataHandler, TransactionFutureDataHandler} import com.xsn.explorer.data.common.PostgresDataHandlerSpec diff --git a/server/test/controllers/AddressesControllerSpec.scala b/server/test/controllers/AddressesControllerSpec.scala index 39d4126..10d4a23 100644 --- a/server/test/controllers/AddressesControllerSpec.scala +++ b/server/test/controllers/AddressesControllerSpec.scala @@ -1,8 +1,9 @@ package controllers -import com.alexitc.playsonify.PublicErrorRenderer import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models.{Count, FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.play.PublicErrorRenderer import com.xsn.explorer.data.{BalanceBlockingDataHandler, TransactionBlockingDataHandler} import com.xsn.explorer.helpers.{BalanceDummyDataHandler, DataHelper, TransactionDummyDataHandler} import com.xsn.explorer.models._ diff --git a/server/test/controllers/BalancesControllerSpec.scala b/server/test/controllers/BalancesControllerSpec.scala index 3c7abf4..b59b675 100644 --- a/server/test/controllers/BalancesControllerSpec.scala +++ b/server/test/controllers/BalancesControllerSpec.scala @@ -1,7 +1,8 @@ package controllers import com.alexitc.playsonify.core.ApplicationResult -import com.alexitc.playsonify.models._ +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination._ import com.xsn.explorer.data.BalanceBlockingDataHandler import com.xsn.explorer.helpers.DataHelper import com.xsn.explorer.models.fields.BalanceField diff --git a/server/test/controllers/BlocksControllerSpec.scala b/server/test/controllers/BlocksControllerSpec.scala index b0bcaa2..ef300a1 100644 --- a/server/test/controllers/BlocksControllerSpec.scala +++ b/server/test/controllers/BlocksControllerSpec.scala @@ -1,8 +1,9 @@ package controllers -import com.alexitc.playsonify.PublicErrorRenderer import com.alexitc.playsonify.core.{ApplicationResult, FutureApplicationResult} -import com.alexitc.playsonify.models.{Count, FieldOrdering, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.play.PublicErrorRenderer import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.errors.{BlockNotFoundError, TransactionNotFoundError} import com.xsn.explorer.helpers.{BlockLoader, DummyXSNService, TransactionDummyDataHandler, TransactionLoader} diff --git a/server/test/controllers/MasternodesControllerSpec.scala b/server/test/controllers/MasternodesControllerSpec.scala index a476d64..88037dc 100644 --- a/server/test/controllers/MasternodesControllerSpec.scala +++ b/server/test/controllers/MasternodesControllerSpec.scala @@ -1,7 +1,7 @@ package controllers -import com.alexitc.playsonify.PublicErrorRenderer import com.alexitc.playsonify.core.FutureApplicationResult +import com.alexitc.playsonify.play.PublicErrorRenderer import com.xsn.explorer.errors.MasternodeNotFoundError import com.xsn.explorer.helpers.DummyXSNService import com.xsn.explorer.models.rpc.Masternode diff --git a/server/test/controllers/TransactionsControllerSpec.scala b/server/test/controllers/TransactionsControllerSpec.scala index a90a3cc..4be9abd 100644 --- a/server/test/controllers/TransactionsControllerSpec.scala +++ b/server/test/controllers/TransactionsControllerSpec.scala @@ -1,7 +1,7 @@ package controllers -import com.alexitc.playsonify.PublicErrorRenderer import com.alexitc.playsonify.core.{ApplicationResult, FutureApplicationResult} +import com.alexitc.playsonify.play.PublicErrorRenderer import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.errors.TransactionNotFoundError import com.xsn.explorer.helpers.{DataHelper, DummyXSNService, TransactionDummyDataHandler, TransactionLoader}