Skip to content

Commit

Permalink
server: Add endpoint "GET /v2/blocks/:blockhash/light-wallet-transact…
Browse files Browse the repository at this point in the history
…ions"
  • Loading branch information
AlexITC committed Mar 12, 2019
1 parent b6bc0d1 commit 10f1932
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 0 deletions.
4 changes: 4 additions & 0 deletions server/app/com/xsn/explorer/data/TransactionDataHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ trait TransactionDataHandler[F[_]] {
limit: Limit,
lastSeenTxid: Option[TransactionId]): F[List[TransactionWithValues]]

def getTransactionsWithIOBy(
blockhash: Blockhash,
limit: Limit,
lastSeenTxid: Option[TransactionId]): F[List[Transaction.HasIO]]
}

trait TransactionBlockingDataHandler extends TransactionDataHandler[ApplicationResult]
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,16 @@ class TransactionPostgresDataHandler @Inject() (

Good(transactions)
}

override def getTransactionsWithIOBy(
blockhash: Blockhash,
limit: Limit,
lastSeenTxid: Option[TransactionId]): ApplicationResult[List[Transaction.HasIO]] = withConnection { implicit conn =>

val transactions = lastSeenTxid
.map { transactionPostgresDAO.getTransactionsWithIOBy(blockhash, _, limit) }
.getOrElse { transactionPostgresDAO.getTransactionsWithIOBy(blockhash, limit) }

Good(transactions)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ class TransactionInputPostgresDAO {
).as(parseTransactionInput.*)
}

def getInputs(txid: TransactionId)(implicit conn: Connection): List[Transaction.Input] = {
SQL(
"""
|SELECT txid, index, from_txid, from_output_index, value, address
|FROM transaction_inputs
|WHERE txid = {txid}
""".stripMargin
).on(
'txid -> txid.string
).as(parseTransactionInput.*)
}

