feat: sync chains config, rebrand assets icon, update onboarding image

- Sync chains.json from pezkuwi-wallet-utils (staking on Asset Hub)
- Replace Nova star with Nevruz fire icon on Assets bottom nav tab
- Update onboarding welcome background image (all DPI variants)
- Fix build URLs to point to pezkuwi-wallet-utils GitHub raw
- Update staking reward calculator and era computation
- Bump version code to 159
This commit is contained in:
2026-02-10 16:03:09 +03:00
parent 62ffa5d959
commit f475ff858b
15 changed files with 2378 additions and 2463 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

After

Width:  |  Height:  |  Size: 191 KiB

@@ -7,7 +7,7 @@
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M24,12V12.315C22.039,12.625 17.834,13.352 15.767,14.142C15.029,14.426 14.442,15.008 14.153,15.74C13.357,17.797 12.625,22.028 12.315,24H11.685C11.37,22.034 10.643,17.802 9.847,15.74C9.558,15.003 8.971,14.42 8.233,14.142C6.166,13.352 1.961,12.625 0,12.315V11.685C1.961,11.375 6.166,10.648 8.233,9.858C8.971,9.574 9.558,8.992 9.847,8.26C10.643,6.203 11.375,1.972 11.685,0H12.315C12.63,1.966 13.357,6.198 14.153,8.26C14.442,8.997 15.029,9.58 15.767,9.858C17.834,10.648 22.039,11.375 24,11.685V12Z"
android:pathData="M12,2.3C13.4,5.4 16.4,7.3 17.6,10.5C18.8,13.8 17.6,17.1 16.4,19C15.2,20.9 13.4,22.3 12,22.7C10.6,22.3 8.8,20.9 7.6,19C6.4,17.1 5.2,13.8 6.4,10.5C7.6,7.3 10.6,5.4 12,2.3Z"
android:fillColor="#1F78FF"/>
</group>
</vector>
@@ -7,7 +7,7 @@
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M14.153,15.74C14.442,15.008 15.029,14.426 15.767,14.142C17.333,13.543 20.125,12.981 22.24,12.609C22.869,12.498 23.439,12.405 23.898,12.331C23.933,12.326 23.967,12.321 24,12.315V11.685C23.967,11.679 23.933,11.674 23.898,11.669C23.439,11.595 22.869,11.502 22.24,11.391C20.125,11.019 17.333,10.457 15.767,9.858C15.029,9.58 14.442,8.997 14.153,8.26C13.549,6.695 12.985,3.882 12.611,1.757C12.5,1.128 12.405,0.56 12.332,0.102C12.326,0.067 12.321,0.033 12.315,0H11.685C11.679,0.034 11.674,0.068 11.668,0.104C11.596,0.562 11.502,1.13 11.392,1.758C11.018,3.885 10.451,6.699 9.847,8.26C9.558,8.992 8.971,9.574 8.233,9.858C6.667,10.457 3.875,11.019 1.76,11.391C1.131,11.502 0.561,11.595 0.102,11.669C0.067,11.674 0.033,11.679 0,11.685V12.315C0.033,12.321 0.067,12.326 0.102,12.331C0.561,12.405 1.131,12.498 1.76,12.609C3.875,12.981 6.667,13.543 8.233,14.142C8.971,14.42 9.558,15.003 9.847,15.74C10.451,17.305 11.015,20.118 11.389,22.243C11.5,22.872 11.595,23.44 11.668,23.898C11.674,23.933 11.679,23.967 11.685,24H12.315C12.321,23.966 12.326,23.931 12.332,23.896C12.404,23.438 12.498,22.87 12.608,22.243C12.982,20.115 13.549,17.301 14.153,15.74ZM11.999,19.08C12.304,17.664 12.659,16.275 13.034,15.307L13.037,15.3C13.449,14.254 14.286,13.426 15.337,13.022L15.338,13.022C16.304,12.652 17.678,12.302 19.079,12C17.679,11.698 16.307,11.348 15.341,10.979C14.284,10.58 13.447,9.748 13.036,8.697L13.034,8.692C12.659,7.723 12.306,6.334 12.001,4.92C11.696,6.336 11.341,7.725 10.966,8.693L10.963,8.7C10.551,9.746 9.714,10.574 8.664,10.978L8.662,10.978C7.696,11.348 6.322,11.698 4.921,12C6.321,12.302 7.693,12.652 8.659,13.021C9.716,13.42 10.553,14.252 10.964,15.303L10.966,15.308C11.341,16.277 11.694,17.666 11.999,19.08Z"
android:pathData="M12,2.3C13.4,5.4 16.4,7.3 17.6,10.5C18.8,13.8 17.6,17.1 16.4,19C15.2,20.9 13.4,22.3 12,22.7C10.6,22.3 8.8,20.9 7.6,19C6.4,17.1 5.2,13.8 6.4,10.5C7.6,7.3 10.6,5.4 12,2.3ZM12,5.5C12.7,7.6 14.7,8.9 15.3,11.2C15.9,13.5 15.3,15.5 14.5,17C13.7,18.5 13,19.6 12,20.1C11,19.6 10.3,18.5 9.5,17C8.7,15.5 8.1,13.5 8.7,11.2C9.3,8.9 11.3,7.6 12,5.5Z"
android:fillColor="#ffffff"
android:fillAlpha="0.4"
android:fillType="evenOdd"/>
@@ -212,7 +212,8 @@ class StakingFeatureModule {
bagListRepository: BagListRepository,
totalIssuanceRepository: TotalIssuanceRepository,
eraTimeCalculatorFactory: EraTimeCalculatorFactory,
stakingConstantsRepository: StakingConstantsRepository
stakingConstantsRepository: StakingConstantsRepository,
chainRegistry: ChainRegistry
) = StakingSharedComputation(
stakingRepository = stakingRepository,
computationalCache = computationalCache,
@@ -221,7 +222,8 @@ class StakingFeatureModule {
bagListRepository = bagListRepository,
totalIssuanceRepository = totalIssuanceRepository,
eraTimeCalculatorFactory = eraTimeCalculatorFactory,
stakingConstantsRepository = stakingConstantsRepository
stakingConstantsRepository = stakingConstantsRepository,
chainRegistry = chainRegistry
)
@Provides
@@ -297,7 +299,8 @@ class StakingFeatureModule {
sessionRepository: SessionRepository,
chainStateRepository: ChainStateRepository,
electionsSessionRegistry: ElectionsSessionRegistry,
) = EraTimeCalculatorFactory(stakingRepository, sessionRepository, chainStateRepository, electionsSessionRegistry)
chainRegistry: ChainRegistry,
) = EraTimeCalculatorFactory(stakingRepository, sessionRepository, chainStateRepository, electionsSessionRegistry, chainRegistry)
@Provides
@FeatureScope
@@ -9,6 +9,7 @@ import io.novafoundation.nova.feature_staking_impl.data.chain
import io.novafoundation.nova.feature_staking_impl.data.repository.SessionRepository
import io.novafoundation.nova.feature_staking_impl.data.repository.consensus.ElectionsSessionRegistry
import io.novafoundation.nova.runtime.ext.timelineChainIdOrSelf
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.repository.ChainStateRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -96,6 +97,7 @@ class EraTimeCalculatorFactory(
private val sessionRepository: SessionRepository,
private val chainStateRepository: ChainStateRepository,
private val electionsSessionRegistry: ElectionsSessionRegistry,
private val chainRegistry: ChainRegistry,
) {
suspend fun create(
@@ -103,8 +105,8 @@ class EraTimeCalculatorFactory(
activeEraFlow: Flow<EraIndex>
): Flow<EraTimeCalculator> {
val stakingChain = stakingOption.chain
val stakingChainId = stakingChain.id
val timelineChainId = stakingChain.timelineChainIdOrSelf()
val timelineChain = chainRegistry.getChain(timelineChainId)
val electionsSession = electionsSessionRegistry.electionsSessionFor(stakingOption)
@@ -112,7 +114,7 @@ class EraTimeCalculatorFactory(
val sessionLength = electionsSession.sessionLength(timelineChainId)
val eraAndStartSessionIndex = activeEraFlow.map { activeEra ->
val eraStartSessionIndex = stakingRepository.eraStartSessionIndex(stakingChainId, activeEra)
val eraStartSessionIndex = stakingRepository.eraStartSessionIndex(timelineChainId, activeEra)
activeEra to eraStartSessionIndex
}
@@ -124,7 +126,7 @@ class EraTimeCalculatorFactory(
) { (activeEra, eraStartSessionIndex), currentSessionIndex, currentEpochIndex, currentSlot ->
EraTimeCalculator(
startTimeStamp = System.currentTimeMillis().toBigInteger(),
eraLength = stakingRepository.eraLength(stakingChain),
eraLength = stakingRepository.eraLength(timelineChain),
blockCreationTime = chainStateRepository.predictedBlockTime(timelineChainId),
currentSessionIndex = currentSessionIndex,
currentEpochIndex = currentEpochIndex ?: currentSessionIndex,
@@ -18,6 +18,8 @@ import io.novafoundation.nova.feature_staking_impl.domain.minimumStake
import io.novafoundation.nova.feature_staking_impl.domain.rewards.RewardCalculator
import io.novafoundation.nova.feature_staking_impl.domain.rewards.RewardCalculatorFactory
import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance
import io.novafoundation.nova.runtime.ext.timelineChainIdOrSelf
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.ChainWithAsset
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
@@ -43,15 +45,18 @@ class StakingSharedComputation(
private val bagListRepository: BagListRepository,
private val totalIssuanceRepository: TotalIssuanceRepository,
private val eraTimeCalculatorFactory: EraTimeCalculatorFactory,
private val stakingConstantsRepository: StakingConstantsRepository
private val stakingConstantsRepository: StakingConstantsRepository,
private val chainRegistry: ChainRegistry
) {
fun eraCalculatorFlow(stakingOption: StakingOption, scope: CoroutineScope): Flow<EraTimeCalculator> {
val chainId = stakingOption.assetWithChain.chain.id
val chain = stakingOption.assetWithChain.chain
val chainId = chain.id
val timelineChainId = chain.timelineChainIdOrSelf()
val key = "ERA_TIME_CALCULATOR:$chainId"
return computationalCache.useSharedFlow(key, scope) {
val activeEraFlow = activeEraFlow(chainId, scope)
val activeEraFlow = activeEraFlow(timelineChainId, scope)
eraTimeCalculatorFactory.create(stakingOption, activeEraFlow)
}
@@ -79,14 +84,17 @@ class StakingSharedComputation(
val key = "MIN_STAKE:$chainId"
return computationalCache.useSharedFlow(key, scope) {
val minBond = stakingRepository.minimumNominatorBond(chainId)
val bagListLocator = bagListRepository.bagListLocatorOrNull(chainId)
val totalIssuance = totalIssuanceRepository.getTotalIssuance(chainId)
val bagListScoreConverter = BagListScoreConverter.U128(totalIssuance)
val maxElectingVoters = bagListRepository.maxElectingVotes(chainId)
val bagListSize = bagListRepository.bagListSize(chainId)
val chain = chainRegistry.getChain(chainId)
val timelineChainId = chain.timelineChainIdOrSelf()
electedExposuresWithActiveEraFlow(chainId, scope).map { (exposures, activeEraIndex) ->
val minBond = stakingRepository.minimumNominatorBond(timelineChainId)
val bagListLocator = bagListRepository.bagListLocatorOrNull(timelineChainId)
val totalIssuance = totalIssuanceRepository.getTotalIssuance(timelineChainId)
val bagListScoreConverter = BagListScoreConverter.U128(totalIssuance)
val maxElectingVoters = bagListRepository.maxElectingVotes(timelineChainId)
val bagListSize = bagListRepository.bagListSize(timelineChainId)
electedExposuresWithActiveEraFlow(timelineChainId, scope).map { (exposures, activeEraIndex) ->
val minStake = minimumStake(
exposures = exposures.values,
minimumNominatorBond = minBond,
@@ -28,6 +28,7 @@ import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain.Asset.Staki
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain.Asset.StakingType.TURING
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain.Asset.StakingType.UNSUPPORTED
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import io.novafoundation.nova.runtime.ext.timelineChainIdOrSelf
import io.novafoundation.nova.runtime.repository.TotalIssuanceRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -48,7 +49,10 @@ class RewardCalculatorFactory(
validatorsPrefs: AccountIdMap<ValidatorPrefs?>,
scope: CoroutineScope
): RewardCalculator = withContext(Dispatchers.Default) {
val totalIssuance = totalIssuanceRepository.getTotalIssuance(stakingOption.assetWithChain.chain.id)
val timelineChainId = stakingOption.assetWithChain.chain.timelineChainIdOrSelf()
val totalIssuance = totalIssuanceRepository.getTotalIssuance(timelineChainId)
Log.d("RewardCalculatorFactory", "totalIssuance for $timelineChainId: $totalIssuance")
val validators = exposures.keys.mapNotNull { accountIdHex ->
val exposure = exposures[accountIdHex] ?: accountIdNotFound(accountIdHex)
@@ -61,6 +65,12 @@ class RewardCalculatorFactory(
)
}
Log.d("RewardCalculatorFactory", "Validators count for reward calculation: ${validators.size}")
if (validators.isNotEmpty()) {
val totalStaked = validators.sumOf { it.totalStake }
Log.d("RewardCalculatorFactory", "Total staked: $totalStaked, stakedPortion: ${totalStaked.toDouble() / totalIssuance.toDouble()}")
}
stakingOption.createRewardCalculator(validators, totalIssuance, scope)
}
@@ -85,10 +95,16 @@ class RewardCalculatorFactory(
val custom = customRelayChainCalculator(validators, totalIssuance, scope)
if (custom != null) return custom
val activePublicParachains = parasRepository.activePublicParachains(assetWithChain.chain.id)
val inflationConfig = InflationConfig.create(chain.id, activePublicParachains)
val timelineChainId = chain.timelineChainIdOrSelf()
val activePublicParachains = parasRepository.activePublicParachains(timelineChainId)
Log.d("RewardCalculatorFactory", "activePublicParachains for $timelineChainId: $activePublicParachains")
RewardCurveInflationRewardCalculator(validators, totalIssuance, inflationConfig)
val inflationConfig = InflationConfig.create(timelineChainId, activePublicParachains)
Log.d("RewardCalculatorFactory", "Using Default InflationConfig for $timelineChainId")
val calculator = RewardCurveInflationRewardCalculator(validators, totalIssuance, inflationConfig)
Log.d("RewardCalculatorFactory", "expectedAPY: ${calculator.expectedAPY}, maxAPY: ${calculator.maxAPY}")
calculator
}
ALEPH_ZERO -> AlephZeroRewardCalculator(validators, chainAsset = assetWithChain.asset)
+2320 -2434
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -8,9 +8,9 @@ android {
buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/android/chains.json\""
buildConfigField "String", "EVM_ASSETS_URL", "\"https://wallet.pezkuwichain.io/evm_assets.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAINS_URL", "\"https://wallet.pezkuwichain.io/pre_configured_chains.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAIN_DETAILS_URL", "\"https://wallet.pezkuwichain.io/chain_details\""
buildConfigField "String", "EVM_ASSETS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/assets/evm/v3/assets.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAINS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/preConfigured/chains.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAIN_DETAILS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/preConfigured/details\""
buildConfigField "String", "TEST_CHAINS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/tests/chains_for_testBalance.json\""
@@ -28,9 +28,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/android/chains.json\""
buildConfigField "String", "EVM_ASSETS_URL", "\"https://wallet.pezkuwichain.io/evm_assets.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAINS_URL", "\"https://wallet.pezkuwichain.io/pre_configured_chains.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAIN_DETAILS_URL", "\"https://wallet.pezkuwichain.io/chain_details\""
buildConfigField "String", "EVM_ASSETS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/assets/evm/v3/assets.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAINS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/preConfigured/chains.json\""
buildConfigField "String", "PRE_CONFIGURED_CHAIN_DETAILS_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/chains/v22/preConfigured/details\""
}
}
namespace 'io.novafoundation.nova.runtime'
+1 -1
View File
@@ -1 +1 @@
VERSION_CODE=103
VERSION_CODE=159