Skip to content

Commit

Permalink
add accounts_history table
Browse files Browse the repository at this point in the history
  • Loading branch information
redroy44 committed Apr 7, 2021
1 parent 6bfcae4 commit 30b7a4d
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 8 deletions.
56 changes: 55 additions & 1 deletion conseil-api/src/main/resources/metadata/ethereum.mainnet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
block_number {
visible: true
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
source {
display-name: "From"
data-type: "accountAddress"
Expand Down Expand Up @@ -163,6 +167,10 @@
block_number {
visible: true
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
data {
visible: true
}
Expand Down Expand Up @@ -213,6 +221,10 @@
block_number {
visible: true
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
contract_address {
visible: true
data-type: "accountAddress"
Expand Down Expand Up @@ -254,6 +266,7 @@
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
bytecode {
visible: true
Expand Down Expand Up @@ -288,6 +301,7 @@
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
name {
visible: true
Expand All @@ -310,12 +324,22 @@
data-type: "accountAddress"
visible: true
}
block_hash {
visible: true
}
block_number {
visible: true
}
timestamp {
visible: true
data-format: "YYYY MMM DD, HH:mm"
}
transaction_hash {
visible: true
}
log_index {
visible: true
}
from_address {
data-type: "accountAddress"
visible: true
Expand All @@ -337,6 +361,9 @@
data-type: "accountAddress"
visible: true
}
block_hash {
visible: true
}
block_number {
visible: true
temporal-column: true
Expand Down Expand Up @@ -380,7 +407,6 @@
scale: 18
data-type: "currency"
currency-symbol-code: 926
visible: true
}
bytecode {
visible: true
Expand All @@ -402,5 +428,33 @@
}
}
}
accounts_history {
visible: true,
temporal-partition: "address"
attributes {
address {
data-type: "accountAddress"
visible: true
}
block_hash {
visible: true
}
block_number {
visible: true
temporal-column: true
}
balance {
visible: true
scale: 18
data-type: "currency"
currency-symbol-code: 926
}
asof {
visible: true
data-format: "YYYY MMM DD, HH:mm"
temporal-column: true
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ object OpenApiDoc
ethereumContractsEndpoint,
ethereumAccountsEndpoint,
ethereumAccountByAddressEndpoint,
ethereumAccountsHistoryEndpoint,
quorumBlocksEndpoint,
quorumBlocksHeadEndpoint,
quorumBlockByHashEndpoint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ trait EthereumDataEndpoints extends EthereumDataEndpointsCreator {
def ethereumAccountByAddressEndpoint: Endpoint[((String, String), Option[String]), Option[QueryResponse]] =
accountByAddressEndpoint(platform)

def ethereumAccountsHistoryEndpoint: Endpoint[((String, EthereumFilter), Option[String]), Option[
List[QueryResponse]
]] =
accountsHistoryEndpoint(platform)
}

/** Represents list of endpoints exposed for Quorum Blockchain (based on Ethereum) */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@ trait EthereumDataEndpointsCreator
docs = EndpointDocs(tags = createTags(platform, "Accounts"))
)

/** V2 Accounts history endpoint definition */
private[ethereum] def accountsHistoryEndpoint(
platform: String
): Endpoint[((String, EthereumFilter), Option[String]), Option[
List[QueryResponse]
]] =
endpoint(
request =
get(url = createPath(platform) / "accounts_history" /? ethereumQsFilter, headers = optRequestHeader("apiKey")),
response = compatibilityQuery[List[QueryResponse]]("accounts history"),
docs = EndpointDocs(tags = createTags(platform, "Accounts history"))
)

private def createPath(platform: String): Path[String] =
path / "v2" / "data" / platform / segment[String](name = "network")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,8 @@ class EthereumDataOperations(prefix: String) extends ApiDataOperations {
queryWithPredicates(prefix, "accounts", filter.toQuery).map(_.headOption)
}

/** Fetches the list of account balances for given query */
def fetchAccountsHistory(query: Query)(implicit ec: ExecutionContext): Future[Option[List[QueryResponse]]] =
queryWithPredicates(prefix, "accounts_history", query).map(Some(_))

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ trait EthereumDataRoutesCreator
private val accountsByAddressRoute: Route =
delegateCall(ethereumAccountByAddressEndpoint)(operations.fetchAccountByAddress)

/** V2 Route implementation for accounts history endpoint */
private val accountsHistoryRoute: Route = delegateCall(ethereumAccountsHistoryEndpoint)(
filter => operations.fetchAccountsHistory(filter.toQuery.withLimitCap(maxQueryResultSize))
)

/**
* Helper method, which validates the network and delegates the call for specific endpoint to the given method `f`.
* Note that this method works only for Tuple2 input parameters in the `endpoint`.
Expand Down Expand Up @@ -155,7 +160,8 @@ trait EthereumDataRoutesCreator
tokenTransfersRoute,
tokensHistoryRoute,
accountsRoute,
accountsByAddressRoute
accountsByAddressRoute,
accountsHistoryRoute
)

/** Function for validation of the platform and network with flatten */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ trait EthereumInMemoryDatabaseSetup extends InMemoryDatabaseSetup {
Fixture.table(Tables.Logs),
Fixture.table(Tables.TokenTransfers),
Fixture.table(Tables.TokensHistory),
Fixture.table(Tables.Accounts)
Fixture.table(Tables.Accounts),
Fixture.table(Tables.AccountsHistory)
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class EthereumDataOperationsTest
}
}

"correctly use query on tempotal tokens_history" in {
"correctly use query on temporal tokens_history" in {

val tokensHistoryRow = TokensHistoryRow(
tokenAddress = "0x1",
Expand Down Expand Up @@ -187,7 +187,7 @@ class EthereumDataOperationsTest

}

"get the balance of a token at a specific timestamp there there are multiple entitioes for given account" in {
"get the balance of a token at a specific timestamp there there are multiple entities for given account" in {
val tokensHistoryRows = List(
TokensHistoryRow(
tokenAddress = "0x1",
Expand Down Expand Up @@ -310,6 +310,156 @@ class EthereumDataOperationsTest
)
)
}

"correctly use query on temporal accounts_history" in {

val accountsHistoryRow = AccountsHistoryRow(
address = "0x1",
blockHash = "0x1",
blockNumber = 1,
balance = BigDecimal("1.0"),
asof = new Timestamp(1)
)

val populateAndTest = for {
_ <- Tables.AccountsHistory += accountsHistoryRow
found <- sut.selectWithPredicates(
"ethereum",
table = Tables.AccountsHistory.baseTableRow.tableName,
columns = List(SimpleField("address"), SimpleField("block_number"), SimpleField("asof")),
predicates = List.empty,
ordering = List(),
aggregation = List.empty,
temporalPartition = Some("address"),
snapshot = Some(Snapshot("asof", new Timestamp(1))),
outputType = OutputType.json,
limit = 10
)
} yield found

val result = dbHandler.run(populateAndTest.transactionally).futureValue

result shouldBe List(
Map(
"address" -> Some("0x1"),
"block_number" -> Some(1),
"asof" -> Some(new Timestamp(1)),
"r" -> Some(1)
)
)
}

"get the balance of an account at a specific timestamp there there are multiple entities for given account" in {
val accountsHistoryRows = List(
AccountsHistoryRow(
address = "0x1",
blockHash = "0x1",
blockNumber = 1,
balance = BigDecimal("1.0"),
asof = new Timestamp(1)
),
AccountsHistoryRow(
address = "0x1",
blockHash = "0x2",
blockNumber = 2,
balance = BigDecimal("2.0"),
asof = new Timestamp(2)
),
AccountsHistoryRow(
address = "0x1",
blockHash = "0x3",
blockNumber = 3,
balance = BigDecimal("3.0"),
asof = new Timestamp(3)
)
)

val populateAndTest = for {
_ <- Tables.AccountsHistory ++= accountsHistoryRows
found <- sut.selectWithPredicates(
"ethereum",
table = Tables.AccountsHistory.baseTableRow.tableName,
columns = List(SimpleField("address"), SimpleField("block_number"), SimpleField("asof")),
predicates = List.empty,
ordering = List(),
aggregation = List.empty,
temporalPartition = Some("address"),
snapshot = Some(Snapshot("asof", new Timestamp(2))),
outputType = OutputType.json,
limit = 10
)
} yield found

val result = dbHandler.run(populateAndTest.transactionally).futureValue

result shouldBe List(
Map(
"address" -> Some("0x1"),
"block_number" -> Some(2),
"asof" -> Some(new Timestamp(2)),
"r" -> Some(1)
)
)
}

"get the accounts balance of an account at a specific timestamp" in {
val accountsHistoryRows = List(
AccountsHistoryRow(
address = "0x1",
blockHash = "0x1",
blockNumber = 1,
balance = BigDecimal("1.0"),
asof = new Timestamp(1)
),
AccountsHistoryRow(
address = "0x2",
blockHash = "0x2",
blockNumber = 2,
balance = BigDecimal("2.0"),
asof = new Timestamp(2)
),
AccountsHistoryRow(
address = "0x1",
blockHash = "0x3",
blockNumber = 3,
balance = BigDecimal("3.0"),
asof = new Timestamp(3)
)
)

val populateAndTest = for {
_ <- Tables.AccountsHistory ++= accountsHistoryRows
found <- sut.selectWithPredicates(
"ethereum",
table = Tables.AccountsHistory.baseTableRow.tableName,
columns = List(SimpleField("address"), SimpleField("block_number"), SimpleField("asof")),
predicates = List.empty,
ordering = List(),
aggregation = List.empty,
temporalPartition = Some("address"),
snapshot = Some(Snapshot("asof", new Timestamp(2))),
outputType = OutputType.json,
limit = 10
)
} yield found

val result = dbHandler.run(populateAndTest.transactionally).futureValue

result shouldBe List(
Map(
"address" -> Some("0x1"),
"block_number" -> Some(1),
"asof" -> Some(new Timestamp(1)),
"r" -> Some(1)
),
Map(
"address" -> Some("0x2"),
"block_number" -> Some(2),
"asof" -> Some(new Timestamp(2)),
"r" -> Some(1)
)
)
}
}
}
object EthereumDataOperationsTest {
Expand Down

0 comments on commit 30b7a4d

Please sign in to comment.