def getInputs(txid: TransactionId, address: Address)(implicit conn: Connection): List[Transaction.Input] = {
SQL(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ class TransactionOutputPostgresDAO {
result
}

def getOutputs(txid: TransactionId)(implicit conn: Connection): List[Transaction.Output] = {
SQL(
"""
|SELECT txid, index, hex_script, value, address, tpos_owner_address, tpos_merchant_address
|FROM transaction_outputs
|WHERE txid = {txid}
""".stripMargin
).on(
'txid -> txid.string
).as(parseTransactionOutput.*)
}

def getOutputs(txid: TransactionId, address: Address)(implicit conn: Connection): List[Transaction.Output] = {
SQL(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,59 @@ class TransactionPostgresDAO @Inject() (
).as(parseTransactionWithValues.*)
}

def getTransactionsWithIOBy(blockhash: Blockhash, limit: Limit)(implicit conn: Connection): List[Transaction.HasIO] = {
val transactions = SQL(
"""
|SELECT t.txid, t.blockhash, t.time, t.size
|FROM transactions t JOIN blocks USING (blockhash)
|WHERE blockhash = {blockhash}
|ORDER BY t.index ASC
|LIMIT {limit}
""".stripMargin
).on(
'limit -> limit.int,
'blockhash -> blockhash.string
).as(parseTransaction.*)

for {
tx <- transactions
} yield {
val inputs = transactionInputDAO.getInputs(tx.id)
val outputs = transactionOutputDAO.getOutputs(tx.id)
Transaction.HasIO(tx, inputs = inputs, outputs = outputs)
}
}

def getTransactionsWithIOBy(blockhash: Blockhash, lastSeenTxid: TransactionId, limit: Limit)(implicit conn: Connection): List[Transaction.HasIO] = {
val transactions = SQL(
"""
|WITH CTE AS (
| SELECT index AS lastSeenIndex
| FROM transactions
| WHERE txid = {lastSeenTxid}
|)
|SELECT t.txid, t.blockhash, t.time, t.size
|FROM CTE CROSS JOIN transactions t JOIN blocks USING (blockhash)
|WHERE blockhash = {blockhash} AND
| t.index > lastSeenIndex
|ORDER BY t.index ASC
|LIMIT {limit}
""".stripMargin
).on(
'limit -> limit.int,
'blockhash -> blockhash.string,
'lastSeenTxid -> lastSeenTxid.string
).as(parseTransaction.*)

for {
tx <- transactions
} yield {
val inputs = transactionInputDAO.getInputs(tx.id)
val outputs = transactionOutputDAO.getOutputs(tx.id)
Transaction.HasIO(tx, inputs = inputs, outputs = outputs)
}
}

private def upsertTransaction(index: Int, transaction: Transaction)(implicit conn: Connection): Option[Transaction] = {
SQL(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,12 @@ class TransactionFutureDataHandler @Inject() (

blockingDataHandler.getByBlockhash(blockhash, limit, lastSeenTxid)
}

override def getTransactionsWithIOBy(
blockhash: Blockhash,
limit: Limit,
lastSeenTxid: Option[TransactionId]): FutureApplicationResult[List[Transaction.HasIO]] = Future {

blockingDataHandler.getTransactionsWithIOBy(blockhash, limit, lastSeenTxid)
}
}
27 changes: 27 additions & 0 deletions server/app/com/xsn/explorer/services/TransactionService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,33 @@ class TransactionService @Inject() (
result.toFuture
}

def getLightWalletTransactionsByBlockhash(
blockhashString: String,
limit: Limit,
lastSeenTxidString: Option[String]): FutureApplicationResult[WrappedResult[List[LightWalletTransaction]]] = {

val result = for {
blockhash <- Or.from(Blockhash.from(blockhashString), One(BlockhashFormatError)).toFutureOr
_ <- paginatedQueryValidator.validate(PaginatedQuery(Offset(0), limit), maxTransactionsPerQuery).toFutureOr

lastSeenTxid <- {
lastSeenTxidString
.map(TransactionId.from)
.map { txid => Or.from(txid, One(TransactionFormatError)).map(Option.apply) }
.getOrElse(Good(Option.empty))
.toFutureOr
}

transactions <- transactionFutureDataHandler.getTransactionsWithIOBy(blockhash, limit, lastSeenTxid).toFutureOr
} yield {
val lightTxs = transactions.map(toLightWalletTransaction)

WrappedResult(lightTxs)
}

result.toFuture
}

/** TODO: Move to another file */
private def getOrderingConditionResult(unsafeOrderingCondition: String) = {
val maybe = parseOrderingCondition(unsafeOrderingCondition)
Expand Down
4 changes: 4 additions & 0 deletions server/app/controllers/BlocksController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,8 @@ class BlocksController @Inject() (
def getTransactionsV2(blockhash: String, limit: Int, lastSeenTxid: Option[String]) = public { _ =>
transactionService.getByBlockhash(blockhash, Limit(limit), lastSeenTxid)
}

def getLightTransactionsV2(blockhash: String, limit: Int, lastSeenTxid: Option[String]) = public { _ =>
transactionService.getLightWalletTransactionsByBlockhash(blockhash, Limit(limit), lastSeenTxid)
}
}
1 change: 1 addition & 0 deletions server/conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ GET /blocks/:query controllers.BlocksController.getDetails
GET /blocks/:query/raw controllers.BlocksController.getRawBlock(query: String)
GET /blocks/:blockhash/transactions controllers.BlocksController.getTransactions(blockhash: String, offset: Int ?= 0, limit: Int ?= 10, orderBy: String ?= "")
GET /v2/blocks/:blockhash/transactions controllers.BlocksController.getTransactionsV2(blockhash: String, limit: Int ?= 10, lastSeenTxid: Option[String])
GET /v2/blocks/:blockhash/light-wallet-transactions controllers.BlocksController.getLightTransactionsV2(blockhash: String, limit: Int ?= 10, lastSeenTxid: Option[String])

GET /stats controllers.StatisticsController.getStatus()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ class TransactionDummyDataHandler extends TransactionBlockingDataHandler {

override def getByBlockhash(blockhash: Blockhash, limit: pagination.Limit, lastSeenTxid: Option[TransactionId]): ApplicationResult[List[TransactionWithValues]] = ???

override def getTransactionsWithIOBy(blockhash: Blockhash, limit: pagination.Limit, lastSeenTxid: Option[TransactionId]): ApplicationResult[List[Transaction.HasIO]] = ???
}

0 comments on commit 10f1932

Please sign in to comment.