Browse Source

server: Add the number of masternodes to the statistics endpoint

scalafmt-draft
Alexis Hernandez 7 years ago
parent
commit
3f60fe7611
  1. 26
      server/app/com/xsn/explorer/models/StatisticsDetails.scala
  2. 20
      server/app/com/xsn/explorer/services/StatisticsService.scala
  3. 23
      server/app/com/xsn/explorer/services/XSNService.scala
  4. 1
      server/test/com/xsn/explorer/helpers/DummyXSNService.scala
  5. 14
      server/test/controllers/StatisticsControllerSpec.scala

26
server/app/com/xsn/explorer/models/StatisticsDetails.scala

@ -0,0 +1,26 @@
package com.xsn.explorer.models
import play.api.libs.json._
case class StatisticsDetails(statistics: Statistics, masternodes: Option[Int])
object StatisticsDetails {
implicit val writes: Writes[StatisticsDetails] = Writes { obj =>
val values = Map(
"blocks" -> JsNumber(obj.statistics.blocks),
"transactions" -> JsNumber(obj.statistics.transactions),
"totalSupply" -> JsNumber(obj.statistics.totalSupply),
"circulatingSupply" -> JsNumber(obj.statistics.circulatingSupply))
val result = obj.masternodes
.map { count =>
values + ("masternodes" -> JsNumber(count))
}
.getOrElse {
values
}
JsObject.apply(result)
}
}

20
server/app/com/xsn/explorer/services/StatisticsService.scala

@ -3,16 +3,30 @@ package com.xsn.explorer.services
import javax.inject.Inject
import com.alexitc.playsonify.core.FutureApplicationResult
import com.alexitc.playsonify.core.FutureOr.Implicits.FutureOps
import com.xsn.explorer.data.async.StatisticsFutureDataHandler
import com.xsn.explorer.models.Statistics
import com.xsn.explorer.models.StatisticsDetails
import org.scalactic.{Bad, Good}
import scala.concurrent.ExecutionContext
class StatisticsService @Inject() (
xsnService: XSNService,
statisticsFutureDataHandler: StatisticsFutureDataHandler)(
implicit ec: ExecutionContext) {
def getStatistics(): FutureApplicationResult[Statistics] = {
statisticsFutureDataHandler.getStatistics()
def getStatistics(): FutureApplicationResult[StatisticsDetails] = {
val dbStats = statisticsFutureDataHandler.getStatistics()
val rpcStats = xsnService.getMasternodeCount()
val result = for {
stats <- dbStats.toFutureOr
count <- rpcStats.map {
case Good(count) => Good(Some(count))
case Bad(_) => Good(None)
}.toFutureOr
} yield StatisticsDetails(stats, count)
result.toFuture
}
}

23
server/app/com/xsn/explorer/services/XSNService.scala

@ -30,6 +30,8 @@ trait XSNService {
def getLatestBlock(): FutureApplicationResult[Block]
def getServerStatistics(): FutureApplicationResult[ServerStatistics]
def getMasternodeCount(): FutureApplicationResult[Int]
}
class XSNServiceRPCImpl @Inject() (
@ -182,6 +184,27 @@ class XSNServiceRPCImpl @Inject() (
}
}
override def getMasternodeCount(): FutureApplicationResult[Int] = {
val body = s"""
|{
| "jsonrpc": "1.0",
| "method": "masternode",
| "params": ["count"]
|}
|""".stripMargin
server
.post(body)
.map { response =>
val maybe = getResult[Int](response)
maybe.getOrElse {
logger.warn(s"Unexpected response from XSN Server, status = ${response.status}, response = ${response.body}")
Bad(XSNUnexpectedResponseError).accumulating
}
}
}
private def mapError(json: JsValue, errorCodeMapper: Map[Int, ApplicationError]): Option[ApplicationError] = {
val jsonErrorMaybe = (json \ "error")
.asOpt[JsValue]

1
server/test/com/xsn/explorer/helpers/DummyXSNService.scala

@ -13,4 +13,5 @@ class DummyXSNService extends XSNService {
override def getBlock(blockhash: Blockhash): FutureApplicationResult[Block] = ???
override def getLatestBlock(): FutureApplicationResult[Block] = ???
override def getServerStatistics(): FutureApplicationResult[ServerStatistics] = ???
override def getMasternodeCount(): FutureApplicationResult[Int] = ???
}

14
server/test/controllers/StatisticsControllerSpec.scala

@ -1,13 +1,17 @@
package controllers
import com.alexitc.playsonify.core.ApplicationResult
import com.alexitc.playsonify.core.{ApplicationResult, FutureApplicationResult}
import com.xsn.explorer.data.StatisticsBlockingDataHandler
import com.xsn.explorer.helpers.DummyXSNService
import com.xsn.explorer.models.Statistics
import com.xsn.explorer.services.XSNService
import controllers.common.MyAPISpec
import org.scalactic.Good
import play.api.inject.bind
import play.api.test.Helpers._
import scala.concurrent.Future
class StatisticsControllerSpec extends MyAPISpec {
val stats = Statistics(
@ -20,8 +24,15 @@ class StatisticsControllerSpec extends MyAPISpec {
override def getStatistics(): ApplicationResult[Statistics] = Good(stats)
}
val xsnService = new DummyXSNService {
override def getMasternodeCount(): FutureApplicationResult[Int] = {
Future.successful(Good(1000))
}
}
override val application = guiceApplicationBuilder
.overrides(bind[StatisticsBlockingDataHandler].to(dataHandler))
.overrides(bind[XSNService].to(xsnService))
.build()
"GET /stats" should {
@ -34,6 +45,7 @@ class StatisticsControllerSpec extends MyAPISpec {
(json \ "transactions").as[Int] mustEqual stats.transactions
(json \ "totalSupply").as[BigDecimal] mustEqual stats.totalSupply
(json \ "circulatingSupply").as[BigDecimal] mustEqual stats.circulatingSupply
(json \ "masternodes").as[Int] mustEqual 1000
}
}
}

Loading…
Cancel
Save