Browse Source

server: Add isTPoSContract method to the XSNService

The method verifies whether a transaction is a TPoS contract.
master
Alexis Hernandez 6 years ago
parent
commit
bdbaa415b5
  1. 30
      server/app/com/xsn/explorer/services/XSNService.scala
  2. 1
      server/test/com/xsn/explorer/helpers/DummyXSNService.scala
  3. 42
      server/test/com/xsn/explorer/services/XSNServiceRPCImplSpec.scala

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

@ -11,7 +11,7 @@ import com.xsn.explorer.models.values._
import javax.inject.Inject
import org.scalactic.{Bad, Good}
import org.slf4j.LoggerFactory
import play.api.libs.json.{JsNull, JsValue, Reads}
import play.api.libs.json._
import play.api.libs.ws.{WSAuthScheme, WSClient, WSResponse}
import scala.util.Try
@ -48,6 +48,8 @@ trait XSNService {
def sendRawTransaction(hex: HexString): FutureApplicationResult[String]
def isTPoSContract(txid: TransactionId): FutureApplicationResult[Boolean]
def cleanGenesisBlock(block: rpc.Block): rpc.Block = {
Option(block)
.filter(_.hash == genesisBlockhash)
@ -421,6 +423,32 @@ class XSNServiceRPCImpl @Inject() (
}
}
override def isTPoSContract(txid: TransactionId): FutureApplicationResult[Boolean] = {
val innerBody = Json.obj("txid" -> txid.string, "check_spent" -> 0)
val body = Json.obj(
"jsonrpc" -> "1.0",
"method" -> "tposcontract",
"params" -> List(
JsString("validate"),
JsString(innerBody.toString())
)
)
server
.post(body)
.map { response =>
val maybe = getResult[String](response)
.map { _.map(_ == "Contract is valid") }
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

@ -25,4 +25,5 @@ class DummyXSNService extends XSNService {
override def getMasternode(ipAddress: IPAddress): FutureApplicationResult[Masternode] = ???
override def getUnspentOutputs(address: Address): FutureApplicationResult[JsValue] = ???
override def sendRawTransaction(hex: HexString): FutureApplicationResult[String] = ???
override def isTPoSContract(txid: TransactionId): FutureApplicationResult[Boolean] = ???
}

42
server/test/com/xsn/explorer/services/XSNServiceRPCImplSpec.scala

@ -3,23 +3,23 @@ package com.xsn.explorer.services
import com.xsn.explorer.config.{ExplorerConfig, RPCConfig}
import com.xsn.explorer.errors._
import com.xsn.explorer.helpers.{BlockLoader, DataHelper, Executors, TransactionLoader}
import com.xsn.explorer.models._
import com.xsn.explorer.models.rpc.Masternode
import com.xsn.explorer.models.values._
import org.mockito.ArgumentMatchers._
import org.mockito.Mockito._
import org.mockito.Mockito.{mock => _, _}
import org.scalactic.{Bad, Good}
import org.scalatest.MustMatchers._
import org.scalatest.WordSpec
import org.scalatest.concurrent.PatienceConfiguration.Timeout
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.mockito.MockitoSugar
import org.scalatest.concurrent.ScalaFutures._
import org.scalatest.mockito.MockitoSugar._
import org.scalatest.time.{Seconds, Span}
import org.scalatest.{MustMatchers, OptionValues, WordSpec}
import play.api.libs.json.{JsNull, JsString, JsValue, Json}
import play.api.libs.ws.{WSClient, WSRequest, WSResponse}
import scala.concurrent.Future
class XSNServiceRPCImplSpec extends WordSpec with MustMatchers with ScalaFutures with MockitoSugar with OptionValues {
class XSNServiceRPCImplSpec extends WordSpec {
import DataHelper._
@ -601,11 +601,39 @@ class XSNServiceRPCImplSpec extends WordSpec with MustMatchers with ScalaFutures
}
}
"isTPoSContract" should {
"return true when the contract is valid" in {
val txid = createTransactionId("b02f99d87194c9400ab147c070bf621770684906dedfbbe9ba5f3a35c26b8d01")
val content = "Contract is valid"
val responseBody = createRPCSuccessfulResponse(JsString(content))
val json = Json.parse(responseBody)
mockRequest(request, response)(200, json)
whenReady(service.isTPoSContract(txid)) { result =>
result mustEqual Good(true)
}
}
"return false when the contract is not valid" in {
val txid = createTransactionId("b02f99d87194c9400ab147c070bf621770684906dedfbbe9ba5f3a35c26b8d01")
val content = "Contract invalid, error: Signature invalid"
val responseBody = createRPCSuccessfulResponse(JsString(content))
val json = Json.parse(responseBody)
mockRequest(request, response)(200, json)
whenReady(service.isTPoSContract(txid)) { result =>
result mustEqual Good(false)
}
}
}
private def mockRequest(request: WSRequest, response: WSResponse)(status: Int, body: JsValue) = {
when(response.status).thenReturn(status)
when(response.json).thenReturn(body)
when(response.body).thenReturn(body.toString())
when(request.post[String](anyString())(any())).thenReturn(Future.successful(response))
when(request.post[AnyRef](any())(any())).thenReturn(Future.successful(response))
}
private def mockRequestString(request: WSRequest, response: WSResponse)(status: Int, body: String) = {

Loading…
Cancel
Save