Browse Source

server: Retrieve transaction list while retrieving an address

scalafmt-draft
Alexis Hernandez 7 years ago
parent
commit
5094bb35e4
  1. 5
      server/app/com/xsn/explorer/models/AddressDetails.scala
  2. 4
      server/app/com/xsn/explorer/services/AddressService.scala
  3. 8
      server/app/com/xsn/explorer/services/XSNService.scala
  4. 8
      server/test/com/xsn/explorer/helpers/DataHelper.scala
  5. 2
      server/test/com/xsn/explorer/helpers/DummyXSNService.scala
  6. 13
      server/test/com/xsn/explorer/services/XSNServiceRPCImplSpec.scala
  7. 24
      server/test/controllers/AddressesControllerSpec.scala

5
server/app/com/xsn/explorer/models/AddressDetails.scala

@ -3,15 +3,16 @@ package com.xsn.explorer.models
import com.xsn.explorer.models.rpc.AddressBalance import com.xsn.explorer.models.rpc.AddressBalance
import play.api.libs.json._ import play.api.libs.json._
case class AddressDetails(balance: AddressBalance, transactionCount: Int) case class AddressDetails(balance: AddressBalance, transactions: List[TransactionId])
object AddressDetails { object AddressDetails {
implicit val writes: Writes[AddressDetails] = Writes { obj => implicit val writes: Writes[AddressDetails] = Writes { obj =>
val transactions = obj.transactions.map { txid => Json.toJson(txid) }
val values = Map( val values = Map(
"balance" -> JsNumber(obj.balance.balance), "balance" -> JsNumber(obj.balance.balance),
"received" -> JsNumber(obj.balance.received), "received" -> JsNumber(obj.balance.received),
"transactionCount" -> JsNumber(obj.transactionCount)) "transactions" -> JsArray(transactions))
JsObject.apply(values) JsObject.apply(values)
} }

4
server/app/com/xsn/explorer/services/AddressService.scala

@ -20,8 +20,8 @@ class AddressService @Inject() (xsnService: XSNService)(implicit ec: ExecutionCo
} }
balance <- xsnService.getAddressBalance(address).toFutureOr balance <- xsnService.getAddressBalance(address).toFutureOr
transactionCount <- xsnService.getTransactionCount(address).toFutureOr transactions <- xsnService.getTransactions(address).toFutureOr
} yield AddressDetails(balance, transactionCount) } yield AddressDetails(balance, transactions)
result.toFuture result.toFuture
} }

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

