Skip to content

Commit

Permalink
Merge pull request #1505 from novasamatech/rc/7.12
Browse files Browse the repository at this point in the history
Rc/7.12
  • Loading branch information
valentunn committed May 7, 2024
2 parents d8bee70 + 63a2d23 commit 9c6efd6
Show file tree
Hide file tree
Showing 30 changed files with 331 additions and 91 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
buildscript {
ext {
// App version
versionName = '7.11.2'
versionCode = 131
versionName = '7.12.0'
versionCode = 132

applicationId = "io.novafoundation.nova"
releaseApplicationSuffix = "market"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ typealias FixedI64 = BigDecimal

const val PERBILL_MANTISSA_SIZE = 9
const val PERMILL_MANTISSA_SIZE = 6
const val PERQUINTILL_MANTISSA_SIZE = 18

@HelperBinding
fun bindPerbillNumber(value: BigInteger, mantissa: Int = PERBILL_MANTISSA_SIZE): Perbill {
Expand All @@ -34,3 +35,7 @@ fun bindPerbillTyped(dynamic: Any?, mantissa: Int = PERBILL_MANTISSA_SIZE): Perb
fun bindPermill(dynamic: Any?): PerbillTyped {
return bindPerbillTyped(dynamic, mantissa = PERMILL_MANTISSA_SIZE)
}

fun BigInteger.asPerQuintill(): PerbillTyped {
return PerbillTyped(toBigDecimal(scale = PERQUINTILL_MANTISSA_SIZE).toDouble())
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ class LongMathConverters {

@TypeConverter
fun toBigInteger(balance: String?): BigInteger? {
return balance?.let { BigInteger(it) }
return balance?.let {
// When using aggregates like SUM in SQL queries, SQLite might return the result in a scientific notation especially if aggregation is done
// BigInteger, which is stored as a string and SQLite casts it to REAL which causing the scientific notation on big numbers
// This can be avoided by adjusting the query but we keep the fallback to BigDecimal parsing here anyways to avoid unpleasant crashes
// It doesn't bring much impact since try-catch doesn't have an overhead unless the exception is thrown
try {
BigInteger(it)
} catch (e: NumberFormatException) {
BigDecimal(it).toBigInteger()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ class BuyFeatureModule {
): BuyTokenRegistry {
return RealBuyTokenRegistry(
providers = listOf(
mercuryoProvider,
transakProvider,
banxaProvider,
mercuryoProvider
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class RealPushSettingsProvider(
sentTokensEnabled = true,
receivedTokensEnabled = true,
subscribedMetaAccounts = setOf(accountRepository.getSelectedMetaAccount().id),
stakingReward = PushSettings.ChainFeature.Concrete(emptyList()),
stakingReward = PushSettings.ChainFeature.All,
governance = emptyMap()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Validator(
val prefs: ValidatorPrefs?,
val electedInfo: ElectedInfo?,
val identity: OnChainIdentity?,
val isNovaValidator: Boolean
) : Identifiable {

class ElectedInfo(
Expand Down
4 changes: 2 additions & 2 deletions feature-staking-impl/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ android {

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

buildConfigField "String", "DASHBOARD_SUBQUERY_URL", "\"https://api.subquery.network/sq/nova-wallet/subquery-staking\""
buildConfigField "String", "GLOBAL_CONFIG_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/staking/global_config_dev.json\""
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

buildConfigField "String", "DASHBOARD_SUBQUERY_URL", "\"https://api.subquery.network/sq/nova-wallet/subquery-staking\""
buildConfigField "String", "GLOBAL_CONFIG_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/staking/global_config.json\""
}
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.novafoundation.nova.feature_staking_impl.data.config

class StakingGlobalConfig(
val multiStakingApiUrl: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.novafoundation.nova.feature_staking_impl.data.config.api

import io.novafoundation.nova.feature_staking_impl.BuildConfig
import io.novafoundation.nova.feature_staking_impl.data.config.api.response.StakingGlobalConfigRemote
import retrofit2.http.GET

interface StakingGlobalConfigApi {

@GET(BuildConfig.GLOBAL_CONFIG_URL)
suspend fun getStakingGlobalConfig(): StakingGlobalConfigRemote
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.novafoundation.nova.feature_staking_impl.data.config.api.response

class StakingGlobalConfigRemote(
val multiStakingApiUrl: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import io.novafoundation.nova.feature_staking_impl.data.dashboard.network.stats.
import io.novafoundation.nova.feature_staking_impl.data.dashboard.network.stats.api.StakingStatsResponse.WithStakingId
import io.novafoundation.nova.feature_staking_impl.data.dashboard.network.stats.api.StakingStatsRewards
import io.novafoundation.nova.feature_staking_impl.data.dashboard.network.stats.api.mapSubQueryIdToStakingType
import io.novafoundation.nova.feature_staking_impl.data.repository.StakingGlobalConfigRepository
import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance
import io.novafoundation.nova.runtime.ext.UTILITY_ASSET_ID
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
Expand All @@ -28,7 +29,7 @@ interface StakingStatsDataSource {

class RealStakingStatsDataSource(
private val api: StakingStatsApi,
private val dashboardApiUrl: String,
private val stakingGlobalConfigRepository: StakingGlobalConfigRepository
) : StakingStatsDataSource {

override suspend fun fetchStakingStats(
Expand All @@ -37,6 +38,7 @@ class RealStakingStatsDataSource(
): MultiChainStakingStats = withContext(Dispatchers.IO) {
retryUntilDone {
val request = StakingStatsRequest(stakingAccounts, stakingChains)
val dashboardApiUrl = stakingGlobalConfigRepository.getStakingGlobalConfig().multiStakingApiUrl
val response = api.fetchStakingStats(request, dashboardApiUrl).data

val earnings = response.stakingApies.associatedById()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class FixedKnownNovaPools : KnownNovaPools {
override val novaPoolIds: Set<Pair<ChainId, PoolId>> = setOf(
key(Chain.Geneses.POLKADOT, 54),
key(Chain.Geneses.KUSAMA, 160),
key(Chain.Geneses.ALEPH_ZERO, 74)
key(Chain.Geneses.ALEPH_ZERO, 74),
key(Chain.Geneses.VARA, 65)
)

private fun key(chainId: ChainId, poolId: Int) = chainId to PoolId(poolId)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.novafoundation.nova.feature_staking_impl.data.repository

import io.novafoundation.nova.feature_staking_impl.data.config.StakingGlobalConfig
import io.novafoundation.nova.feature_staking_impl.data.config.api.StakingGlobalConfigApi
import io.novafoundation.nova.feature_staking_impl.data.config.api.response.StakingGlobalConfigRemote
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

interface StakingGlobalConfigRepository {

suspend fun getStakingGlobalConfig(): StakingGlobalConfig
}

class RealStakingGlobalConfigRepository(
private val api: StakingGlobalConfigApi
) : StakingGlobalConfigRepository {

private val mutex = Mutex()
private var cache: StakingGlobalConfig? = null

override suspend fun getStakingGlobalConfig(): StakingGlobalConfig {
return mutex.withLock {
if (cache == null) {
cache = api.getStakingGlobalConfig().toDomain()
}

cache!!
}
}

private fun StakingGlobalConfigRemote.toDomain(): StakingGlobalConfig {
return StakingGlobalConfig(
multiStakingApiUrl = multiStakingApiUrl
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.novafoundation.nova.feature_staking_impl.data.repository

import io.novafoundation.nova.common.data.network.runtime.binding.asPerQuintill
import io.novafoundation.nova.common.utils.Perbill
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import io.novafoundation.nova.runtime.multiNetwork.getSocket
import io.novasama.substrate_sdk_android.wsrpc.SocketService
import io.novasama.substrate_sdk_android.wsrpc.executeAsync
import io.novasama.substrate_sdk_android.wsrpc.mappers.nonNull
import io.novasama.substrate_sdk_android.wsrpc.mappers.pojo
import io.novasama.substrate_sdk_android.wsrpc.request.runtime.RuntimeRequest
import java.math.BigInteger

interface VaraRepository {

suspend fun getVaraInflation(chainId: ChainId): Perbill
}

class RealVaraRepository(
private val chainRegistry: ChainRegistry
) : VaraRepository {

override suspend fun getVaraInflation(chainId: ChainId): Perbill {
return chainRegistry.getSocket(chainId).inflationInfo().inflation.asPerQuintill()
}

private suspend fun SocketService.inflationInfo(): InflationInfo {
return executeAsync(InflationInfoRequest(), mapper = pojo<InflationInfo>().nonNull())
}

private class InflationInfoRequest : RuntimeRequest(
method = "stakingRewards_inflationInfo",
params = emptyList()
)

private class InflationInfo(val inflation: BigInteger)
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,61 @@
package io.novafoundation.nova.feature_staking_impl.data.validators

import io.novafoundation.nova.common.utils.toHexAccountId
import io.novafoundation.nova.runtime.ext.Geneses
import io.novafoundation.nova.common.utils.filterNotNull
import io.novafoundation.nova.runtime.ext.accountIdOf
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import io.novafoundation.nova.runtime.multiNetwork.chainsById
import io.novasama.substrate_sdk_android.extensions.toHexString
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

interface KnownNovaValidators {

fun getValidatorIds(chainId: ChainId): Set<String>
suspend fun getValidatorIds(chainId: ChainId): List<String>
}

class FixedKnownNovaValidators : KnownNovaValidators {
class RemoteKnownNovaValidators(
private val validatorsApi: NovaValidatorsApi,
private val chainRegistry: ChainRegistry,
) : KnownNovaValidators {

private val novaValidators by lazy {
val sharedAccounts = sharedValidatorsAccountIdsHex()
private var validatorsByNetwork: Map<String, List<String>>? = null
private val validatorsMutex = Mutex()

mapOf(
Chain.Geneses.POLKADOT to sharedAccounts,
Chain.Geneses.KUSAMA to kusamaValidators(),
Chain.Geneses.ALEPH_ZERO to sharedAccounts
)
override suspend fun getValidatorIds(chainId: ChainId): List<String> {
return getValidators()[chainId].orEmpty()
}

override fun getValidatorIds(chainId: ChainId): Set<String> {
return novaValidators[chainId].orEmpty()
private suspend fun getValidators(): Map<String, List<String>> {
return validatorsMutex.withLock {
if (validatorsByNetwork == null) {
validatorsByNetwork = fetchValidators()
}

requireNotNull(validatorsByNetwork)
}
}

private suspend fun fetchValidators(): Map<String, List<String>> {
return runCatching {
val chainsById = chainRegistry.chainsById()

validatorsApi.getValidators().mapValues { (chainId, addresses) ->
chainsById[chainId]?.let { chain ->
addresses.convertAddressesToAccountIds(chain)
}
}.filterNotNull()
}.getOrDefault(emptyMap())
}

private fun sharedValidatorsAccountIdsHex(): Set<String> {
return setOf(
"127zarPDhVzmCXVQ7Kfr1yyaa9wsMuJ74GJW9Q7ezHfQEgh6".toHexAccountId()
)
private fun List<String>.convertAddressesToAccountIds(chain: Chain): List<String> {
return mapNotNull {
chain.tryConvertAddressToAccountIdHex(it)
}
}

private fun kusamaValidators(): Set<String> {
return setOf(
"DhK6qU2U5kDWeJKvPRtmnWRs8ETUGZ9S9QmNmQFuzrNoKm4".toHexAccountId(),
"EtETk1FbrDg7FoAfkREuXT7xHxCjbEf28sBvWf6zfB5wFyV".toHexAccountId()
)
private fun Chain.tryConvertAddressToAccountIdHex(address: String): String? {
return runCatching { accountIdOf(address).toHexString() }.getOrNull()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.novafoundation.nova.feature_staking_impl.data.validators

import retrofit2.http.GET

interface NovaValidatorsApi {

@GET("https://raw.githubusercontent.com/novasamatech/nova-utils/master/staking/nova_validators.json")
suspend fun getValidators(): Map<String, List<String>>
}

0 comments on commit 9c6efd6

Please sign in to comment.