From 0f04494d65ab5f0b3e61d1797e3ceec4314f2f83 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sun, 31 Mar 2019 15:00:20 -0700 Subject: [PATCH] server: Add endpoint "GET /addresses/:address/tposcontracts" --- .../xsn/explorer/models/TPoSContract.scala | 13 ++++++++++ .../services/TPoSContractService.scala | 25 +++++++++++++++++++ .../validators/AddressValidator.scala | 14 +++++++++++ .../app/controllers/AddressesController.scala | 7 +++++- server/conf/routes | 1 + 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 server/app/com/xsn/explorer/services/TPoSContractService.scala create mode 100644 server/app/com/xsn/explorer/services/validators/AddressValidator.scala diff --git a/server/app/com/xsn/explorer/models/TPoSContract.scala b/server/app/com/xsn/explorer/models/TPoSContract.scala index ae8f0024..292b0fd3 100644 --- a/server/app/com/xsn/explorer/models/TPoSContract.scala +++ b/server/app/com/xsn/explorer/models/TPoSContract.scala @@ -2,6 +2,7 @@ package com.xsn.explorer.models import com.xsn.explorer.models.values.{Address, TransactionId} import enumeratum._ +import play.api.libs.json.{Json, Writes} import scala.util.Try @@ -65,4 +66,16 @@ object TPoSContract { final case object Active extends State("ACTIVE") final case object Closed extends State("CLOSED") } + + implicit val writes: Writes[TPoSContract] = (obj: TPoSContract) => { + Json.obj( + "txid" -> obj.id.txid, + "index" -> obj.id.index, + "owner" -> obj.details.owner, + "merchant" -> obj.details.merchant, + "merchantCommission" -> obj.details.merchantCommission.int, + "time" -> obj.time, + "state" -> obj.state.entryName + ) + } } diff --git a/server/app/com/xsn/explorer/services/TPoSContractService.scala b/server/app/com/xsn/explorer/services/TPoSContractService.scala new file mode 100644 index 00000000..38f3d33d --- /dev/null +++ b/server/app/com/xsn/explorer/services/TPoSContractService.scala @@ -0,0 +1,25 @@ +package com.xsn.explorer.services + +import com.alexitc.playsonify.core.FutureApplicationResult +import com.alexitc.playsonify.core.FutureOr.Implicits.{FutureOps, OrOps} +import com.xsn.explorer.data.async.TPoSContractFutureDataHandler +import com.xsn.explorer.models.{TPoSContract, WrappedResult} +import com.xsn.explorer.services.validators.AddressValidator +import javax.inject.Inject + +import scala.concurrent.ExecutionContext + +class TPoSContractService @Inject() ( + addressValidator: AddressValidator, + tposContractFutureDataHandler: TPoSContractFutureDataHandler)( + implicit ec: ExecutionContext) { + + def getBy(addressString: String): FutureApplicationResult[WrappedResult[List[TPoSContract]]] = { + val result = for { + address <- addressValidator.validate(addressString).toFutureOr + contracts <- tposContractFutureDataHandler.getBy(address).toFutureOr + } yield WrappedResult(contracts) + + result.toFuture + } +} diff --git a/server/app/com/xsn/explorer/services/validators/AddressValidator.scala b/server/app/com/xsn/explorer/services/validators/AddressValidator.scala new file mode 100644 index 00000000..2c43c7f6 --- /dev/null +++ b/server/app/com/xsn/explorer/services/validators/AddressValidator.scala @@ -0,0 +1,14 @@ +package com.xsn.explorer.services.validators + +import com.alexitc.playsonify.core.ApplicationResult +import com.xsn.explorer.errors.AddressFormatError +import com.xsn.explorer.models.values.Address +import org.scalactic.{One, Or} + +class AddressValidator { + + def validate(string: String): ApplicationResult[Address] = { + val maybe = Address.from(string) + Or.from(maybe, One(AddressFormatError)) + } +} diff --git a/server/app/controllers/AddressesController.scala b/server/app/controllers/AddressesController.scala index 43e78ed4..bb6c6c63 100644 --- a/server/app/controllers/AddressesController.scala +++ b/server/app/controllers/AddressesController.scala @@ -4,7 +4,7 @@ import com.alexitc.playsonify.models.ordering.OrderingQuery import com.alexitc.playsonify.models.pagination.{Limit, Offset, PaginatedQuery} import com.xsn.explorer.models.LightWalletTransaction import com.xsn.explorer.models.persisted.Transaction -import com.xsn.explorer.services.{AddressService, TransactionService} +import com.xsn.explorer.services.{AddressService, TPoSContractService, TransactionService} import com.xsn.explorer.util.Extensions.BigDecimalExt import controllers.common.{Codecs, MyJsonController, MyJsonControllerComponents} import javax.inject.Inject @@ -13,6 +13,7 @@ import play.api.libs.json._ class AddressesController @Inject() ( addressService: AddressService, transactionService: TransactionService, + tposContractService: TPoSContractService, cc: MyJsonControllerComponents) extends MyJsonController(cc) { @@ -60,6 +61,10 @@ class AddressesController @Inject() ( def getUnspentOutputs(address: String) = public { _ => addressService.getUnspentOutputs(address) } + + def getTPoSContracts(address: String) = public { _ => + tposContractService.getBy(address) + } } object AddressesController { diff --git a/server/conf/routes b/server/conf/routes index 150a8935..28ccbaaa 100644 --- a/server/conf/routes +++ b/server/conf/routes @@ -12,6 +12,7 @@ POST /transactions controllers.TransactionsController.sendRawTrans GET /addresses/:address controllers.AddressesController.getBy(address: String) GET /addresses/:address/transactions controllers.AddressesController.getTransactions(address: String, offset: Int ?= 0, limit: Int ?= 10, orderBy: String ?= "") +GET /addresses/:address/tposcontracts controllers.AddressesController.getTPoSContracts(address: String) GET /v2/addresses/:address/transactions controllers.AddressesController.getLightWalletTransactions(address: String, limit: Int ?= 10, lastSeenTxid: Option[String], order: String ?= "desc") GET /addresses/:address/utxos controllers.AddressesController.getUnspentOutputs(address: String)