@ -22,7 +22,7 @@ trait XSNService {
def getAddressBalance(address: Address): FutureApplicationResult[AddressBalance] def getAddressBalance(address: Address): FutureApplicationResult[AddressBalance]
def getTransactionCount(address: Address): FutureApplicationResult[Int] def getTransactions(address: Address): FutureApplicationResult[List[TransactionId]]
def getBlock(blockhash: Blockhash): FutureApplicationResult[Block] def getBlock(blockhash: Blockhash): FutureApplicationResult[Block]
} }
@ -83,7 +83,7 @@ class XSNServiceRPCImpl @Inject() (
} }
} }
override def getTransactionCount(address: Address): FutureApplicationResult[Int] = { override def getTransactions(address: Address): FutureApplicationResult[List[TransactionId]] = {
val body = s""" val body = s"""
|{ |{
| "jsonrpc": "1.0", | "jsonrpc": "1.0",
@ -101,8 +101,8 @@ class XSNServiceRPCImpl @Inject() (
.post(body) .post(body)
.map { response => .map { response =>
val maybe = getResult[List[JsValue]](response, errorCodeMapper) val maybe = getResult[List[TransactionId]](response, errorCodeMapper)
maybe.map(_.map(_.size)).getOrElse { maybe.getOrElse {
logger.warn(s"Unexpected response from XSN Server, status = ${response.status}, address = ${address.string}, response = ${response.body}") logger.warn(s"Unexpected response from XSN Server, status = ${response.status}, address = ${address.string}, response = ${response.body}")
Bad(XSNUnexpectedResponseError).accumulating Bad(XSNUnexpectedResponseError).accumulating

8
server/test/com/xsn/explorer/helpers/DataHelper.scala

@ -1,7 +1,7 @@
package com.xsn.explorer.helpers package com.xsn.explorer.helpers
import com.xsn.explorer.models.rpc.{ScriptPubKey, TransactionVOUT} import com.xsn.explorer.models.rpc.{AddressBalance, ScriptPubKey, TransactionVOUT}
import com.xsn.explorer.models.{Address, TransactionId} import com.xsn.explorer.models.{Address, AddressDetails, TransactionId}
object DataHelper { object DataHelper {
@ -23,4 +23,8 @@ object DataHelper {
def createScriptPubKey(scriptType: String, asm: String, address: Option[Address] = None) = { def createScriptPubKey(scriptType: String, asm: String, address: Option[Address] = None) = {
ScriptPubKey(scriptType, asm, address.toList) ScriptPubKey(scriptType, asm, address.toList)
} }
def createAddressDetails(balance: Int, received: Int, transactions: List[TransactionId]) = {
AddressDetails(AddressBalance(BigDecimal(balance), BigDecimal(received)), transactions)
}
} }

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

@ -9,6 +9,6 @@ class DummyXSNService extends XSNService {
override def getTransaction(txid: TransactionId): FutureApplicationResult[Transaction] = ??? override def getTransaction(txid: TransactionId): FutureApplicationResult[Transaction] = ???
override def getAddressBalance(address: Address): FutureApplicationResult[AddressBalance] = ??? override def getAddressBalance(address: Address): FutureApplicationResult[AddressBalance] = ???
override def getTransactionCount(address: Address): FutureApplicationResult[Int] = ??? override def getTransactions(address: Address): FutureApplicationResult[List[TransactionId]] = ???
override def getBlock(blockhash: Blockhash): FutureApplicationResult[Block] = ??? override def getBlock(blockhash: Blockhash): FutureApplicationResult[Block] = ???
} }

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

@ -6,7 +6,7 @@ import com.xsn.explorer.helpers.Executors
import com.xsn.explorer.models.{Address, Blockhash, TransactionId} import com.xsn.explorer.models.{Address, Blockhash, TransactionId}
import org.mockito.ArgumentMatchers._ import org.mockito.ArgumentMatchers._
import org.mockito.Mockito._ import org.mockito.Mockito._
import org.scalactic.{Bad, Good} import org.scalactic.Bad
import org.scalatest.concurrent.ScalaFutures import org.scalatest.concurrent.ScalaFutures
import org.scalatest.mockito.MockitoSugar import org.scalatest.mockito.MockitoSugar
import org.scalatest.{MustMatchers, OptionValues, WordSpec} import org.scalatest.{MustMatchers, OptionValues, WordSpec}
@ -279,8 +279,8 @@ class XSNServiceRPCImplSpec extends WordSpec with MustMatchers with ScalaFutures
} }
} }
"getTransactionCount" should { "getTransactions" should {
"return the number of transactions" in { "return the transactions" in {
val responseBody = val responseBody =
""" """
|{ |{
@ -308,8 +308,9 @@ class XSNServiceRPCImplSpec extends WordSpec with MustMatchers with ScalaFutures
when(response.json).thenReturn(json) when(response.json).thenReturn(json)
when(request.post[String](anyString())(any())).thenReturn(Future.successful(response)) when(request.post[String](anyString())(any())).thenReturn(Future.successful(response))
whenReady(service.getTransactionCount(address)) { result => whenReady(service.getTransactions(address)) { result =>
result mustEqual Good(9) result.isGood mustEqual true
result.get.size mustEqual 9
} }
} }
@ -324,7 +325,7 @@ class XSNServiceRPCImplSpec extends WordSpec with MustMatchers with ScalaFutures
when(response.json).thenReturn(json) when(response.json).thenReturn(json)
when(request.post[String](anyString())(any())).thenReturn(Future.successful(response)) when(request.post[String](anyString())(any())).thenReturn(Future.successful(response))
whenReady(service.getTransactionCount(address)) { result => whenReady(service.getTransactions(address)) { result =>
result mustEqual Bad(AddressFormatError).accumulating result mustEqual Bad(AddressFormatError).accumulating
} }
} }

24
server/test/controllers/AddressesControllerSpec.scala

@ -3,7 +3,7 @@ package controllers
import com.alexitc.playsonify.PublicErrorRenderer import com.alexitc.playsonify.PublicErrorRenderer
import com.alexitc.playsonify.core.FutureApplicationResult import com.alexitc.playsonify.core.FutureApplicationResult
import com.xsn.explorer.errors.AddressFormatError import com.xsn.explorer.errors.AddressFormatError
import com.xsn.explorer.helpers.DummyXSNService import com.xsn.explorer.helpers.{DataHelper, DummyXSNService}
import com.xsn.explorer.models._ import com.xsn.explorer.models._
import com.xsn.explorer.models.rpc.AddressBalance import com.xsn.explorer.models.rpc.AddressBalance
import com.xsn.explorer.services.XSNService import com.xsn.explorer.services.XSNService
@ -15,15 +15,19 @@ import play.api.test.Helpers._
import scala.concurrent.Future import scala.concurrent.Future
class AddressesControllerSpec extends MyAPISpec { class AddressesControllerSpec extends MyAPISpec {
def addressDetails(balance: Int, received: Int, txCount: Int) = { import DataHelper._
AddressDetails(AddressBalance(BigDecimal(balance), BigDecimal(received)), txCount)
}
val addressEmpty = addressDetails(0, 0, 0) val addressEmpty = createAddressDetails(0, 0, List())
val addressFilled = addressDetails(100, 200, 25) val addressFilled = createAddressDetails(
100,
200,
List(
createTransactionId("0834641a7d30d8a2d2b451617599670445ee94ed7736e146c13be260c576c641"),
createTransactionId("024aba1d535cfe5dd3ea465d46a828a57b00e1df012d7a2d158e0f7484173f7c")
)
)
val customXSNService = new DummyXSNService { val customXSNService = new DummyXSNService {
val map = Map( val map = Map(
@ -37,8 +41,8 @@ class AddressesControllerSpec extends MyAPISpec {
Future.successful(result) Future.successful(result)
} }
override def getTransactionCount(address: Address): FutureApplicationResult[Int] = { override def getTransactions(address: Address): FutureApplicationResult[List[TransactionId]] = {
val maybe = map.get(address.string).map(_.transactionCount) val maybe = map.get(address.string).map(_.transactions)
val result = Or.from(maybe, One(AddressFormatError)) val result = Or.from(maybe, One(AddressFormatError))
Future.successful(result) Future.successful(result)
} }
@ -59,7 +63,7 @@ class AddressesControllerSpec extends MyAPISpec {
val json = contentAsJson(response) val json = contentAsJson(response)
(json \ "balance").as[BigDecimal] mustEqual address.balance.balance (json \ "balance").as[BigDecimal] mustEqual address.balance.balance
(json \ "received").as[BigDecimal] mustEqual address.balance.received (json \ "received").as[BigDecimal] mustEqual address.balance.received
(json \ "transactionCount").as[Int] mustEqual address.transactionCount (json \ "transactions").as[List[String]].size mustEqual address.transactions.size
} }
"fail on bad address format" in { "fail on bad address format" in {

Loading…
Cancel
Save