Browse Source

server: Remove unnecessary endpoint "POST /transactions/latest"

prometheus-integration
Alexis Hernandez 6 years ago
parent
commit
97254aae11
  1. 2
      server/app/com/xsn/explorer/data/TransactionDataHandler.scala
  2. 8
      server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala
  3. 24
      server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala
  4. 5
      server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala
  5. 4
      server/app/com/xsn/explorer/services/TransactionService.scala
  6. 6
      server/app/controllers/TransactionsController.scala
  7. 1
      server/conf/routes
  8. 21
      server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala
  9. 2
      server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala
  10. 54
      server/test/controllers/TransactionsControllerSpec.scala

2
server/app/com/xsn/explorer/data/TransactionDataHandler.scala

@ -5,7 +5,6 @@ import com.alexitc.playsonify.models.ordering.{FieldOrdering, OrderingCondition}
import com.alexitc.playsonify.models.pagination.{Limit, PaginatedQuery, PaginatedResult} import com.alexitc.playsonify.models.pagination.{Limit, PaginatedQuery, PaginatedResult}
import com.xsn.explorer.models._ import com.xsn.explorer.models._
import com.xsn.explorer.models.fields.TransactionField import com.xsn.explorer.models.fields.TransactionField
import org.scalactic.Every
import scala.language.higherKinds import scala.language.higherKinds
@ -30,7 +29,6 @@ trait TransactionDataHandler[F[_]] {
limit: Limit, limit: Limit,
lastSeenTxid: Option[TransactionId]): F[List[TransactionWithValues]] lastSeenTxid: Option[TransactionId]): F[List[TransactionWithValues]]
def getLatestTransactionBy(addresses: Every[Address]): F[Map[String, String]]
} }
trait TransactionBlockingDataHandler extends TransactionDataHandler[ApplicationResult] trait TransactionBlockingDataHandler extends TransactionDataHandler[ApplicationResult]

8
server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala

@ -8,7 +8,7 @@ import com.xsn.explorer.data.anorm.dao.TransactionPostgresDAO
import com.xsn.explorer.models._ import com.xsn.explorer.models._
import com.xsn.explorer.models.fields.TransactionField import com.xsn.explorer.models.fields.TransactionField
import javax.inject.Inject import javax.inject.Inject
import org.scalactic.{Every, Good} import org.scalactic.Good
import play.api.db.Database import play.api.db.Database
class TransactionPostgresDataHandler @Inject() ( class TransactionPostgresDataHandler @Inject() (
@ -70,10 +70,4 @@ class TransactionPostgresDataHandler @Inject() (
Good(transactions) Good(transactions)
} }
def getLatestTransactionBy(addresses: Every[Address]): ApplicationResult[Map[String, String]] = withConnection { implicit conn =>
val result = transactionPostgresDAO.getLatestTransactionBy(addresses)
Good(result)
}
} }

24
server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala

