-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove flow database dependency (#574)
* add flyway nav events table * add nav events domain object * add queries * add queries add tests * add nav fetcher * refactor fetchers, add utils file for shared methods, add tests * add service to read marker nav events, add tests * refactor test in prep for more * add id to nav table * add scope event parsing * add internal nav datasource * fix a few things, add tests * fix lint * fix database setup for tests * fix lint * update sql script * fix test * tx hash can be null * wire in nav service * add temp log * fix logging * add temp log * fix lint * update loggin * fix lint * fix millis to epoch * remove temporary logging * remove unused import * clean up a few things * add change log * remove some old references * fix lint
- Loading branch information
1 parent
54bef14
commit 3aaddb0
Showing
25 changed files
with
12,071 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
database/src/main/resources/db/migration/V1_96__Add_nav_event_table.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
SELECT 'Add nav events table' AS comment; | ||
|
||
CREATE TABLE IF NOT EXISTS nav_events ( | ||
id SERIAL PRIMARY KEY, | ||
block_height INT NOT NULL, | ||
block_time TIMESTAMP NOT NULL, | ||
tx_hash TEXT, | ||
event_order INT, | ||
event_type TEXT, | ||
scope_id TEXT, | ||
denom TEXT, | ||
price_amount BIGINT, | ||
price_denom TEXT, | ||
volume BIGINT, | ||
source TEXT, | ||
UNIQUE (block_height, tx_hash, event_order) | ||
); | ||
|
||
CREATE INDEX IF NOT EXISTS idx_nav_events_block_time ON nav_events(block_time); | ||
CREATE INDEX IF NOT EXISTS idx_nav_events_denom ON nav_events(denom); | ||
CREATE INDEX IF NOT EXISTS idx_nav_events_scope_id ON nav_events(scope_id); |
261 changes: 261 additions & 0 deletions
261
service/src/main/kotlin/io/provenance/explorer/domain/entities/NavEvents.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
package io.provenance.explorer.domain.entities | ||
|
||
import io.provenance.explorer.domain.extensions.execAndMap | ||
import io.provenance.explorer.domain.extensions.toDateTime | ||
import org.jetbrains.exposed.dao.IntEntity | ||
import org.jetbrains.exposed.dao.IntEntityClass | ||
import org.jetbrains.exposed.dao.id.EntityID | ||
import org.jetbrains.exposed.dao.id.IntIdTable | ||
import org.jetbrains.exposed.sql.ColumnType | ||
import org.jetbrains.exposed.sql.VarCharColumnType | ||
import org.jetbrains.exposed.sql.insertIgnore | ||
import org.jetbrains.exposed.sql.jodatime.DateColumnType | ||
import org.jetbrains.exposed.sql.jodatime.datetime | ||
import org.jetbrains.exposed.sql.transactions.transaction | ||
import org.joda.time.DateTime | ||
import java.sql.ResultSet | ||
|
||
object NavEventsTable : IntIdTable(name = "nav_events") { | ||
val blockHeight = integer("block_height") | ||
val blockTime = datetime("block_time") | ||
val txHash = text("tx_hash") | ||
val eventOrder = integer("event_order") | ||
val eventType = text("event_type") | ||
val scopeId = text("scope_id").nullable() | ||
val denom = text("denom").nullable() | ||
val priceAmount = long("price_amount").nullable() | ||
val priceDenom = text("price_denom").nullable() | ||
val volume = long("volume") | ||
val dataSource = text("source") | ||
|
||
init { | ||
uniqueIndex("nav_events_unique_idx", blockHeight, txHash, eventOrder) | ||
} | ||
} | ||
|
||
class NavEventsRecord(id: EntityID<Int>) : IntEntity(id) { | ||
companion object : IntEntityClass<NavEventsRecord>(NavEventsTable) { | ||
fun insert( | ||
blockHeight: Int, | ||
blockTime: DateTime, | ||
txHash: String, | ||
eventOrder: Int, | ||
eventType: String, | ||
scopeId: String?, | ||
denom: String?, | ||
priceAmount: Long?, | ||
priceDenom: String?, | ||
volume: Long, | ||
source: String | ||
) = transaction { | ||
NavEventsTable.insertIgnore { | ||
it[this.blockHeight] = blockHeight | ||
it[this.blockTime] = blockTime | ||
it[this.txHash] = txHash | ||
it[this.eventOrder] = eventOrder | ||
it[this.eventType] = eventType | ||
it[this.scopeId] = scopeId | ||
it[this.denom] = denom | ||
it[this.priceAmount] = priceAmount | ||
it[this.priceDenom] = priceDenom | ||
it[this.volume] = volume | ||
it[this.dataSource] = source | ||
} | ||
} | ||
|
||
fun getNavEvents( | ||
denom: String? = null, | ||
scopeId: String? = null, | ||
fromDate: DateTime? = null, | ||
toDate: DateTime? = null, | ||
priceDenoms: List<String>? = null | ||
) = transaction { | ||
var query = """ | ||
SELECT block_height, block_time, tx_hash, event_order, | ||
event_type, scope_id, denom, price_amount, price_denom, volume, source | ||
FROM nav_events | ||
WHERE 1=1 | ||
""".trimIndent() | ||
|
||
val args = mutableListOf<Pair<ColumnType, *>>() | ||
|
||
denom?.let { | ||
query += " AND denom = ?" | ||
args.add(Pair(VarCharColumnType(), it)) | ||
} ?: scopeId?.let { | ||
query += " AND scope_id = ?" | ||
args.add(Pair(VarCharColumnType(), it)) | ||
} | ||
|
||
fromDate?.let { | ||
query += " AND block_time >= ?" | ||
args.add(Pair(DateColumnType(true), it)) | ||
} | ||
|
||
toDate?.let { | ||
query += " AND block_time <= ?" | ||
args.add(Pair(DateColumnType(true), it)) | ||
} | ||
|
||
priceDenoms?.let { | ||
if (it.isNotEmpty()) { | ||
val placeholders = it.joinToString(", ") { "?" } | ||
query += " AND price_denom IN ($placeholders)" | ||
it.forEach { denom -> | ||
args.add(Pair(VarCharColumnType(), denom)) | ||
} | ||
} | ||
} | ||
|
||
query += " ORDER BY block_height DESC, event_order DESC" | ||
|
||
query.execAndMap(args) { | ||
NavEvent( | ||
it.getInt("block_height"), | ||
it.getTimestamp("block_time").toDateTime(), | ||
it.getString("tx_hash"), | ||
it.getInt("event_order"), | ||
it.getString("event_type"), | ||
it.getString("scope_id"), | ||
it.getString("denom"), | ||
it.getLong("price_amount"), | ||
it.getString("price_denom"), | ||
it.getLong("volume"), | ||
it.getString("source") | ||
) | ||
} | ||
} | ||
|
||
fun getLatestNavEvents( | ||
priceDenom: String, | ||
includeMarkers: Boolean, | ||
includeScopes: Boolean, | ||
fromDate: DateTime? = null | ||
) = transaction { | ||
require(includeMarkers || includeScopes) { "Either includeMarkers or includeScope must be true" } | ||
|
||
var query = """ | ||
SELECT DISTINCT ON (denom, scope_id) | ||
block_height, block_time, tx_hash, event_order, event_type, | ||
scope_id, denom, price_amount, price_denom, volume, source | ||
FROM nav_events | ||
WHERE price_denom = ? | ||
""".trimIndent() | ||
|
||
val args = mutableListOf<Pair<ColumnType, *>>( | ||
Pair(VarCharColumnType(), priceDenom) | ||
) | ||
|
||
fromDate?.let { | ||
query += " AND block_time >= ?" | ||
args.add(Pair(DateColumnType(true), it)) | ||
} | ||
|
||
when { | ||
includeMarkers && includeScopes -> query += " AND (denom IS NOT NULL OR scope_id IS NOT NULL)" | ||
includeMarkers -> query += " AND denom IS NOT NULL" | ||
includeScopes -> query += " AND scope_id IS NOT NULL" | ||
} | ||
|
||
query += " ORDER BY denom, scope_id, block_height DESC, event_order DESC" | ||
|
||
query.execAndMap(args) { | ||
NavEvent( | ||
it.getInt("block_height"), | ||
it.getTimestamp("block_time").toDateTime(), | ||
it.getString("tx_hash"), | ||
it.getInt("event_order"), | ||
it.getString("event_type"), | ||
it.getString("scope_id"), | ||
it.getString("denom"), | ||
it.getLong("price_amount"), | ||
it.getString("price_denom"), | ||
it.getLong("volume"), | ||
it.getString("source") | ||
) | ||
} | ||
} | ||
} | ||
|
||
var blockHeight by NavEventsTable.blockHeight | ||
var blockTime by NavEventsTable.blockTime | ||
var txHash by NavEventsTable.txHash | ||
var eventOrder by NavEventsTable.eventOrder | ||
var eventType by NavEventsTable.eventType | ||
var scopeId by NavEventsTable.scopeId | ||
var denom by NavEventsTable.denom | ||
var priceAmount by NavEventsTable.priceAmount | ||
var priceDenom by NavEventsTable.priceDenom | ||
var volume by NavEventsTable.volume | ||
var source by NavEventsTable.dataSource | ||
} | ||
|
||
data class NavPrice( | ||
val blockHeight: Int, | ||
val blockTime: DateTime, | ||
val txHash: String, | ||
val eventOrder: Int, | ||
val eventType: String, | ||
val scopeId: String?, | ||
val denom: String, | ||
val priceAmount: Long, | ||
val priceDenom: String, | ||
val volume: Long, | ||
val source: String | ||
) { | ||
constructor(rs: ResultSet) : this( | ||
rs.getInt("block_height"), | ||
rs.getTimestamp("block_time").toDateTime(), | ||
rs.getString("tx_hash"), | ||
rs.getInt("event_order"), | ||
rs.getString("event_type"), | ||
rs.getString("scope_id"), | ||
rs.getString("denom"), | ||
rs.getLong("price_amount"), | ||
rs.getString("price_denom"), | ||
rs.getLong("volume"), | ||
rs.getString("source") | ||
) | ||
|
||
constructor(record: NavEventsRecord) : this( | ||
record.blockHeight, | ||
record.blockTime, | ||
record.txHash, | ||
record.eventOrder, | ||
record.eventType, | ||
record.scopeId, | ||
record.denom!!, | ||
record.priceAmount!!, | ||
record.priceDenom!!, | ||
record.volume, | ||
record.source | ||
) | ||
} | ||
|
||
data class NavEvent( | ||
val blockHeight: Int, | ||
val blockTime: DateTime, | ||
val txHash: String?, | ||
val eventOrder: Int, | ||
val eventType: String, | ||
val scopeId: String?, | ||
val denom: String?, | ||
val priceAmount: Long?, | ||
val priceDenom: String?, | ||
val volume: Long, | ||
val source: String | ||
) { | ||
constructor(record: NavEventsRecord) : this( | ||
record.blockHeight, | ||
record.blockTime, | ||
record.txHash, | ||
record.eventOrder, | ||
record.eventType, | ||
record.scopeId, | ||
record.denom, | ||
record.priceAmount, | ||
record.priceDenom, | ||
record.volume, | ||
record.source | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.