Skip to content

Commit

Permalink
correctly calculate usd price per unit with extension, add tests for …
Browse files Browse the repository at this point in the history
…extension
  • Loading branch information
nullpointer0x00 committed Oct 9, 2024
1 parent 3e4fc39 commit 248db86
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.provenance.explorer.domain.extensions

import io.provenance.explorer.model.base.USD_LOWER
import io.provlabs.flow.api.NavEvent
import java.math.BigDecimal
import java.math.RoundingMode

/**
* Calculates the USD price per unit for a NAV event.
*
* The `priceAmount` is in dollar millis (e.g., 1234 = $1.234) and is divided by the volume to get the price per unit.
* If the `priceDenom` is not "usd" or the volume is 0, it returns `BigDecimal.ZERO`.
*
* @return The USD price per unit or `BigDecimal.ZERO` if not a USD event or volume is 0.
*/
fun NavEvent.calculateUsdPricePerUnit(): BigDecimal {
if (this.priceDenom != USD_LOWER) {
return BigDecimal.ZERO
}

if (this.volume == 0L) {
return BigDecimal.ZERO
}

return BigDecimal(this.priceAmount)
.setScale(3, RoundingMode.DOWN)
.divide(BigDecimal(1000), RoundingMode.DOWN)
.divide(BigDecimal(this.volume), 3, RoundingMode.DOWN)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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.calculateUsdPricePerUnit
import io.provenance.explorer.domain.extensions.toDateTime
import io.provenance.explorer.domain.models.explorer.AssetPricing
import io.provenance.explorer.grpc.flow.FlowApiGrpcClient
Expand Down Expand Up @@ -55,7 +56,7 @@ class PricingService(
marker = marker,
markerDenom = price.denom,
pricingDenom = price.priceDenom,
pricingAmount = BigDecimal(price.priceAmount).setScale(3).divide(BigDecimal(1000)),
pricingAmount = price.calculateUsdPricePerUnit(),
timestamp = DateTime(price.blockTime * 1000)
)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.provenance.explorer.domain.extensions

import io.provlabs.flow.api.NavEvent
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.math.BigDecimal

class NavEventExtensionsKtTest {

@Test
fun `test calculateUsdPricePerUnit for flow nav events`() {
val usdDenom = "usd"
val nonUsdDenom = "non-usd"

val navEventUsdVolume1Price1 = NavEvent.newBuilder()
.setPriceAmount(1)
.setPriceDenom(usdDenom)
.setVolume(1L)
.build()

val navEventUsdVolume1Price12 = NavEvent.newBuilder()
.setPriceAmount(12)
.setPriceDenom(usdDenom)
.setVolume(1L)
.build()

val navEventUsdVolume1Price123 = NavEvent.newBuilder()
.setPriceAmount(123)
.setPriceDenom(usdDenom)
.setVolume(1L)
.build()

val navEventUsdVolume1Price1234 = NavEvent.newBuilder()
.setPriceAmount(1234)
.setPriceDenom(usdDenom)
.setVolume(1L)
.build()

val navEventNonUsd = NavEvent.newBuilder()
.setPriceAmount(1234)
.setPriceDenom(nonUsdDenom)
.setVolume(1L)
.build()

val navEventZeroVolume = NavEvent.newBuilder()
.setPriceAmount(1234)
.setPriceDenom(usdDenom)
.setVolume(0L)
.build()

assertEquals(BigDecimal("0.001"), navEventUsdVolume1Price1.calculateUsdPricePerUnit(), "Price amount 1 should be converted to 0.001")
assertEquals(BigDecimal("0.012"), navEventUsdVolume1Price12.calculateUsdPricePerUnit(), "Price amount 12 should be converted to 0.012")
assertEquals(BigDecimal("0.123"), navEventUsdVolume1Price123.calculateUsdPricePerUnit(), "Price amount 123 should be converted to 0.123")
assertEquals(BigDecimal("1.234"), navEventUsdVolume1Price1234.calculateUsdPricePerUnit(), "Price amount 1234 should be converted to 1.234")
assertEquals(BigDecimal.ZERO, navEventNonUsd.calculateUsdPricePerUnit(), "Non-USD denomination should return 0")
assertEquals(BigDecimal.ZERO, navEventZeroVolume.calculateUsdPricePerUnit(), "Zero volume should return 0")
}
}

0 comments on commit 248db86

Please sign in to comment.