@ -277,30 +277,6 @@ class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderi
).as(parseTransactionOutput.*).flatten ).as(parseTransactionOutput.*).flatten
} }
def getLatestTransactionBy(addresses: Every[Address])(implicit conn: Connection): Map[String, String] = {
import SqlParser._
val result = SQL(
s"""
|SELECT address, (
| SELECT txid
| FROM address_transaction_details
| WHERE address = a.address
| ORDER BY time DESC
| LIMIT 1
|) AS txid
|FROM address_transaction_details a
|GROUP BY address
|HAVING address IN ({addresses});
""".stripMargin
).on(
'addresses -> addresses.map(_.string).toList
).as((str("address") ~ str("txid")).map(flatten).*)
result.toMap
}
private def upsertTransaction(index: Int, transaction: Transaction)(implicit conn: Connection): Option[Transaction] = { private def upsertTransaction(index: Int, transaction: Transaction)(implicit conn: Connection): Option[Transaction] = {
SQL( SQL(
""" """

5
server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala

@ -8,7 +8,6 @@ import com.xsn.explorer.executors.DatabaseExecutionContext
import com.xsn.explorer.models._ import com.xsn.explorer.models._
import com.xsn.explorer.models.fields.TransactionField import com.xsn.explorer.models.fields.TransactionField
import javax.inject.Inject import javax.inject.Inject
import org.scalactic.Every
import scala.concurrent.Future import scala.concurrent.Future
@ -53,8 +52,4 @@ class TransactionFutureDataHandler @Inject() (
blockingDataHandler.getByBlockhash(blockhash, limit, lastSeenTxid) blockingDataHandler.getByBlockhash(blockhash, limit, lastSeenTxid)
} }
override def getLatestTransactionBy(addresses: Every[Address]): FutureApplicationResult[Map[String, String]] = Future {
blockingDataHandler.getLatestTransactionBy(addresses)
}
} }

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

@ -240,10 +240,6 @@ class TransactionService @Inject() (
result.toFuture result.toFuture
} }
def getLatestTransactionBy(addresses: Every[Address]): FutureApplicationResult[Map[String, String]] = {
transactionFutureDataHandler.getLatestTransactionBy(addresses)
}
private def getTransactionValue(vin: TransactionVIN): FutureApplicationResult[TransactionValue] = { private def getTransactionValue(vin: TransactionVIN): FutureApplicationResult[TransactionValue] = {
val valueMaybe = for { val valueMaybe = for {
value <- vin.value value <- vin.value

6
server/app/controllers/TransactionsController.scala

@ -1,6 +1,6 @@
package controllers package controllers
import com.xsn.explorer.models.request.{GetLatestTransactionRequest, SendRawTransactionRequest} import com.xsn.explorer.models.request.SendRawTransactionRequest
import com.xsn.explorer.services.TransactionService import com.xsn.explorer.services.TransactionService
import controllers.common.{MyJsonController, MyJsonControllerComponents} import controllers.common.{MyJsonController, MyJsonControllerComponents}
import javax.inject.Inject import javax.inject.Inject
@ -23,8 +23,4 @@ class TransactionsController @Inject() (
def sendRawTransaction() = publicInput { ctx: HasModel[SendRawTransactionRequest] => def sendRawTransaction() = publicInput { ctx: HasModel[SendRawTransactionRequest] =>
transactionService.sendRawTransaction(ctx.model.hex) transactionService.sendRawTransaction(ctx.model.hex)
} }
def getLatestByAddresses() = publicInput { ctx: HasModel[GetLatestTransactionRequest] =>
transactionService.getLatestTransactionBy(ctx.model.addresses)
}
} }

1
server/conf/routes

@ -9,7 +9,6 @@ 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 /transactions/:txid/raw controllers.TransactionsController.getRawTransaction(txid: String)
POST /transactions controllers.TransactionsController.sendRawTransaction() POST /transactions controllers.TransactionsController.sendRawTransaction()
POST /transactions/latest controllers.TransactionsController.getLatestByAddresses()
GET /addresses/:address controllers.AddressesController.getBy(address: String) GET /addresses/:address controllers.AddressesController.getBy(address: String)
GET /addresses/:address/transactions controllers.AddressesController.getTransactions(address: String, offset: Int ?= 0, limit: Int ?= 10, orderBy: String ?= "") GET /addresses/:address/transactions controllers.AddressesController.getTransactions(address: String, offset: Int ?= 0, limit: Int ?= 10, orderBy: String ?= "")

21
server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala

@ -299,27 +299,6 @@ class TransactionPostgresDataHandlerSpec extends PostgresDataHandlerSpec with Be
} }
} }
"getLatestTransactionBy" should {
"return the relation address -> latest txid" in {
clearDatabase()
val blocks = blockList
blocks.map(createBlock)
val expected = Map(
"XcqpUChZhNkVDgQqFF9U4DdewDGUMWwG53" -> "41e315108dc2df60caddbc7e8740a5614217f996c96898019e69b3195fd7ee10",
"XdJnCKYNwzCz8ATv8Eu75gonaHyfr9qXg9" -> "1e591eae200f719344fc5df0c4286e3fb191fb8a645bdf054f9b36a856fce41e"
)
val addresses = Every(
createAddress("XdJnCKYNwzCz8ATv8Eu75gonaHyfr9qXg9"),
createAddress("XcqpUChZhNkVDgQqFF9U4DdewDGUMWwG53"),
createAddress("XcqpUChZhNkVDgQqFF9U4DdewDGUMWwG54"),
)
val result = dataHandler.getLatestTransactionBy(addresses).get
result mustEqual expected
}
}
"getBy with scroll" should { "getBy with scroll" should {
val address = createAddress("XxQ7j37LfuXgsLD5DZAwFKhT3s2ZMkW86F") val address = createAddress("XxQ7j37LfuXgsLD5DZAwFKhT3s2ZMkW86F")
val blockhash = createBlockhash("0000000000bdbb23e28f79a49d29b41429737c6c7e15df40d1b1f1b35907ae34") val blockhash = createBlockhash("0000000000bdbb23e28f79a49d29b41429737c6c7e15df40d1b1f1b35907ae34")

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

@ -7,7 +7,6 @@ import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult
import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.data.TransactionBlockingDataHandler
import com.xsn.explorer.models._ import com.xsn.explorer.models._
import com.xsn.explorer.models.fields.TransactionField import com.xsn.explorer.models.fields.TransactionField
import org.scalactic.Every
class TransactionDummyDataHandler extends TransactionBlockingDataHandler { class TransactionDummyDataHandler extends TransactionBlockingDataHandler {
@ -21,5 +20,4 @@ class TransactionDummyDataHandler extends TransactionBlockingDataHandler {
override def getByBlockhash(blockhash: Blockhash, limit: pagination.Limit, lastSeenTxid: Option[TransactionId]): ApplicationResult[List[TransactionWithValues]] = ??? override def getByBlockhash(blockhash: Blockhash, limit: pagination.Limit, lastSeenTxid: Option[TransactionId]): ApplicationResult[List[TransactionWithValues]] = ???
override def getLatestTransactionBy(addresses: Every[Address]): ApplicationResult[Map[String, String]] = ???
} }

54
server/test/controllers/TransactionsControllerSpec.scala

@ -1,6 +1,6 @@
package controllers package controllers
import com.alexitc.playsonify.core.{ApplicationResult, FutureApplicationResult} import com.alexitc.playsonify.core.FutureApplicationResult
import com.alexitc.playsonify.play.PublicErrorRenderer import com.alexitc.playsonify.play.PublicErrorRenderer
import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.data.TransactionBlockingDataHandler
import com.xsn.explorer.errors.TransactionNotFoundError import com.xsn.explorer.errors.TransactionNotFoundError
@ -9,9 +9,9 @@ import com.xsn.explorer.models._
import com.xsn.explorer.models.rpc.Transaction import com.xsn.explorer.models.rpc.Transaction
import com.xsn.explorer.services.XSNService import com.xsn.explorer.services.XSNService
import controllers.common.MyAPISpec import controllers.common.MyAPISpec
import org.scalactic.{Bad, Every, Good} import org.scalactic.{Bad, Good}
import play.api.inject.bind import play.api.inject.bind
import play.api.libs.json.{JsValue, Json} import play.api.libs.json.JsValue
import play.api.test.Helpers._ import play.api.test.Helpers._
import scala.concurrent.Future import scala.concurrent.Future
@ -59,18 +59,7 @@ class TransactionsControllerSpec extends MyAPISpec {
} }
} }
val transactionDataHandler = new TransactionDummyDataHandler { val transactionDataHandler = new TransactionDummyDataHandler {}
val map: Map[Address, TransactionId] = Map(firstAddress -> firstTxId, secondAddress -> secondTxId)
override def getLatestTransactionBy(addresses: Every[Address]): ApplicationResult[Map[String, String]] = {
val result = map
.filterKeys(addresses contains _)
.map( x => x._1.string -> x._2.string )
Good(result)
}
}
override val application = guiceApplicationBuilder override val application = guiceApplicationBuilder
.overrides(bind[XSNService].to(customXSNService)) .overrides(bind[XSNService].to(customXSNService))
@ -224,39 +213,4 @@ class TransactionsControllerSpec extends MyAPISpec {
json mustEqual expected json mustEqual expected
} }
} }
"POST /transactions/latest" should {
def url = s"/transactions/latest"
"return the latest transactions for the addresses" in {
val addresses = List(firstAddress.string, secondAddress.string, s"3rd${secondAddress.string}")
.map(x => s""" "$x" """)
.mkString("[", ",", "]")
val body = s"""{ "addresses": $addresses }"""
val expected = Json.obj(firstAddress.string -> firstTxId, secondAddress.string -> secondTxId)
val response = POST(url, Some(body))
status(response) mustEqual OK
val json = contentAsJson(response)
json mustEqual expected
}
"fail while passing no addresses" in {
val body = """{ "addresses": [] }"""
val response = POST(url, Some(body))
status(response) mustEqual BAD_REQUEST
val json = contentAsJson(response)
val errorList = (json \ "errors").as[List[JsValue]]
errorList.size mustEqual 1
val error = errorList.head
(error \ "type").as[String] mustEqual PublicErrorRenderer.FieldValidationErrorType
(error \ "field").as[String] mustEqual "addresses"
(error \ "message").as[String].nonEmpty mustEqual true
}
}
} }

Loading…
Cancel
Save