From e3bf0b0ef44e85b0297d997bace18c7f4d80c4a6 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sat, 7 Apr 2018 12:49:04 -0500 Subject: [PATCH] server: Allow to retrieve blocks by hash --- .../xsn/explorer/data/BlockDataHandler.scala | 4 +++- .../data/anorm/BlockPostgresDataHandler.scala | 8 ++++++- .../data/anorm/dao/BlockPostgresDAO.scala | 14 ++++++++++++ .../data/BlockPostgresDataHandlerSpec.scala | 22 +++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/server/app/com/xsn/explorer/data/BlockDataHandler.scala b/server/app/com/xsn/explorer/data/BlockDataHandler.scala index aea973d..d48c580 100644 --- a/server/app/com/xsn/explorer/data/BlockDataHandler.scala +++ b/server/app/com/xsn/explorer/data/BlockDataHandler.scala @@ -1,6 +1,7 @@ package com.xsn.explorer.data import com.alexitc.playsonify.core.ApplicationResult +import com.xsn.explorer.models.Blockhash import com.xsn.explorer.models.rpc.Block import scala.language.higherKinds @@ -8,7 +9,8 @@ import scala.language.higherKinds trait BlockDataHandler[F[_]] { def create(block: Block): F[Block] + + def getBy(blockhash: Blockhash): F[Block] } trait BlockBlockingDataHandler extends BlockDataHandler[ApplicationResult] - diff --git a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala index a547dbe..a603e8f 100644 --- a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala @@ -5,7 +5,8 @@ import javax.inject.Inject import com.alexitc.playsonify.core.ApplicationResult import com.xsn.explorer.data.BlockBlockingDataHandler import com.xsn.explorer.data.anorm.dao.BlockPostgresDAO -import com.xsn.explorer.errors.BlockUnknownError +import com.xsn.explorer.errors.{BlockNotFoundError, BlockUnknownError} +import com.xsn.explorer.models.Blockhash import com.xsn.explorer.models.rpc.Block import org.scalactic.{One, Or} import play.api.db.Database @@ -20,4 +21,9 @@ class BlockPostgresDataHandler @Inject() ( val maybe = blockPostgresDAO.create(block) Or.from(maybe, One(BlockUnknownError)) } + + override def getBy(blockhash: Blockhash): ApplicationResult[Block] = database.withConnection { implicit conn => + val maybe = blockPostgresDAO.getBy(blockhash) + Or.from(maybe, One(BlockNotFoundError)) + } } diff --git a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala index 8bb004f..1b1a45b 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala @@ -4,6 +4,7 @@ import java.sql.Connection import anorm._ import com.xsn.explorer.data.anorm.parsers.BlockParsers._ +import com.xsn.explorer.models.Blockhash import com.xsn.explorer.models.rpc.Block class BlockPostgresDAO { @@ -56,4 +57,17 @@ class BlockPostgresDAO { 'difficulty -> block.difficulty ).as(parseBlock.singleOpt).flatten } + + def getBy(blockhash: Blockhash)(implicit conn: Connection): Option[Block] = { + SQL( + """ + |SELECT hash, previous_blockhash, next_blockhash, tpos_contract, merkle_root, size, + | height, version, time, median_time, nonce, bits, chainwork, difficulty + |FROM blocks + |WHERE hash = {hash} + """.stripMargin + ).on( + "hash" -> blockhash.string + ).as(parseBlock.singleOpt).flatten + } } diff --git a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala index 005ca5f..98a27e7 100644 --- a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala @@ -3,8 +3,11 @@ package com.xsn.explorer.data import com.xsn.explorer.data.anorm.BlockPostgresDataHandler import com.xsn.explorer.data.anorm.dao.BlockPostgresDAO import com.xsn.explorer.data.common.PostgresDataHandlerSpec +import com.xsn.explorer.errors.BlockNotFoundError import com.xsn.explorer.helpers.BlockLoader +import com.xsn.explorer.models.Blockhash import com.xsn.explorer.models.rpc.Block +import org.scalactic.Bad class BlockPostgresDataHandlerSpec extends PostgresDataHandlerSpec { @@ -32,6 +35,25 @@ class BlockPostgresDataHandlerSpec extends PostgresDataHandlerSpec { } } + "getBy" should { + "return a block" in { + val block = BlockLoader.get("1ca318b7a26ed67ca7c8c9b5069d653ba224bf86989125d1dfbb0973b7d6a5e0") + + dataHandler.create(block) + + val result = dataHandler.getBy(block.hash) + result.isGood mustEqual true + matches(block, result.get) + } + + "fail on block not found" in { + val blockhash = Blockhash.from("b858d38a3552c83aea58f66fe00ae220352a235e33fcf1f3af04507a61a9dc32").get + + val result = dataHandler.getBy(blockhash) + result mustEqual Bad(BlockNotFoundError).accumulating + } + } + private def matches(expected: Block, result: Block) = { // NOTE: transactions and confirmations are not matched intentionally result.hash mustEqual expected.hash