From c600980e8381916be3ae92c1016140620a0c2b5e Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sat, 12 May 2018 16:03:38 -0500 Subject: [PATCH] server: Add endpoint: "GET /transactions/:txid/raw" --- .../services/TransactionService.scala | 14 ++++++++++ .../controllers/TransactionsController.scala | 4 +++ server/conf/routes | 3 ++- .../TransactionsControllerSpec.scala | 26 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/server/app/com/xsn/explorer/services/TransactionService.scala b/server/app/com/xsn/explorer/services/TransactionService.scala index bae0a45..6d91cb6 100644 --- a/server/app/com/xsn/explorer/services/TransactionService.scala +++ b/server/app/com/xsn/explorer/services/TransactionService.scala @@ -8,11 +8,25 @@ import com.xsn.explorer.errors.{TransactionFormatError, TransactionNotFoundError import com.xsn.explorer.models.rpc.TransactionVIN import com.xsn.explorer.models.{Transaction, TransactionDetails, TransactionId, TransactionValue} import org.scalactic.{Bad, Good, One, Or} +import play.api.libs.json.JsValue import scala.concurrent.{ExecutionContext, Future} class TransactionService @Inject() (xsnService: XSNService)(implicit ec: ExecutionContext) { + def getRawTransaction(txidString: String): FutureApplicationResult[JsValue] = { + val result = for { + txid <- { + val maybe = TransactionId.from(txidString) + Or.from(maybe, One(TransactionFormatError)).toFutureOr + } + + transaction <- xsnService.getRawTransaction(txid).toFutureOr + } yield transaction + + result.toFuture + } + def getTransactionDetails(txidString: String): FutureApplicationResult[TransactionDetails] = { val result = for { txid <- { diff --git a/server/app/controllers/TransactionsController.scala b/server/app/controllers/TransactionsController.scala index 237380f..054b640 100644 --- a/server/app/controllers/TransactionsController.scala +++ b/server/app/controllers/TransactionsController.scala @@ -13,4 +13,8 @@ class TransactionsController @Inject() ( def getTransaction(txid: String) = publicNoInput { _ => transactionService.getTransactionDetails(txid) } + + def getRawTransaction(txid: String) = publicNoInput { _ => + transactionService.getRawTransaction(txid) + } } diff --git a/server/conf/routes b/server/conf/routes index bda033a..1d5147a 100644 --- a/server/conf/routes +++ b/server/conf/routes @@ -5,7 +5,8 @@ GET /health controllers.HealthController.check() -GET /transactions/:txid controllers.TransactionsController.getTransaction(txid: String) +GET /transactions/:txid controllers.TransactionsController.getTransaction(txid: String) +GET /transactions/:txid/raw controllers.TransactionsController.getRawTransaction(txid: String) GET /addresses/:address controllers.AddressesController.getDetails(address: String) diff --git a/server/test/controllers/TransactionsControllerSpec.scala b/server/test/controllers/TransactionsControllerSpec.scala index f703dcd..779d93a 100644 --- a/server/test/controllers/TransactionsControllerSpec.scala +++ b/server/test/controllers/TransactionsControllerSpec.scala @@ -41,6 +41,17 @@ class TransactionsControllerSpec extends MyAPISpec { Future.successful(result) } + + override def getRawTransaction(txid: TransactionId): FutureApplicationResult[JsValue] = { + val result = map.get(txid) + .map { _ => TransactionLoader.json(txid.string) } + .map(Good(_)) + .getOrElse { + Bad(TransactionNotFoundError).accumulating + } + + Future.successful(result) + } } override val application = guiceApplicationBuilder @@ -179,4 +190,19 @@ class TransactionsControllerSpec extends MyAPISpec { (error \ "message").as[String].nonEmpty mustEqual true } } + + "GET transactions/:txid/raw" should { + def url(txid: String) = s"/transactions/$txid/raw" + + "retrieve the raw transaction" in { + val tx = coinbaseTx + val expected = TransactionLoader.json(tx.id.string) + val response = GET(url(tx.id.string)) + + status(response) mustEqual OK + val json = contentAsJson(response) + + json mustEqual expected + } + } }