package jbok.app.service.store.doobie import cats.effect.Sync import cats.implicits._ import doobie.implicits._ import doobie.util.transactor.Transactor import doobie.util.update.Update import jbok.app.service.store.TransactionStore import jbok.common.math.N import jbok.core.api.HistoryTransaction import jbok.core.models.{Receipt, Block => CoreBlock} final class DoobieTransactionStore[F[_]](xa: Transactor[F])(implicit F: Sync[F]) extends TransactionStore[F] with DoobieSupport { def findTransactionsByAddress(address: String, page: Int, size: Int): F[List[HistoryTransaction]] = sql""" SELECT txHash, nonce, fromAddress, toAddress, value, payload, v, r, s, gasUsed, gasPrice, blockNumber, blockHash, location FROM transactions WHERE (fromAddress = ${address.toString} OR toAddress = ${address.toString}) ORDER BY blockNumber, location DESC limit ${size} offset ${(page - 1) * size} """ .query[HistoryTransaction] .to[List] .transact(xa) def findTransactionByHash(txHash: String): F[Option[HistoryTransaction]] = sql""" SELECT txHash, nonce, fromAddress, toAddress, value, payload, v, r, s, gasUsed, gasPrice, blockNumber, blockHash, location FROM transactions WHERE txHash = ${txHash} """ .query[HistoryTransaction] .option .transact(xa) override def findTransactionsByNumber(blockNumber: Int): F[List[HistoryTransaction]] = sql""" SELECT txHash, nonce, fromAddress, toAddress, value, payload, v, r, s, gasUsed, gasPrice, blockNumber, blockHash, location FROM transactions WHERE (blockNumber = ${blockNumber}) ORDER BY blockNumber, location DESC """ .query[HistoryTransaction] .to[List] .transact(xa) override def delByBlockNumber(number: N): F[Unit] = sql"""DELETE from transactions WHERE blockNumber = $number""".update.run.void.transact(xa) def insertBlockTransactions(block: CoreBlock, receipts: List[Receipt]): F[Unit] = { require(block.body.transactionList.length == receipts.length) val xs = block.body.transactionList.zip(receipts).zipWithIndex.map { case ((stx, receipt), idx) => ( stx.hash.toHex, stx.nonce.toInt, stx.senderAddress.map(_.toString).getOrElse(""), stx.receivingAddress.toString, stx.value.toString, stx.payload.toHex, stx.v.toString, stx.r.toString, stx.s.toString, receipt.gasUsed.toString, stx.gasPrice.toString, block.header.number.toLong, block.header.hash.toHex, idx ) } val holes = List.fill(14)("?").mkString(",") val sql = s"insert into transactions (txHash, nonce, fromAddress, toAddress, value, payload, v, r, s, gasUsed, gasPrice, blockNumber, blockHash, location) values ($holes)" Update[(String, Int, String, String, String, String, String, String, String, String, String, Long, String, Int)](sql) .updateMany(xs) .transact(xa) .void } }