Browse Source

server: Fill the address_transaction_details while synching the db

prometheus-integration
Alexis Hernandez 6 years ago
parent
commit
f7887cf3b1
  1. 60
      server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala
  2. 9
      server/app/com/xsn/explorer/data/anorm/parsers/TransactionParsers.scala
  3. 9
      server/app/com/xsn/explorer/models/AddressTransactionDetails.scala
  4. 1
      server/test/com/xsn/explorer/data/common/PostgresDataHandlerSpec.scala

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

@ -21,6 +21,7 @@ class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderi
inputs <- upsertInputs(transaction.id, transaction.inputs)
outputs <- upsertOutputs(transaction.id, transaction.outputs)
_ <- spend(transaction.id, inputs)
_ = insertDetails(transaction)
} yield partialTx.copy(inputs = inputs, outputs = outputs)
}
@ -64,6 +65,7 @@ class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderi
val result = expectedTransactions.map { tx =>
val inputs = deleteInputs(tx.id)
val outputs = deleteOutputs(tx.id)
val _ = deleteDetails(tx.id)
tx.copy(inputs = inputs, outputs = outputs)
}
@ -340,4 +342,62 @@ class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderi
result.flatten
}
private def insertDetails(transaction: Transaction)(implicit conn: Connection): List[AddressTransactionDetails] = {
val received = transaction
.outputs
.groupBy(_.address)
.mapValues { outputs => outputs.map(_.value).sum }
.map { case (address, value) => AddressTransactionDetails(address, transaction.id, time = transaction.time, received = value) }
val sent = transaction
.inputs
.groupBy(_.address)
.mapValues { inputs => inputs.map(_.value).sum }
.map { case (address, value) => AddressTransactionDetails(address, transaction.id, time = transaction.time, sent = value) }
val result = (received ++ sent)
.groupBy(_.address)
.mapValues {
case head :: list => list.foldLeft(head) { (acc, current) =>
current.copy(received = current.received + acc.received, sent = current.sent + acc.sent)
}
}
.values
.map(d => insertDetails(d))
result.toList
}
private def insertDetails(details: AddressTransactionDetails)(implicit conn: Connection): AddressTransactionDetails = {
SQL(
"""
|INSERT INTO address_transaction_details
| (address, txid, received, sent, time)
|VALUES
| ({address}, {txid}, {received}, {sent}, {time})
|RETURNING address, txid, received, sent, time
""".stripMargin
).on(
'address -> details.address.string,
'txid -> details.txid.string,
'received -> details.received,
'sent -> details.sent,
'time -> details.time
).as(parseAddressTransactionDetails.single)
}
private def deleteDetails(txid: TransactionId)(implicit conn: Connection): List[AddressTransactionDetails] = {
val result = SQL(
"""
|DELETE FROM address_transaction_details
|WHERE txid = {txid}
|RETURNING address, txid, received, sent, time
""".stripMargin
).on(
'txid -> txid.string
).as(parseAddressTransactionDetails.*)
result
}
}

9
server/app/com/xsn/explorer/data/anorm/parsers/TransactionParsers.scala

@ -69,4 +69,13 @@ object TransactionParsers {
script <- scriptMaybe
} yield Transaction.Output(txid, index, value, address, script, tposOwnerAddress.flatten, tposMerchantAddress.flatten)
}
val parseAddressTransactionDetails = (parseAddress ~ parseTransactionId ~ parseSent ~ parseReceived ~ parseTime).map {
case address ~ txid ~ sent ~ received ~ time => AddressTransactionDetails(
address.getOrElse(throw new RuntimeException("failed to retrieve address")),
txid.getOrElse(throw new RuntimeException("failed to retrieve txid")),
time = time,
sent = sent,
received = received)
}
}

9
server/app/com/xsn/explorer/models/AddressTransactionDetails.scala

@ -0,0 +1,9 @@
package com.xsn.explorer.models
case class AddressTransactionDetails(
address: Address,
txid: TransactionId,
time: Long,
received: BigDecimal = 0,
sent: BigDecimal = 0)

1
server/test/com/xsn/explorer/data/common/PostgresDataHandlerSpec.scala

@ -62,6 +62,7 @@ trait PostgresDataHandlerSpec
database.withConnection { implicit conn =>
_root_.anorm.SQL("""DELETE FROM transaction_inputs""").execute()
_root_.anorm.SQL("""DELETE FROM transaction_outputs""").execute()
_root_.anorm.SQL("""DELETE FROM address_transaction_details""").execute()
_root_.anorm.SQL("""DELETE FROM transactions""").execute()
_root_.anorm.SQL("""DELETE FROM blocks""").execute()
_root_.anorm.SQL("""DELETE FROM balances""").execute()

Loading…
Cancel
Save