Skip to content

Commit

Permalink
move logic to use new flow structure, move most business logic out of…
Browse files Browse the repository at this point in the history
… scheduler and into service
  • Loading branch information
nullpointer0x00 committed Oct 8, 2024
1 parent 5129dd8 commit d542192
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,27 +226,26 @@ object AssetPricingTable : IdTable<Int>(name = "asset_pricing") {
class AssetPricingRecord(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<AssetPricingRecord>(AssetPricingTable) {

private fun findUnique(data: AssetPricing) = transaction {
private fun findUnique(markerDenom: String, pricingDenom: String): AssetPricingRecord? = transaction {
AssetPricingRecord.find {
(AssetPricingTable.denom eq data.markerDenom) and
(AssetPricingTable.pricingDenom eq data.priceDenomination)
(AssetPricingTable.denom eq markerDenom) and
(AssetPricingTable.pricingDenom eq pricingDenom)
}
.limit(1)
.firstOrNull()
}

fun upsert(markerId: Int, data: AssetPricing) = transaction {
findUnique(data)?.apply {
this.pricing = data.usdPrice ?: data.price!!
this.lastUpdated = data.priceTimestamp.toDateTime()
this.data = data
fun upsert(markerId: Int, markerDenom:String, pricingDenom: String, pricingAmount:BigDecimal, timestamp :DateTime) = transaction {

Check failure on line 237 in service/src/main/kotlin/io/provenance/explorer/domain/entities/Markers.kt

View workflow job for this annotation

GitHub Actions / ktlint

Missing spacing after ":"

Check failure on line 237 in service/src/main/kotlin/io/provenance/explorer/domain/entities/Markers.kt

View workflow job for this annotation

GitHub Actions / ktlint

Missing spacing after ":"

Check failure on line 237 in service/src/main/kotlin/io/provenance/explorer/domain/entities/Markers.kt

View workflow job for this annotation

GitHub Actions / ktlint

Unexpected spacing before ":"

Check failure on line 237 in service/src/main/kotlin/io/provenance/explorer/domain/entities/Markers.kt

View workflow job for this annotation

GitHub Actions / ktlint

Missing spacing after ":"
findUnique(markerDenom, pricingDenom)?.apply {
this.pricing = pricingAmount
this.lastUpdated = timestamp
} ?: AssetPricingTable.insert {
it[this.markerId] = markerId
it[this.markerAddress] = data.markerAddress
it[this.denom] = data.markerDenom
it[this.pricing] = data.usdPrice ?: data.price!!
it[this.pricingDenom] = data.priceDenomination
it[this.lastUpdated] = data.priceTimestamp.toDateTime()
it[this.data] = data
// it[this.markerAddress] = data.markerAddress
it[this.denom] = markerDenom
it[this.pricing] = pricingAmount
it[this.pricingDenom] = pricingDenom
it[this.lastUpdated] = timestamp
// it[this.data] = data
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,81 @@ import io.ktor.client.request.parameter
import io.provenance.explorer.KTOR_CLIENT_JAVA
import io.provenance.explorer.config.ExplorerProperties
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_DECIMAL_PLACES
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_MULTIPLIER
import io.provenance.explorer.domain.core.logger
import io.provenance.explorer.domain.entities.AssetPricingRecord
import io.provenance.explorer.domain.entities.MarkerCacheRecord
import io.provenance.explorer.domain.entities.MarkerCacheTable
import io.provenance.explorer.domain.extensions.toDateTime
import io.provenance.explorer.domain.models.explorer.AssetPricing
import io.provenance.explorer.grpc.flow.FlowApiGrpcClient
import io.provenance.explorer.model.base.USD_LOWER
import io.provenance.explorer.model.base.USD_UPPER
import io.provenance.marker.v1.MarkerStatus
import kotlinx.coroutines.runBlocking
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import org.joda.time.DateTime
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.time.OffsetDateTime
import java.time.ZoneOffset

@Service
class PricingService(
private val props: ExplorerProperties,
private val tokenService: TokenService
private val tokenService: TokenService,
private val assetService: AssetService,
private val flowApiGrpcClient: FlowApiGrpcClient
) {
protected val logger = logger(PricingService::class)

private var lastRunTime: OffsetDateTime? = null

fun updateAssetPricingFromLatestNav(now: OffsetDateTime) = runBlocking {
val fromDate = lastRunTime
logger.info("Updating asset pricing, last run at: $fromDate")

val latestPrices = flowApiGrpcClient.getLatestNavPrices(
priceDenom = USD_LOWER,
includeMarkers = true,
includeScopes = true,
fromDate = fromDate?.toDateTime(),
limit = 100000
)

latestPrices.forEach { price ->
if (price.denom != UTILITY_TOKEN) {
val marker = assetService.getAssetRaw(price.denom)
insertAssetPricing(
marker = marker,
markerDenom = price.denom,
pricingDenom = price.priceDenom,
pricingAmount = BigDecimal(price.priceAmount).setScale(3).divide(BigDecimal(1000)),
timestamp = DateTime.now() // Use the appropriate timestamp here
)
} else {
// val cmcPrice = tokenService.getTokenLatest()?.quote?.get(USD_UPPER)?.price?.let {
// val scale = it.scale()
// it.setScale(scale + UTILITY_TOKEN_BASE_DECIMAL_PLACES)
// .div(UTILITY_TOKEN_BASE_MULTIPLIER)
// }
// val newPriceObj = price.copy(usdPrice = cmcPrice ?: price.usdPrice)
// val marker = assetService.getAssetRaw(price.markerDenom)
// insertAssetPricing(
// marker = marker,
// markerDenom = price.markerDenom,
// pricingDenom = price.priceDenom,
// pricingAmount = newPriceObj.usdPrice!!,
// timestamp = DateTime.now()
// )
}
}
lastRunTime = now
}

fun getTotalAum() = runBlocking {
val baseMap = transaction {
MarkerCacheRecord.find {
Expand Down Expand Up @@ -55,8 +110,8 @@ class PricingService(

fun getPricingInfoSingle(denom: String) = AssetPricingRecord.findByDenom(denom)?.pricing

fun insertAssetPricing(marker: Pair<EntityID<Int>, MarkerCacheRecord>, data: AssetPricing) = transaction {
marker.first.value.let { AssetPricingRecord.upsert(it, data) }
fun insertAssetPricing(marker: Pair<EntityID<Int>, MarkerCacheRecord>, markerDenom:String, pricingDenom: String, pricingAmount:BigDecimal, timestamp : DateTime) = transaction {
marker.first.value.let { AssetPricingRecord.upsert(it, markerDenom, pricingDenom, pricingAmount, timestamp) }
}

fun getPricingAsync(time: String, comingFrom: String) = runBlocking {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import cosmos.authz.v1beta1.msgGrant
import cosmos.authz.v1beta1.msgRevoke
import io.provenance.explorer.config.ExplorerProperties
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_DECIMAL_PLACES
import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_MULTIPLIER
import io.provenance.explorer.domain.core.logger
import io.provenance.explorer.domain.entities.BlockCacheRecord
import io.provenance.explorer.domain.entities.BlockTxCountsCacheRecord
Expand Down Expand Up @@ -38,9 +36,7 @@ import io.provenance.explorer.domain.extensions.startOfDay
import io.provenance.explorer.domain.extensions.toDateTime
import io.provenance.explorer.grpc.extensions.getMsgSubTypes
import io.provenance.explorer.grpc.extensions.getMsgType
import io.provenance.explorer.model.base.USD_UPPER
import io.provenance.explorer.service.AccountService
import io.provenance.explorer.service.AssetService
import io.provenance.explorer.service.BlockService
import io.provenance.explorer.service.CacheService
import io.provenance.explorer.service.ExplorerService
Expand Down Expand Up @@ -74,7 +70,6 @@ import javax.annotation.PostConstruct
class ScheduledTaskService(
private val props: ExplorerProperties,
private val blockService: BlockService,
private val assetService: AssetService,
private val govService: GovService,
private val blockAndTxProcessor: BlockAndTxProcessor,
private val explorerService: ExplorerService,
Expand Down Expand Up @@ -252,34 +247,41 @@ class ScheduledTaskService(
}.let { if (it.isNotEmpty()) BlockTxRetryRecord.deleteRecords(it) }
}

// @Scheduled(cron = "0 0/15 * * * ?") // Every 15 minutes
// fun updateAssetPricing() {
// logger.info("Updating asset pricing")
// val key = CacheKeys.PRICING_UPDATE.key
// val now = OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()
// cacheService.getCacheValue(key)!!.let { cache ->
// pricingService.getPricingAsync(cache.cacheValue!!, "async pricing update").forEach { price ->
// // don't set price from PE
// if (price.markerDenom != UTILITY_TOKEN) {
// assetService.getAssetRaw(price.markerDenom).let { pricingService.insertAssetPricing(it, price) }
// } else {
// // Pull price from CMC, calculate to the true base denom price
// val cmcPrice =
// tokenService.getTokenLatest()?.quote?.get(USD_UPPER)?.price
// ?.let {
// val scale = it.scale()
// it.setScale(scale + UTILITY_TOKEN_BASE_DECIMAL_PLACES)
// .div(UTILITY_TOKEN_BASE_MULTIPLIER)
// }
// // If CMC data exists, use that, else use the PE value
// val newPriceObj = price.copy(usdPrice = cmcPrice ?: price.usdPrice!!)
// // Save it
// assetService.getAssetRaw(price.markerDenom).let {
// pricingService.insertAssetPricing(it, newPriceObj)
// }
// }
// }
// }.let { cacheService.updateCacheValue(key, now) }
// }

@Scheduled(cron = "0 0/15 * * * ?") // Every 15 minutes
fun updateAssetPricing() {
logger.info("Updating asset pricing")
val key = CacheKeys.PRICING_UPDATE.key
val now = OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()
cacheService.getCacheValue(key)!!.let { cache ->
pricingService.getPricingAsync(cache.cacheValue!!, "async pricing update").forEach { price ->
// don't set price from PE
if (price.markerDenom != UTILITY_TOKEN) {
assetService.getAssetRaw(price.markerDenom).let { pricingService.insertAssetPricing(it, price) }
} else {
// Pull price from CMC, calculate to the true base denom price
val cmcPrice =
tokenService.getTokenLatest()?.quote?.get(USD_UPPER)?.price
?.let {
val scale = it.scale()
it.setScale(scale + UTILITY_TOKEN_BASE_DECIMAL_PLACES)
.div(UTILITY_TOKEN_BASE_MULTIPLIER)
}
// If CMC data exists, use that, else use the PE value
val newPriceObj = price.copy(usdPrice = cmcPrice ?: price.usdPrice!!)
// Save it
assetService.getAssetRaw(price.markerDenom).let {
pricingService.insertAssetPricing(it, newPriceObj)
}
}
}
}.let { cacheService.updateCacheValue(key, now) }
val now = OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC)
pricingService.updateAssetPricingFromLatestNav(now)
}

@Scheduled(cron = "0 0/15 * * * ?") // Every 15 minutes
Expand Down

0 comments on commit d542192

Please sign in to comment.