Skip to content

Commit

Permalink
Support case with bag list score being greater then latest bag (#1060)
Browse files Browse the repository at this point in the history
  • Loading branch information
valentunn authored Aug 11, 2023
1 parent 8dbeead commit 066b8b9
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ val BigDecimal.isNonNegative: Boolean
val BigInteger.isZero: Boolean
get() = signum() == 0

inline fun <T : Comparable<T>, R : Comparable<R>> ClosedRange<T>.map(mapper: (T) -> R): ClosedRange<R> {
return mapper(start)..mapper(endInclusive)
}

fun BigInteger?.orZero(): BigInteger = this ?: BigInteger.ZERO
fun BigDecimal?.orZero(): BigDecimal = this ?: 0.toBigDecimal()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.novafoundation.nova.common.utils

interface SemiUnboundedRange<T : Comparable<T>> {

val start: T

val endInclusive: T?
}

infix operator fun <T : Comparable<T>> T.rangeTo(another: T?): SemiUnboundedRange<T> {
return ComparableSemiUnboundedRange(this, another)
}

inline fun <T : Comparable<T>, R : Comparable<R>> SemiUnboundedRange<T>.map(mapper: (T) -> R): SemiUnboundedRange<R> {
return mapper(start)..endInclusive?.let(mapper)
}

class ComparableSemiUnboundedRange<T : Comparable<T>>(override val start: T, override val endInclusive: T?) : SemiUnboundedRange<T>
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ fun minimumStake(

val lastElectedBag = bagListLocator.bagBoundaries(bagListScoreConverter.scoreOf(minElectedStake))

val nextBagThreshold = bagListScoreConverter.balanceOf(lastElectedBag.endInclusive)
val nextBagThreshold = bagListScoreConverter.balanceOf(lastElectedBag.endInclusive ?: lastElectedBag.start)
val epsilon = Balance.ONE

return nextBagThreshold + epsilon
val nextBagRequiredAmount = nextBagThreshold + epsilon

return nextBagRequiredAmount.coerceAtLeast(minElectedStake)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package io.novafoundation.nova.feature_staking_impl.domain.bagList

import io.novafoundation.nova.common.utils.rangeTo
import io.novafoundation.nova.feature_staking_impl.domain.model.BagListNode.Score

interface BagListLocator {

fun bagBoundaries(userScore: Score): BagScoreBoundaries

fun nextBagBoundaries(previous: BagScoreBoundaries): BagScoreBoundaries
}

typealias BagScoreBoundaries = ClosedRange<Score>

fun BagListLocator(thresholds: List<Score>): BagListLocator = RealBagListLocator(thresholds)

private class RealBagListLocator(private val thresholds: List<Score>) : BagListLocator {
Expand All @@ -21,15 +18,8 @@ private class RealBagListLocator(private val thresholds: List<Score>) : BagListL
return bagBoundariesAt(bagIndex)
}

override fun nextBagBoundaries(previous: BagScoreBoundaries): BagScoreBoundaries {
val previousBagIndex = notionalBagIndexFor(previous.endInclusive)
val nextBagIndex = (previousBagIndex + 1).coerceAtMost(thresholds.size - 1)

return bagBoundariesAt(nextBagIndex)
}

private fun bagBoundariesAt(index: Int): BagScoreBoundaries {
val bagUpper = thresholds[index]
val bagUpper = thresholds.getOrNull(index)
val bagLower = if (index > 0) thresholds[index - 1] else Score.zero()

return bagLower..bagUpper
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.novafoundation.nova.feature_staking_impl.domain.bagList

import io.novafoundation.nova.common.utils.SemiUnboundedRange
import io.novafoundation.nova.feature_staking_impl.domain.model.BagListNode.Score

typealias BagScoreBoundaries = SemiUnboundedRange<Score>
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.novafoundation.nova.feature_staking_impl.domain.bagList.rebag

import io.novafoundation.nova.common.utils.SemiUnboundedRange
import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance

typealias BagAmountBoundaries = ClosedRange<Balance>
typealias BagAmountBoundaries = SemiUnboundedRange<Balance>

class RebagMovement(
val from: BagAmountBoundaries,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.novafoundation.nova.feature_wallet_api.presentation.formatters

import io.novafoundation.nova.common.utils.SemiUnboundedRange
import io.novafoundation.nova.common.utils.formatting.format
import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance
import io.novafoundation.nova.feature_wallet_api.domain.model.amountFromPlanks
Expand All @@ -12,19 +13,29 @@ fun BigInteger.formatPlanks(chainAsset: Chain.Asset): String {
return chainAsset.amountFromPlanks(this).formatTokenAmount(chainAsset)
}

fun ClosedRange<Balance>.formatPlanksRange(chainAsset: Chain.Asset): String {
fun SemiUnboundedRange<Balance>.formatPlanksRange(chainAsset: Chain.Asset): String {
val end = endInclusive
val startFormatted = chainAsset.amountFromPlanks(start).format()
val endFormatted = endInclusive.formatPlanks(chainAsset)

return "$startFormatted$endFormatted"
return if (end != null) {
val endFormatted = end.formatPlanks(chainAsset)

"$startFormatted$endFormatted"
} else {
"$startFormatted+".withTokenSymbol(chainAsset.symbol)
}
}

fun BigDecimal.formatTokenAmount(chainAsset: Chain.Asset, roundingMode: RoundingMode = RoundingMode.FLOOR): String {
return formatTokenAmount(chainAsset.symbol, roundingMode)
}

fun BigDecimal.formatTokenAmount(tokenSymbol: String, roundingMode: RoundingMode = RoundingMode.FLOOR): String {
return "${format(roundingMode)} $tokenSymbol"
return format(roundingMode).withTokenSymbol(tokenSymbol)
}

fun String.withTokenSymbol(tokenSymbol: String): String {
return "$this $tokenSymbol"
}

fun BigDecimal.formatTokenChange(chainAsset: Chain.Asset, isIncome: Boolean): String {
Expand Down

0 comments on commit 066b8b9

Please sign in to comment.