From bbf62d79fdd9cb5938126685feede6b9c4d851f9 Mon Sep 17 00:00:00 2001 From: valentunn Date: Tue, 21 Jan 2025 13:50:16 +0300 Subject: [PATCH 1/3] Select myth collator --- .../staking/MythosStakingNavigationModule.kt | 8 + .../staking/mythos/MythosStakingNavigator.kt | 19 +- ...thosCollatorInterScreenCommunicatorImpl.kt | 24 +++ .../navigation/staking_mythos_start_graph.xml | 13 ++ .../nova/common/address/AccountId.kt | 5 + .../nova/common/address/AccountIdParcel.kt | 20 ++ .../nova/common/utils/KotlinExt.kt | 2 + .../repository/MythosStakingRepository.kt | 8 + .../di/StakingFeatureComponent.kt | 8 +- .../di/StakingFeatureHolder.kt | 3 + .../singleSelect/SingleSelectRecommendator.kt | 3 + .../FilteringSingleSelectRecommendator.kt | 4 +- .../SingleSelectRecommendatorConfig.kt | 3 + .../common/collator/MythosCollatorProvider.kt | 2 +- .../mythos/common/model/MythosCollator.kt | 2 +- .../common/model/MythosDelegatorState.kt | 7 + .../recommendations/MythosCollatorSorting.kt | 2 +- .../start/StartMythosStakingInteractor.kt | 26 +++ .../presentation/MythosStakingRouter.kt | 7 +- .../presentation/ParachainStakingRouter.kt | 5 +- .../presentation/StarkingReturnableRouter.kt | 8 + .../SingleSelectChooseTargetFragment.kt | 99 ++++++++++ .../SingleSelectChooseTargetViewModel.kt | 135 +++++++++++++ .../presentation/mappers/Identity.kt | 4 + .../presentation/mappers/Validator.kt | 18 +- .../SelectMythosInterScreenCommunicator.kt | 19 ++ .../mythos/common/MythosCollatorFormatter.kt | 84 ++++++-- .../common/StakeTargetDetailsMappers.kt | 32 +++ .../common/model/MythosCollatorAliases.kt | 4 +- .../mythos/start/details/Payload.kt | 18 ++ .../SelectMythosCollatorFragment.kt | 21 ++ .../SelectMythosCollatorViewModel.kt | 86 ++++++++ .../di/SelectMythosCollatorComponent.kt | 25 +++ .../di/SelectMythosCollatorModule.kt | 61 ++++++ .../selectCollator/model/MythosCollator.kt | 41 ++++ .../setup/SetupStartMythosStakingViewModel.kt | 33 +++- .../setup/di/SetupStartMythosStakingModule.kt | 6 +- .../collator/select/SelectCollatorFragment.kt | 94 +-------- .../select/SelectCollatorViewModel.kt | 185 +++++++----------- .../common/mappers/Collator.kt | 11 +- .../details/ValidatorDetailsViewModel.kt | 6 +- .../details/ValidatorStakeBottomSheet.kt | 9 +- .../parcel/StakeTargetStakeParcelModel.kt | 6 +- 43 files changed, 919 insertions(+), 257 deletions(-) create mode 100644 app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythosCollatorInterScreenCommunicatorImpl.kt create mode 100644 common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/SingleSelectRecommendatorConfig.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StarkingReturnableRouter.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/SelectMythosInterScreenCommunicator.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/StakeTargetDetailsMappers.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/details/Payload.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/model/MythosCollator.kt diff --git a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt index dc04cb79e3..c6db572659 100644 --- a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt @@ -4,8 +4,10 @@ import dagger.Module import dagger.Provides import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRegistry import io.novafoundation.nova.app.root.navigation.navigators.staking.mythos.MythosStakingNavigator +import io.novafoundation.nova.app.root.navigation.navigators.staking.mythos.SelectMythosCollatorInterScreenCommunicatorImpl import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator @Module class MythosStakingNavigationModule { @@ -17,4 +19,10 @@ class MythosStakingNavigationModule { ): MythosStakingRouter { return MythosStakingNavigator(navigationHoldersRegistry) } + + @Provides + @ApplicationScope + fun provideSelectCollatorCommunicator(navigationHoldersRegistry: NavigationHoldersRegistry): SelectMythosInterScreenCommunicator { + return SelectMythosCollatorInterScreenCommunicatorImpl(navigationHoldersRegistry) + } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/MythosStakingNavigator.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/MythosStakingNavigator.kt index 96feb869ca..6053070b45 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/MythosStakingNavigator.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/MythosStakingNavigator.kt @@ -1,9 +1,26 @@ package io.novafoundation.nova.app.root.navigation.navigators.staking.mythos +import io.novafoundation.nova.app.R import io.novafoundation.nova.app.root.navigation.navigators.BaseNavigator import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRegistry import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload +import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.ValidatorDetailsFragment class MythosStakingNavigator( navigationHoldersRegistry: NavigationHoldersRegistry, -) : BaseNavigator(navigationHoldersRegistry), MythosStakingRouter +) : BaseNavigator(navigationHoldersRegistry), MythosStakingRouter { + + override fun openCollatorDetails(payload: StakeTargetDetailsPayload) { + navigationBuilder() + .action(R.id.open_validator_details) + .setArgs(ValidatorDetailsFragment.getBundle(payload)) + .navigateInFirstAttachedContext() + } + + override fun returnToStartStaking() { + navigationBuilder() + .action(R.id.action_return_to_start_staking) + .navigateInFirstAttachedContext() + } +} diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythosCollatorInterScreenCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythosCollatorInterScreenCommunicatorImpl.kt new file mode 100644 index 0000000000..9564424165 --- /dev/null +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythosCollatorInterScreenCommunicatorImpl.kt @@ -0,0 +1,24 @@ +package io.novafoundation.nova.app.root.navigation.navigators.staking.mythos + +import io.novafoundation.nova.app.R +import io.novafoundation.nova.app.root.navigation.NavStackInterScreenCommunicator +import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRegistry +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator.Request +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model.MythosCollatorParcel + +class SelectMythosCollatorInterScreenCommunicatorImpl(navigationHoldersRegistry: NavigationHoldersRegistry) : + SelectMythosInterScreenCommunicator, + NavStackInterScreenCommunicator(navigationHoldersRegistry) { + + override fun respond(response: MythosCollatorParcel) { + val responseEntry = navController.getBackStackEntry(R.id.startMythosStakingFragment) + saveResultTo(responseEntry, response) + } + + override fun openRequest(request: Request) { + super.openRequest(request) + + navController.navigate(R.id.action_startMythosStakingFragment_to_selectMythosCollatorFragment) + } +} diff --git a/app/src/main/res/navigation/staking_mythos_start_graph.xml b/app/src/main/res/navigation/staking_mythos_start_graph.xml index 26cab57af6..b796ee6634 100644 --- a/app/src/main/res/navigation/staking_mythos_start_graph.xml +++ b/app/src/main/res/navigation/staking_mythos_start_graph.xml @@ -18,5 +18,18 @@ android:name="io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.SetupStartMythosStakingFragment" android:label="StartMythosStakingFragment" tools:layout="@layout/fragment_parachain_staking_start"> + + + + \ No newline at end of file diff --git a/common/src/main/java/io/novafoundation/nova/common/address/AccountId.kt b/common/src/main/java/io/novafoundation/nova/common/address/AccountId.kt index 889c70a9ff..b60094062b 100644 --- a/common/src/main/java/io/novafoundation/nova/common/address/AccountId.kt +++ b/common/src/main/java/io/novafoundation/nova/common/address/AccountId.kt @@ -1,5 +1,6 @@ package io.novafoundation.nova.common.address +import io.novasama.substrate_sdk_android.extensions.toHexString import io.novasama.substrate_sdk_android.runtime.AccountId class AccountIdKey(val value: AccountId) { @@ -17,6 +18,10 @@ class AccountIdKey(val value: AccountId) { fun AccountId.intoKey() = AccountIdKey(this) +fun AccountIdKey.toHex(): String { + return value.toHexString() +} + operator fun Map.get(key: AccountId) = get(AccountIdKey(key)) fun Map.getValue(key: AccountId) = getValue(AccountIdKey(key)) diff --git a/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt b/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt new file mode 100644 index 0000000000..067d035687 --- /dev/null +++ b/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt @@ -0,0 +1,20 @@ +package io.novafoundation.nova.common.address + +import android.os.Parcelable +import io.novasama.substrate_sdk_android.extensions.fromHex +import io.novasama.substrate_sdk_android.runtime.AccountId +import kotlinx.android.parcel.Parcelize + +@Parcelize +class AccountIdParcel(private val value: AccountId): Parcelable { + + companion object { + + fun fromHex(hexAccountId: String): AccountIdParcel { + return AccountIdParcel(hexAccountId.fromHex()) + } + } + + val accountId: AccountIdKey + get() = value.intoKey() +} diff --git a/common/src/main/java/io/novafoundation/nova/common/utils/KotlinExt.kt b/common/src/main/java/io/novafoundation/nova/common/utils/KotlinExt.kt index 30991b6de0..6979d93cbd 100644 --- a/common/src/main/java/io/novafoundation/nova/common/utils/KotlinExt.kt +++ b/common/src/main/java/io/novafoundation/nova/common/utils/KotlinExt.kt @@ -214,6 +214,8 @@ fun BigDecimal?.orZero(): BigDecimal = this ?: 0.toBigDecimal() fun Double?.orZero(): Double = this ?: 0.0 +fun Int?.orZero(): Int = this ?: 0 + fun BigInteger.divideToDecimal(divisor: BigInteger, mathContext: MathContext = MathContext.DECIMAL64): BigDecimal { return toBigDecimal().divide(divisor.toBigDecimal(), mathContext) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/mythos/repository/MythosStakingRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/mythos/repository/MythosStakingRepository.kt index a502ef4be8..70951e7544 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/mythos/repository/MythosStakingRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/mythos/repository/MythosStakingRepository.kt @@ -21,6 +21,8 @@ interface MythosStakingRepository { fun minStakeFlow(chainId: ChainId): Flow + suspend fun maxCandidatesPerDelegator(chainId: ChainId): Int + suspend fun unstakeDurationInSessions(chainId: ChainId): Int } @@ -37,6 +39,12 @@ class RealMythosStakingRepository @Inject constructor( } } + override suspend fun maxCandidatesPerDelegator(chainId: ChainId): Int { + return chainRegistry.withRuntime(chainId) { + metadata.collatorStaking().numberConstant("MaxStakedCandidates").toInt() + } + } + override suspend fun unstakeDurationInSessions(chainId: ChainId): Int { return chainRegistry.withRuntime(chainId) { metadata.collatorStaking().numberConstant("StakeUnlockDelay").toInt() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt index fc0ee34c92..e1201e4493 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt @@ -32,6 +32,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.validators.chang import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.confirm.nominations.di.ConfirmNominationsComponent import io.novafoundation.nova.feature_staking_impl.presentation.dashboard.main.di.StakingDashboardComponent import io.novafoundation.nova.feature_staking_impl.presentation.dashboard.more.di.MoreStakingOptionsComponent +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.di.SelectMythosCollatorComponent import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.di.SetupStartMythosStakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.nominationPools.bondMore.confirm.di.NominationPoolsConfirmBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.nominationPools.bondMore.setup.di.NominationPoolsSetupBondMoreComponent @@ -241,6 +243,8 @@ interface StakingFeatureComponent : StakingFeatureApi { fun startMythosStakingFactory(): SetupStartMythosStakingComponent.Factory + fun selectMythosCollatorFactory(): SelectMythosCollatorComponent.Factory + @Component.Factory interface Factory { @@ -248,11 +252,13 @@ interface StakingFeatureComponent : StakingFeatureApi { @BindsInstance router: StakingRouter, @BindsInstance parachainStaking: ParachainStakingRouter, - @BindsInstance mythosStakingRouter: MythosStakingRouter, @BindsInstance selectCollatorInterScreenCommunicator: SelectCollatorInterScreenCommunicator, @BindsInstance selectCollatorSettingsInterScreenCommunicator: SelectCollatorSettingsInterScreenCommunicator, @BindsInstance selectAddressCommunicator: SelectAddressCommunicator, + @BindsInstance mythosStakingRouter: MythosStakingRouter, + @BindsInstance selectMythosCollatorSettingsInterScreenCommunicator: SelectMythosInterScreenCommunicator, + @BindsInstance nominationPoolsRouter: NominationPoolsRouter, @BindsInstance startMultiStakingRouter: StartMultiStakingRouter, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt index a06f2e4619..6725cdfb89 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt @@ -14,6 +14,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStaking import io.novafoundation.nova.feature_staking_impl.presentation.StakingDashboardRouter import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.StartMultiStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator import io.novafoundation.nova.feature_wallet_api.di.WalletFeatureApi @@ -32,6 +33,7 @@ class StakingFeatureHolder @Inject constructor( private val selectAddressCommunicator: SelectAddressCommunicator, private val selectCollatorInterScreenCommunicator: SelectCollatorInterScreenCommunicator, private val selectCollatorSettingsInterScreenCommunicator: SelectCollatorSettingsInterScreenCommunicator, + private val selectMythosCollatorSettingsInterScreenCommunicator: SelectMythosInterScreenCommunicator, ) : FeatureApiHolder(featureContainer) { override fun initializeDependencies(): Any { @@ -56,6 +58,7 @@ class StakingFeatureHolder @Inject constructor( nominationPoolsRouter = nominationPoolsRouter, startMultiStakingRouter = startMultiStakingRouter, stakingDashboardRouter = stakingDashboardRouter, + selectMythosCollatorSettingsInterScreenCommunicator = selectMythosCollatorSettingsInterScreenCommunicator, deps = dependencies ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/SingleSelectRecommendator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/SingleSelectRecommendator.kt index 1f68cb1907..4b8f315d6d 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/SingleSelectRecommendator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/SingleSelectRecommendator.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect import io.novafoundation.nova.common.data.memory.ComputationalScope import io.novafoundation.nova.feature_staking_impl.data.StakingOption +import io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.recommendations.SingleSelectRecommendatorConfig interface SingleSelectRecommendator { @@ -11,5 +12,7 @@ interface SingleSelectRecommendator { suspend fun create(stakingOption: StakingOption, computationalScope: ComputationalScope): SingleSelectRecommendator } + fun recommendations(config: SingleSelectRecommendatorConfig): List + fun defaultRecommendation(): T? } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/FilteringSingleSelectRecommendator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/FilteringSingleSelectRecommendator.kt index e72c3322d3..a3ede57abc 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/FilteringSingleSelectRecommendator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/FilteringSingleSelectRecommendator.kt @@ -17,13 +17,13 @@ class FilteringSingleSelectRecommendator( private val excluded: Set ) : SingleSelectRecommendator { - fun recommendations(sorting: Comparator): List { + override fun recommendations(config: SingleSelectRecommendatorConfig): List { return allTargets.filter { it.accountId !in excluded } .sortedWith( // accounts from recommended list first compareByDescending { it.accountId in recommended } // then by the supplied sorting rule - .then(sorting) + .then(config) ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/SingleSelectRecommendatorConfig.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/SingleSelectRecommendatorConfig.kt new file mode 100644 index 0000000000..7e2cbb9a7a --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/common/singleSelect/recommendations/SingleSelectRecommendatorConfig.kt @@ -0,0 +1,3 @@ +package io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.recommendations + +typealias SingleSelectRecommendatorConfig = Comparator diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/collator/MythosCollatorProvider.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/collator/MythosCollatorProvider.kt index beaf7b564d..4e8ab18611 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/collator/MythosCollatorProvider.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/collator/MythosCollatorProvider.kt @@ -64,7 +64,7 @@ class RealMythosCollatorProvider @Inject constructor( totalStake = collatorStake.stake, delegators = collatorStake.stakers, // TODO APY calculation - apy = Fraction.ZERO + apr = Fraction.ZERO ) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosCollator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosCollator.kt index 3e8aab7650..d7602f893f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosCollator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosCollator.kt @@ -13,7 +13,7 @@ class MythosCollator( val identity: OnChainIdentity?, val totalStake: Balance, val delegators: Int, - val apy: Fraction?, + val apr: Fraction?, ) : Identifiable, WithAccountId { override val identifier: String = accountId.value.toHexString() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt index a850f50460..ef327dcef8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt @@ -59,6 +59,13 @@ fun MythosDelegatorState.stakeByCollator(): Map { } } +fun MythosDelegatorState.stakedCollatorsCount(): Int { + return when (this) { + is MythosDelegatorState.Locked.Delegating -> userStakeInfo.candidates.size + MythosDelegatorState.NotStarted, is MythosDelegatorState.Locked.NotDelegating -> 0 + } +} + fun MythosDelegatorState.hasActiveValidators(sessionValidators: SessionValidators): Boolean { return when (this) { is MythosDelegatorState.Locked.Delegating -> userStakeInfo.hasActiveValidators(sessionValidators) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/recommendations/MythosCollatorSorting.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/recommendations/MythosCollatorSorting.kt index b940934447..964bb2eed8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/recommendations/MythosCollatorSorting.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/recommendations/MythosCollatorSorting.kt @@ -4,7 +4,7 @@ import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.My enum class MythosCollatorSorting(private val collatorComparator: Comparator) : Comparator by collatorComparator { - REWARDS(compareByDescending { it.apy }), + REWARDS(compareByDescending { it.apr }), TOTAL_STAKE(compareByDescending { it.totalStake }), } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt index 0f32365386..0d43c77447 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt @@ -12,12 +12,20 @@ import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchai import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.collatorStaking import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.lock import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.stake +import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.MythosCandidatesRepository +import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.MythosStakingRepository +import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.RealMythosCandidatesRepository import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.MythosSharedComputation import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosDelegatorState +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.stakeByCollator +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.stakedCollatorsCount +import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.start.DelegationsLimit import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.state.chain import io.novasama.substrate_sdk_android.runtime.extrinsic.ExtrinsicBuilder +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withContext import javax.inject.Inject interface StartMythosStakingInteractor { @@ -30,6 +38,10 @@ interface StartMythosStakingInteractor { candidate: AccountIdKey, amount: Balance ): Fee + + suspend fun checkDelegationsLimit( + delegatorState: MythosDelegatorState + ): DelegationsLimit } @FeatureScope @@ -37,6 +49,7 @@ class RealStartMythosStakingInteractor @Inject constructor( private val mythosSharedComputation: MythosSharedComputation, private val stakingSharedState: StakingSharedState, private val extrinsicService: ExtrinsicService, + private val stakingRepository: MythosStakingRepository ) : StartMythosStakingInteractor { context(ComputationalScope) @@ -55,6 +68,19 @@ class RealStartMythosStakingInteractor @Inject constructor( } } + override suspend fun checkDelegationsLimit(delegatorState: MythosDelegatorState): DelegationsLimit { + return withContext(Dispatchers.IO) { + val chainId = stakingSharedState.chainId() + val maxCandidatesPerCollator = stakingRepository.maxCandidatesPerDelegator(chainId) + + if (delegatorState.stakedCollatorsCount() < maxCandidatesPerCollator) { + DelegationsLimit.NotReached + } else { + DelegationsLimit.Reached(maxCandidatesPerCollator) + } + } + } + private fun ExtrinsicBuilder.stakeMore( currentState: MythosDelegatorState, candidate: AccountIdKey, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/MythosStakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/MythosStakingRouter.kt index 1642147d6a..23213d9772 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/MythosStakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/MythosStakingRouter.kt @@ -1,5 +1,8 @@ package io.novafoundation.nova.feature_staking_impl.presentation -import io.novafoundation.nova.common.navigation.ReturnableRouter +import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload -interface MythosStakingRouter : ReturnableRouter +interface MythosStakingRouter : StarkingReturnableRouter { + + fun openCollatorDetails(payload: StakeTargetDetailsPayload) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/ParachainStakingRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/ParachainStakingRouter.kt index 3e3cb9ed2b..003e7b4619 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/ParachainStakingRouter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/ParachainStakingRouter.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.presentation -import io.novafoundation.nova.common.navigation.ReturnableRouter import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.rebond.model.ParachainStakingRebondPayload import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.start.common.StartParachainStakingMode import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.start.confirm.model.ConfirmStartParachainStakingPayload @@ -9,7 +8,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.yieldBoost.confirm.model.YieldBoostConfirmPayload import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload -interface ParachainStakingRouter : ReturnableRouter { +interface ParachainStakingRouter : StarkingReturnableRouter { fun openStartStaking(payload: StartParachainStakingPayload) @@ -23,8 +22,6 @@ interface ParachainStakingRouter : ReturnableRouter { fun returnToStakingMain() - fun returnToStartStaking() - fun openCurrentCollators() fun openUnbond() diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StarkingReturnableRouter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StarkingReturnableRouter.kt new file mode 100644 index 0000000000..00643d3231 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/StarkingReturnableRouter.kt @@ -0,0 +1,8 @@ +package io.novafoundation.nova.feature_staking_impl.presentation + +import io.novafoundation.nova.common.navigation.ReturnableRouter + +interface StarkingReturnableRouter : ReturnableRouter { + + fun returnToStartStaking() +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt new file mode 100644 index 0000000000..e522cf98c6 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt @@ -0,0 +1,99 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.utils.applyStatusBarInsets +import io.novafoundation.nova.common.utils.makeGone +import io.novafoundation.nova.common.utils.makeVisible +import io.novafoundation.nova.common.utils.scrollToTopWhenItemsShuffled +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.presentation.validators.StakeTargetAdapter +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorClearFilters +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorContainer +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorContentGroup +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorCount +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorList +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorProgress +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorSorting +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorToolbar + +abstract class SingleSelectChooseTargetFragment> : BaseFragment(), + StakeTargetAdapter.ItemHandler { + + val adapter by lazy(LazyThreadSafetyMode.NONE) { + StakeTargetAdapter(this) + } + + private var filterAction: ImageView? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_parachain_staking_select_collator, container, false) + } + + override fun initViews() { + selectCollatorContainer.applyStatusBarInsets() + + selectCollatorList.adapter = adapter + selectCollatorList.setHasFixedSize(true) + selectCollatorList.itemAnimator = null + + selectCollatorToolbar.setHomeButtonListener { viewModel.backClicked() } + onBackPressed { viewModel.backClicked() } + + filterAction = selectCollatorToolbar.addCustomAction(R.drawable.ic_filter) { + viewModel.settingsClicked() + } + + if (viewModel.searchVisible) { + selectCollatorToolbar.addCustomAction(R.drawable.ic_search) { + viewModel.searchClicked() + } + } + + selectCollatorList.scrollToTopWhenItemsShuffled(viewLifecycleOwner) + + selectCollatorClearFilters.setOnClickListener { viewModel.clearFiltersClicked() } + } + + override fun onDestroyView() { + super.onDestroyView() + + filterAction = null + } + + override fun subscribe(viewModel: V) { + viewModel.targetModelsFlow.observe { + adapter.submitList(it) + + selectCollatorContentGroup.makeVisible() + selectCollatorProgress.makeGone() + } + + viewModel.targetsCount.observe(selectCollatorCount::setText) + + viewModel.scoringHeader.observe(selectCollatorSorting::setText) + + viewModel.recommendationSettingsIcon.observe { icon -> + filterAction?.setImageResource(icon) + } + + viewModel.clearFiltersEnabled.observe(selectCollatorClearFilters::setEnabled) + } + + override fun stakeTargetInfoClicked(stakeTargetModel: StakeTargetModel) { + viewModel.targetInfoClicked(stakeTargetModel) + } + + override fun stakeTargetClicked(stakeTargetModel: StakeTargetModel) { + viewModel.targetClicked(stakeTargetModel) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt new file mode 100644 index 0000000000..ff4d706c85 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt @@ -0,0 +1,135 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget + +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.common.navigation.ReturnableRouter +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.inBackground +import io.novafoundation.nova.common.utils.invoke +import io.novafoundation.nova.common.utils.launchUnit +import io.novafoundation.nova.common.utils.lazyAsync +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.SingleSelectRecommendator +import io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.recommendations.SingleSelectRecommendatorConfig +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel +import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase +import io.novafoundation.nova.feature_wallet_api.domain.model.Token +import io.novafoundation.nova.runtime.state.selectedOption +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch + +abstract class SingleSelectChooseTargetViewModel>( + private val router: ReturnableRouter, + private val recommendatorFactory: SingleSelectRecommendator.Factory, + private val resourceManager: ResourceManager, + private val tokenUseCase: TokenUseCase, + private val selectedAssetState: StakingSharedState, + private val state: SingleSelectChooseTargetState +) : BaseViewModel() { + + private val recommendator by lazyAsync { + recommendatorFactory.create(selectedAssetState.selectedOption(), computationalScope = this) + } + + private val recommendationConfigFlow = MutableStateFlow(state.defaultRecommendatorConfig) + + private val isChangedRecommendationConfigFlow = recommendationConfigFlow.map { + it != state.defaultRecommendatorConfig + } + + val recommendationSettingsIcon = isChangedRecommendationConfigFlow.map { isChanged -> + if (isChanged) R.drawable.ic_filter_indicator else R.drawable.ic_filter + } + .shareInBackground() + + val clearFiltersEnabled = isChangedRecommendationConfigFlow + + private val shownTargets = recommendationConfigFlow.map { it -> + ShownStakeTargets(recommendator().recommendations(it), it) + }.shareInBackground() + + private val tokenFlow = tokenUseCase.currentTokenFlow() + .inBackground() + .share() + + val targetModelsFlow = combine(shownTargets, tokenFlow) { shownTargets, token -> + state.convertTargetsToUi(shownTargets.targets, token, shownTargets.usedConfig) + } + .shareInBackground() + + val targetsCount = shownTargets.map { + resourceManager.getString(R.string.staking_parachain_collators_number_format, it.targets.size) + }.shareInBackground() + + val scoringHeader = recommendationConfigFlow.map(state::scoringHeaderFor) + .shareInBackground() + + val searchVisible = state.searchAction != null + + init { + listenRecommendationConfigChanges() + } + + protected abstract fun settingsClicked(currentConfig: C) + + protected abstract suspend fun targetInfoClicked(target: T) + + protected abstract suspend fun targetSelected(target: T) + + fun clearFiltersClicked() { + recommendationConfigFlow.value = state.defaultRecommendatorConfig + } + + fun backClicked() { + router.back() + } + + fun targetInfoClicked(stakeTargetModel: StakeTargetModel) = launchUnit { + targetInfoClicked(stakeTargetModel.stakeTarget) + } + + fun targetClicked(stakeTargetModel: StakeTargetModel) = launchUnit { + targetSelected(stakeTargetModel.stakeTarget) + } + + fun settingsClicked() = launch { + settingsClicked(recommendationConfigFlow.value) + } + + fun searchClicked() { + state.searchAction?.invoke() + } + + private fun listenRecommendationConfigChanges() { + state.recommendationConfigChanges() + .onEach { recommendationConfigFlow.value = it } + .inBackground() + .launchIn(this) + } + + interface SingleSelectChooseTargetState { + val defaultRecommendatorConfig: C + + val searchAction: SearchAction? + + suspend fun convertTargetsToUi( + targets: List, + token: Token, + config: C + ): List> + + fun scoringHeaderFor(config: C): String + + fun recommendationConfigChanges(): Flow + + } + + private inner class ShownStakeTargets(val targets: List, val usedConfig: C) +} + +typealias SearchAction = () -> Unit diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Identity.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Identity.kt index ca495d31e1..76c0e7bd3f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Identity.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Identity.kt @@ -20,6 +20,10 @@ fun mapIdentityToIdentityParcelModel(identity: OnChainIdentity): IdentityParcelM } } +fun OnChainIdentity.toParcel(): IdentityParcelModel { + return mapIdentityToIdentityParcelModel(this) +} + fun mapIdentityParcelModelToIdentity(identity: IdentityParcelModel): OnChainIdentity { return with(identity) { if (childInfo != null) { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt index e17be26ac4..e4b6a9543e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt @@ -5,8 +5,11 @@ import io.novafoundation.nova.common.address.AddressModel import io.novafoundation.nova.common.address.createAddressModel import io.novafoundation.nova.common.presentation.ColoredText import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.common.utils.Fraction +import io.novafoundation.nova.common.utils.Fraction.Companion.fractions import io.novafoundation.nova.common.utils.formatting.format import io.novafoundation.nova.common.utils.formatting.formatAsPercentage +import io.novafoundation.nova.common.utils.formatting.formatPercents import io.novafoundation.nova.common.utils.fractionToPercentage import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel import io.novafoundation.nova.feature_currency_api.presentation.formatters.formatAsCurrency @@ -89,9 +92,13 @@ suspend fun mapValidatorToValidatorModel( } } -fun rewardsToScoring(rewardsGain: BigDecimal?) = rewardsToColoredText(rewardsGain)?.let(StakeTargetModel.Scoring::OneField) +fun rewardsToScoring(rewardsGain: BigDecimal?) = rewardsToScoring(rewardsGain?.fractions) -fun rewardsToColoredText(rewardsGain: BigDecimal?) = formatStakeTargetRewardsOrNull(rewardsGain)?.let { +fun rewardsToScoring(rewardsGain: Fraction?) = rewardsToColoredText(rewardsGain)?.let(StakeTargetModel.Scoring::OneField) + +fun rewardsToColoredText(rewardsGain: BigDecimal?) = rewardsToColoredText(rewardsGain?.fractions) + +fun rewardsToColoredText(rewardsGain: Fraction?) = formatStakeTargetRewardsOrNull(rewardsGain)?.let { ColoredText(it, R.color.text_positive) } @@ -199,7 +206,7 @@ suspend fun mapValidatorDetailsParcelToValidatorDetailsModel( is StakeTargetStakeParcelModel.Active -> { val totalStakeModel = mapAmountToAmountModel(stake.totalStake, asset) - val nominatorsCount = stake.stakers.size + val nominatorsCount = stake.stakersCount val rewardsWithLabel = displayConfig.rewardSuffix.format(resourceManager, stake.rewards) val formattedMaxStakers = displayConfig.rewardedStakersPerStakeTarget?.format() @@ -229,7 +236,8 @@ suspend fun mapValidatorDetailsParcelToValidatorDetailsModel( } } -fun formatStakeTargetRewards(rewardsRate: BigDecimal) = rewardsRate.fractionToPercentage().formatAsPercentage() -fun formatStakeTargetRewardsOrNull(rewardsRate: BigDecimal?) = rewardsRate?.let(::formatStakeTargetRewards) +fun formatStakeTargetRewards(rewardsRate: Fraction) = rewardsRate.formatPercents() +fun formatStakeTargetRewardsOrNull(rewardsRate: Fraction?) = rewardsRate?.let(::formatStakeTargetRewards) +fun formatStakeTargetRewardsOrNull(rewardsRate: BigDecimal?) = formatStakeTargetRewardsOrNull(rewardsRate?.fractions) fun formatValidatorApy(validator: Validator) = formatStakeTargetRewardsOrNull(validator.electedInfo?.apy) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/SelectMythosInterScreenCommunicator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/SelectMythosInterScreenCommunicator.kt new file mode 100644 index 0000000000..584bfc0a50 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/SelectMythosInterScreenCommunicator.kt @@ -0,0 +1,19 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos + +import android.os.Parcelable +import io.novafoundation.nova.common.navigation.InterScreenRequester +import io.novafoundation.nova.common.navigation.InterScreenResponder +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator.Request +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model.MythosCollatorParcel +import kotlinx.android.parcel.Parcelize + +interface SelectMythosInterScreenRequester : InterScreenRequester +interface SelectMythosInterScreenResponder : InterScreenResponder + +interface SelectMythosInterScreenCommunicator : SelectMythosInterScreenRequester, SelectMythosInterScreenResponder { + + @Parcelize + object Request : Parcelable +} + +fun SelectMythosInterScreenRequester.openRequest() = openRequest(Request) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/MythosCollatorFormatter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/MythosCollatorFormatter.kt index 6d6d98a736..c83cb26dac 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/MythosCollatorFormatter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/MythosCollatorFormatter.kt @@ -1,26 +1,42 @@ package io.novafoundation.nova.feature_staking_impl.presentation.mythos.common import io.novafoundation.nova.common.address.AddressIconGenerator +import io.novafoundation.nova.common.address.toHex import io.novafoundation.nova.common.di.scope.FeatureScope import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.takeUnlessZero import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendationConfig +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorSorting +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.rewardsToColoredText +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.rewardsToScoring +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.stakeToScoring import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.model.MythosCollatorModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.model.MythosCollatorWithAmount +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.model.MythosSelectCollatorModel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.mappers.withSubtitleLabelSuffix import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.selectCollators.labeledAmountSubtitle +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance -import io.novafoundation.nova.feature_wallet_api.domain.model.Asset +import io.novafoundation.nova.feature_wallet_api.domain.model.Token import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel +import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain import io.novafoundation.nova.runtime.state.chain import javax.inject.Inject interface MythosCollatorFormatter { - suspend fun collatorToUi( + suspend fun collatorToSelectUi( collator: MythosCollatorWithAmount, - asset: Asset + token: Token + ): MythosSelectCollatorModel + + suspend fun collatorToUi( + collator: MythosCollator, + token: Token, + recommendationConfig: MythosCollatorRecommendationConfig ): MythosCollatorModel } @@ -31,35 +47,81 @@ class RealMythosCollatorFormatter @Inject constructor( private val addressIconGenerator: AddressIconGenerator, ) : MythosCollatorFormatter { - override suspend fun collatorToUi( + override suspend fun collatorToSelectUi( collatorWithAmount: MythosCollatorWithAmount, - asset: Asset - ): MythosCollatorModel { + token: Token + ): MythosSelectCollatorModel { return mapCollatorToSelectCollatorModel( collator = collatorWithAmount.target, stakedAmount = collatorWithAmount.stake.takeUnlessZero(), - asset = asset + token = token + ) + } + + override suspend fun collatorToUi( + collator: MythosCollator, + token: Token, + recommendationConfig: MythosCollatorRecommendationConfig + ): MythosCollatorModel { + return mapCollatorToCollatorModel( + collator = collator, + chain = stakingSharedState.chain(), + sorting = recommendationConfig.sorting, + token = token ) } private suspend fun mapCollatorToSelectCollatorModel( collator: MythosCollator, - asset: Asset, + token: Token, stakedAmount: Balance? = null, active: Boolean = true, - ): MythosCollatorModel { + ): MythosSelectCollatorModel { val addressModel = addressIconGenerator.collatorAddressModel(collator, stakingSharedState.chain()) - val stakedAmountModel = stakedAmount?.let { mapAmountToAmountModel(stakedAmount, asset) } + val stakedAmountModel = stakedAmount?.let { mapAmountToAmountModel(stakedAmount, token) } val subtitle = stakedAmountModel?.let { resourceManager.labeledAmountSubtitle(R.string.staking_main_stake_balance_staked, it, selectionActive = active) } - return MythosCollatorModel( + return MythosSelectCollatorModel( addressModel = addressModel, payload = collator, active = active, subtitle = subtitle ) } + + private suspend fun mapCollatorToCollatorModel( + collator: MythosCollator, + chain: Chain, + sorting: MythosCollatorSorting, + token: Token, + ): MythosCollatorModel { + val addressModel = addressIconGenerator.collatorAddressModel(collator, chain) + + val scoring = when (sorting) { + MythosCollatorSorting.REWARDS -> rewardsToScoring(collator.apr) + MythosCollatorSorting.TOTAL_STAKE -> stakeToScoring(collator.totalStake, token) + } + + val subtitle = when (sorting) { + MythosCollatorSorting.REWARDS -> null + + MythosCollatorSorting.TOTAL_STAKE -> StakeTargetModel.Subtitle( + label = resourceManager.getString(R.string.staking_rewards).withSubtitleLabelSuffix(), + value = rewardsToColoredText(collator.apr)!! + ) + } + + return MythosCollatorModel( + accountIdHex = collator.accountId.toHex(), + slashed = false, + addressModel = addressModel, + stakeTarget = collator, + isChecked = null, + scoring = scoring, + subtitle = subtitle + ) + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/StakeTargetDetailsMappers.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/StakeTargetDetailsMappers.kt new file mode 100644 index 0000000000..ae43dda512 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/StakeTargetDetailsMappers.kt @@ -0,0 +1,32 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.common + +import io.novafoundation.nova.common.address.toHex +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.toParcel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakeTargetDetailsParcelModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakeTargetStakeParcelModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakeTargetStakeParcelModel.Active.UserStakeInfo + +fun MythosCollator.toTargetDetailsParcel(): StakeTargetDetailsParcelModel { + val stake = if (apr != null) { + StakeTargetStakeParcelModel.Active( + totalStake = totalStake, + ownStake = null, + minimumStake = null, + stakers = emptyList(), + stakersCount = delegators, + rewards = apr.inFraction.toBigDecimal(), + isOversubscribed = false, + userStakeInfo = UserStakeInfo(willBeRewarded = true) + ) + } else { + StakeTargetStakeParcelModel.Inactive + } + + return StakeTargetDetailsParcelModel( + accountIdHex = accountId.toHex(), + isSlashed = false, + stake = stake, + identity = identity?.toParcel() + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/model/MythosCollatorAliases.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/model/MythosCollatorAliases.kt index 13bb96421f..792995bac6 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/model/MythosCollatorAliases.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/common/model/MythosCollatorAliases.kt @@ -3,6 +3,8 @@ package io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.m import io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.model.TargetWithStakedAmount import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator import io.novafoundation.nova.feature_staking_impl.presentation.common.selectStakeTarget.SelectStakeTargetModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel -typealias MythosCollatorModel = SelectStakeTargetModel +typealias MythosSelectCollatorModel = SelectStakeTargetModel +typealias MythosCollatorModel = StakeTargetModel typealias MythosCollatorWithAmount = TargetWithStakedAmount diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/details/Payload.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/details/Payload.kt new file mode 100644 index 0000000000..a982758829 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/details/Payload.kt @@ -0,0 +1,18 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.details + +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.RewardSuffix +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.toTargetDetailsParcel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload + +fun StakeTargetDetailsPayload.Companion.mythos(collator: MythosCollator) = StakeTargetDetailsPayload( + stakeTarget = collator.toTargetDetailsParcel(), + displayConfig = StakeTargetDetailsPayload.DisplayConfig( + rewardSuffix = RewardSuffix.APR, + rewardedStakersPerStakeTarget = null, + titleRes = R.string.staking_parachain_collator_info, + stakersLabelRes = R.string.staking_parachain_delegators, + oversubscribedWarningText = R.string.staking_parachain_collator_details_oversubscribed + ) +) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt new file mode 100644 index 0000000000..450ac243f2 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt @@ -0,0 +1,21 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator + +import io.novafoundation.nova.common.di.FeatureUtils +import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi +import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.model.Collator +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SingleSelectChooseTargetFragment + +class SelectMythosCollatorFragment : SingleSelectChooseTargetFragment() { + + override fun inject() { + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .selectMythosCollatorFactory() + .create(this) + .inject(this) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt new file mode 100644 index 0000000000..b918f833b7 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt @@ -0,0 +1,86 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator + +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendationConfig +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendatorFactory +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorSorting +import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SearchAction +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SingleSelectChooseTargetViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenResponder +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.details.mythos +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model.toParcelable +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload +import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase +import io.novafoundation.nova.feature_wallet_api.domain.model.Token +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow + +class SelectMythosCollatorViewModel( + private val router: MythosStakingRouter, + private val recommendatorFactory: MythosCollatorRecommendatorFactory, + private val resourceManager: ResourceManager, + private val tokenUseCase: TokenUseCase, + private val selectedAssetState: StakingSharedState, + private val mythosCollatorFormatter: MythosCollatorFormatter, + private val selectCollatorResponder: SelectMythosInterScreenResponder, +) : SingleSelectChooseTargetViewModel( + router = router, + recommendatorFactory = recommendatorFactory, + resourceManager = resourceManager, + tokenUseCase = tokenUseCase, + selectedAssetState = selectedAssetState, + state = MythosState(mythosCollatorFormatter, resourceManager) +) { + + override fun settingsClicked(currentConfig: MythosCollatorRecommendationConfig) { + showMessage("TODO") + } + + override suspend fun targetInfoClicked(target: MythosCollator) { + val payload = StakeTargetDetailsPayload.mythos(target) + router.openCollatorDetails(payload) + } + + override suspend fun targetSelected(target: MythosCollator) { + selectCollatorResponder.respond(target.toParcelable()) + router.returnToStartStaking() + } + + class MythosState( + private val mythosCollatorFormatter: MythosCollatorFormatter, + private val resourceManager: ResourceManager, + ) : SingleSelectChooseTargetState { + + override val defaultRecommendatorConfig: MythosCollatorRecommendationConfig = MythosCollatorRecommendationConfig.DEFAULT + + override val searchAction: SearchAction? = null + + override suspend fun convertTargetsToUi( + targets: List, + token: Token, + config: MythosCollatorRecommendationConfig + ): List> { + return targets.map { + mythosCollatorFormatter.collatorToUi(it, token, config) + } + } + + override fun scoringHeaderFor(config: MythosCollatorRecommendationConfig): String { + return when (config.sorting) { + MythosCollatorSorting.REWARDS -> resourceManager.getString(R.string.staking_rewards) + MythosCollatorSorting.TOTAL_STAKE -> resourceManager.getString(R.string.staking_validator_total_stake) + } + } + + override fun recommendationConfigChanges(): Flow { + // TODO settings + return emptyFlow() + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt new file mode 100644 index 0000000000..e3e23dcdf2 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt @@ -0,0 +1,25 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.di + +import androidx.fragment.app.Fragment +import dagger.BindsInstance +import dagger.Subcomponent +import io.novafoundation.nova.common.di.scope.ScreenScope +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorFragment +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select.SelectCollatorFragment + +@Subcomponent( + modules = [ + SelectMythosCollatorModule::class + ] +) +@ScreenScope +interface SelectMythosCollatorComponent { + + @Subcomponent.Factory + interface Factory { + + fun create(@BindsInstance fragment: Fragment): SelectMythosCollatorComponent + } + + fun inject(fragment: SelectMythosCollatorFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt new file mode 100644 index 0000000000..13f3703db1 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt @@ -0,0 +1,61 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.di + +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoMap +import io.novafoundation.nova.common.address.AddressIconGenerator +import io.novafoundation.nova.common.di.modules.Caching +import io.novafoundation.nova.common.di.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.common.resources.ResourceManager +import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendatorFactory +import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.CollatorsUseCase +import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.recommendations.CollatorRecommendatorFactory +import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select.SelectCollatorViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase + +@Module(includes = [ViewModelModule::class]) +class SelectMythosCollatorModule { + + @Provides + @IntoMap + @ViewModelKey(SelectMythosCollatorViewModel::class) + fun provideViewModel( + router: MythosStakingRouter, + recommendatorFactory: MythosCollatorRecommendatorFactory, + resourceManager: ResourceManager, + tokenUseCase: TokenUseCase, + selectedAssetState: StakingSharedState, + mythosCollatorFormatter: MythosCollatorFormatter, + selectCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator + ): ViewModel { + return SelectMythosCollatorViewModel( + router = router, + recommendatorFactory = recommendatorFactory, + resourceManager = resourceManager, + tokenUseCase = tokenUseCase, + selectedAssetState = selectedAssetState, + mythosCollatorFormatter = mythosCollatorFormatter, + selectCollatorResponder = selectCollatorInterScreenCommunicator + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): SelectMythosCollatorViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(SelectMythosCollatorViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/model/MythosCollator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/model/MythosCollator.kt new file mode 100644 index 0000000000..bf6a394722 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/model/MythosCollator.kt @@ -0,0 +1,41 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model + +import android.os.Parcelable +import io.novafoundation.nova.common.address.intoKey +import io.novafoundation.nova.common.utils.Fraction.Companion.fractions +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.mapIdentityParcelModelToIdentity +import io.novafoundation.nova.feature_staking_impl.presentation.mappers.mapIdentityToIdentityParcelModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.IdentityParcelModel +import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance +import io.novasama.substrate_sdk_android.runtime.AccountId +import kotlinx.android.parcel.Parcelize + +@Parcelize +class MythosCollatorParcel( + val accountId: AccountId, + val identity: IdentityParcelModel?, + val totalStake: Balance, + val delegators: Int, + val apr: Double? +) : Parcelable + +fun MythosCollator.toParcelable(): MythosCollatorParcel { + return MythosCollatorParcel( + accountId = this.accountId.value, + identity = this.identity?.let { mapIdentityToIdentityParcelModel(it) }, + totalStake = this.totalStake, + delegators = this.delegators, + apr = this.apr?.inFraction + ) +} + +fun MythosCollatorParcel.toDomain(): MythosCollator { + return MythosCollator( + accountId = accountId.intoKey(), + identity = identity?.let { mapIdentityParcelModelToIdentity(it) }, + totalStake = totalStake, + delegators = delegators, + apr = apr?.fractions + ) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt index 5d179bb38f..8ecc2e641c 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt @@ -9,6 +9,7 @@ import io.novafoundation.nova.common.utils.orZero import io.novafoundation.nova.common.utils.shareInBackground import io.novafoundation.nova.common.validation.ValidationExecutor import io.novafoundation.nova.feature_account_api.data.model.Fee +import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.common.singleSelect.model.TargetWithStakedAmount import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.MythosDelegatorStateUseCase @@ -19,11 +20,16 @@ import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.is import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.stakeableBalance import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendatorFactory import io.novafoundation.nova.feature_staking_impl.domain.mythos.start.StartMythosStakingInteractor +import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.start.DelegationsLimit import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.common.selectStakeTarget.SelectStakeTargetModel import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.start.StartSingleSelectStakingViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenRequester import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.openRequest +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model.toDomain import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.rewards.MythosStakingRewardsComponentFactory +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.openRequest import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.feature_wallet_api.domain.AssetUseCase import io.novafoundation.nova.feature_wallet_api.domain.model.Asset @@ -49,7 +55,8 @@ class SetupStartMythosStakingViewModel( private val selectedAssetState: StakingSharedState, mythosSharedComputation: MythosSharedComputation, mythosCollatorFormatter: MythosCollatorFormatter, - interactor: StartMythosStakingInteractor, + private val interactor: StartMythosStakingInteractor, + private val selectCollatorInterScreenRequester: SelectMythosInterScreenRequester, amountChooserMixinFactory: AmountChooserMixin.Factory, ) : StartSingleSelectStakingViewModel( logicFactory = { scope -> @@ -58,7 +65,8 @@ class SetupStartMythosStakingViewModel( mythosSharedComputation = mythosSharedComputation, mythosCollatorFormatter = mythosCollatorFormatter, interactor = interactor, - mythosDelegatorStateUseCase = mythosDelegatorStateUseCase + mythosDelegatorStateUseCase = mythosDelegatorStateUseCase, + selectCollatorRequester = selectCollatorInterScreenRequester ) }, rewardsComponentFactory = rewardsComponentFactory, @@ -76,11 +84,21 @@ class SetupStartMythosStakingViewModel( override val hintsMixin = NoHintsMixin() override suspend fun openSelectNewTarget() { - showMessage("TODO") + val delegatorState = logic.currentDelegatorStateFlow.first() + + when (val check = interactor.checkDelegationsLimit(delegatorState)) { + DelegationsLimit.NotReached -> selectCollatorInterScreenRequester.openRequest() + is DelegationsLimit.Reached -> { + showError( + title = resourceManager.getString(R.string.staking_parachain_max_delegations_title), + text = resourceManager.getString(R.string.staking_parachain_max_delegations_message, check.limit) + ) + } + } } override suspend fun openSelectFirstTarget() { - showMessage("TODO") + selectCollatorInterScreenRequester.openRequest() } override suspend fun goNext(target: MythosCollator, amount: BigDecimal, fee: Fee, asset: Asset) { @@ -129,6 +147,7 @@ class SetupStartMythosStakingViewModel( private val mythosCollatorFormatter: MythosCollatorFormatter, private val mythosDelegatorStateUseCase: MythosDelegatorStateUseCase, private val interactor: StartMythosStakingInteractor, + private val selectCollatorRequester: SelectMythosInterScreenRequester, ) : StartSingleSelectStakingLogic, ComputationalScope by computationalScope { @@ -136,8 +155,8 @@ class SetupStartMythosStakingViewModel( .shareInBackground() override fun selectedTargetChanges(): Flow { - // TODO - return emptyFlow() + return selectCollatorRequester.responseFlow + .map { it.toDomain() } } override fun stakeableAmount(assetFlow: Flow): Flow { @@ -164,7 +183,7 @@ class SetupStartMythosStakingViewModel( } override suspend fun mapStakedTargetToUi(target: TargetWithStakedAmount, asset: Asset): SelectStakeTargetModel { - return mythosCollatorFormatter.collatorToUi(target, asset) + return mythosCollatorFormatter.collatorToSelectUi(target, asset.token) } override suspend fun minimumStakeToGetRewards(selectedStakeTarget: MythosCollator?): Balance { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt index b500eacb94..e4db51928a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt @@ -17,6 +17,8 @@ import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.MythosSh import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendatorFactory import io.novafoundation.nova.feature_staking_impl.domain.mythos.start.StartMythosStakingInteractor import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenRequester import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.SetupStartMythosStakingViewModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.rewards.MythosStakingRewardsComponentFactory @@ -45,6 +47,7 @@ class SetupStartMythosStakingModule { mythosCollatorFormatter: MythosCollatorFormatter, interactor: StartMythosStakingInteractor, amountChooserMixinFactory: AmountChooserMixin.Factory, + selectCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator ): ViewModel { return SetupStartMythosStakingViewModel( router = router, @@ -60,7 +63,8 @@ class SetupStartMythosStakingModule { mythosSharedComputation = mythosSharedComputation, mythosCollatorFormatter = mythosCollatorFormatter, interactor = interactor, - amountChooserMixinFactory = amountChooserMixinFactory + amountChooserMixinFactory = amountChooserMixinFactory, + selectCollatorInterScreenRequester = selectCollatorInterScreenCommunicator ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorFragment.kt index 6e441a1aff..694b1383fc 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorFragment.kt @@ -1,75 +1,12 @@ package io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import io.novafoundation.nova.common.base.BaseFragment import io.novafoundation.nova.common.di.FeatureUtils -import io.novafoundation.nova.common.utils.applyStatusBarInsets -import io.novafoundation.nova.common.utils.makeGone -import io.novafoundation.nova.common.utils.makeVisible -import io.novafoundation.nova.common.utils.scrollToTopWhenItemsShuffled import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi -import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.model.Collator -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.mappers.CollatorModel -import io.novafoundation.nova.feature_staking_impl.presentation.validators.StakeTargetAdapter -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorClearFilters -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorContainer -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorContentGroup -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorCount -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorList -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorProgress -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorSorting -import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorToolbar +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SingleSelectChooseTargetFragment -class SelectCollatorFragment : BaseFragment(), StakeTargetAdapter.ItemHandler { - - val adapter by lazy(LazyThreadSafetyMode.NONE) { - StakeTargetAdapter(this) - } - - private var filterAction: ImageView? = null - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_parachain_staking_select_collator, container, false) - } - - override fun initViews() { - selectCollatorContainer.applyStatusBarInsets() - - selectCollatorList.adapter = adapter - selectCollatorList.setHasFixedSize(true) - selectCollatorList.itemAnimator = null - - selectCollatorToolbar.setHomeButtonListener { viewModel.backClicked() } - onBackPressed { viewModel.backClicked() } - - filterAction = selectCollatorToolbar.addCustomAction(R.drawable.ic_filter) { - viewModel.settingsClicked() - } - - selectCollatorToolbar.addCustomAction(R.drawable.ic_search) { - viewModel.searchClicked() - } - - selectCollatorList.scrollToTopWhenItemsShuffled(viewLifecycleOwner) - - selectCollatorClearFilters.setOnClickListener { viewModel.clearFiltersClicked() } - } - - override fun onDestroyView() { - super.onDestroyView() - - filterAction = null - } +class SelectCollatorFragment : SingleSelectChooseTargetFragment() { override fun inject() { FeatureUtils.getFeature( @@ -80,31 +17,4 @@ class SelectCollatorFragment : BaseFragment(), StakeTar .create(this) .inject(this) } - - override fun subscribe(viewModel: SelectCollatorViewModel) { - viewModel.collatorModelsFlow.observe { - adapter.submitList(it) - - selectCollatorContentGroup.makeVisible() - selectCollatorProgress.makeGone() - } - - viewModel.collatorsTitle.observe(selectCollatorCount::setText) - - viewModel.scoringHeader.observe(selectCollatorSorting::setText) - - viewModel.recommendationSettingsIcon.observe { icon -> - filterAction?.setImageResource(icon) - } - - viewModel.clearFiltersEnabled.observe(selectCollatorClearFilters::setEnabled) - } - - override fun stakeTargetInfoClicked(stakeTargetModel: CollatorModel) { - viewModel.collatorInfoClicked(stakeTargetModel) - } - - override fun stakeTargetClicked(stakeTargetModel: CollatorModel) { - viewModel.collatorClicked(stakeTargetModel) - } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorViewModel.kt index cab16e7a04..170ef58246 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/collator/select/SelectCollatorViewModel.kt @@ -1,11 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select import io.novafoundation.nova.common.address.AddressIconGenerator -import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.resources.ResourceManager -import io.novafoundation.nova.common.utils.inBackground -import io.novafoundation.nova.common.utils.invoke -import io.novafoundation.nova.common.utils.lazyAsync import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.CollatorsUseCase @@ -14,6 +10,8 @@ import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.commo import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.recommendations.CollatorRecommendatorFactory import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.recommendations.CollatorSorting import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SearchAction +import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SingleSelectChooseTargetViewModel import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator.Response import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenResponder import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.details.parachain @@ -22,22 +20,16 @@ import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenRequester import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.mapCollatorRecommendationConfigFromParcel import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.mapCollatorRecommendationConfigToParcel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.mappers.CollatorModel import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.mappers.mapCollatorToCollatorModel import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.mappers.mapCollatorToDetailsParcelModel +import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase import io.novafoundation.nova.feature_wallet_api.domain.model.Token import io.novafoundation.nova.runtime.state.chain -import io.novafoundation.nova.runtime.state.selectedOption import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext class SelectCollatorViewModel( @@ -45,120 +37,91 @@ class SelectCollatorViewModel( private val selectCollatorInterScreenResponder: SelectCollatorInterScreenResponder, private val selectCollatorSettingsInterScreenRequester: SelectCollatorSettingsInterScreenRequester, private val collatorsUseCase: CollatorsUseCase, - private val collatorRecommendatorFactory: CollatorRecommendatorFactory, - private val addressIconGenerator: AddressIconGenerator, - private val resourceManager: ResourceManager, - private val tokenUseCase: TokenUseCase, - private val selectedAssetState: StakingSharedState, -) : BaseViewModel() { - - private val collatorRecommendator by lazyAsync { - collatorRecommendatorFactory.create(selectedAssetState.selectedOption(), computationalScope = this) - } - - private val recommendationConfigFlow = MutableStateFlow(defaultConfig()) - - val recommendationSettingsIcon = recommendationConfigFlow.map { - val isChanged = it != CollatorRecommendationConfig.DEFAULT - - if (isChanged) R.drawable.ic_filter_indicator else R.drawable.ic_filter - } - .shareInBackground() - - val clearFiltersEnabled = recommendationConfigFlow.map { - it != defaultConfig() - }.shareInBackground() - - private val shownValidators = recommendationConfigFlow.map { - collatorRecommendator().recommendations(it) - }.shareInBackground() - - private val tokenFlow = tokenUseCase.currentTokenFlow() - .inBackground() - .share() - - val collatorModelsFlow = combine(shownValidators, tokenFlow, ::convertToModels) - .shareInBackground() - - val collatorsTitle = shownValidators.map { - resourceManager.getString(R.string.staking_parachain_collators_number_format, it.size) - }.shareInBackground() - - val scoringHeader = recommendationConfigFlow.map { - when (it.sorting) { - CollatorSorting.REWARDS -> resourceManager.getString(R.string.staking_rewards) - CollatorSorting.MIN_STAKE -> resourceManager.getString(R.string.staking_main_minimum_stake_title) - CollatorSorting.TOTAL_STAKE -> resourceManager.getString(R.string.staking_validator_total_stake) - CollatorSorting.OWN_STAKE -> resourceManager.getString(R.string.staking_parachain_collator_own_stake) + collatorRecommendatorFactory: CollatorRecommendatorFactory, + addressIconGenerator: AddressIconGenerator, + resourceManager: ResourceManager, + tokenUseCase: TokenUseCase, + selectedAssetState: StakingSharedState, +) : SingleSelectChooseTargetViewModel( + router = router, + recommendatorFactory = collatorRecommendatorFactory, + resourceManager = resourceManager, + tokenUseCase = tokenUseCase, + selectedAssetState = selectedAssetState, + state = CollatorState( + router = router, + selectCollatorSettingsInterScreenRequester = selectCollatorSettingsInterScreenRequester, + addressIconGenerator = addressIconGenerator, + resourceManager = resourceManager, + selectedAssetState = selectedAssetState + ) +) { + + class CollatorState( + private val router: ParachainStakingRouter, + private val selectCollatorSettingsInterScreenRequester: SelectCollatorSettingsInterScreenRequester, + private val addressIconGenerator: AddressIconGenerator, + private val resourceManager: ResourceManager, + private val selectedAssetState: StakingSharedState, + ) : SingleSelectChooseTargetState { + + override val defaultRecommendatorConfig: CollatorRecommendationConfig = CollatorRecommendationConfig.DEFAULT + + override val searchAction: SearchAction = { + router.openSearchCollator() } - }.shareInBackground() - - init { - listenRecommendationConfigChanges() - } - - fun clearFiltersClicked() { - recommendationConfigFlow.value = defaultConfig() - } - - fun backClicked() { - router.back() - } - fun collatorInfoClicked(collatorModel: CollatorModel) { - launch { - val payload = withContext(Dispatchers.Default) { - val parcel = mapCollatorToDetailsParcelModel(collatorModel.stakeTarget) + override fun recommendationConfigChanges(): Flow { + return selectCollatorSettingsInterScreenRequester.responseFlow + .map { mapCollatorRecommendationConfigFromParcel(it.newConfig) } + } - StakeTargetDetailsPayload.parachain(parcel, collatorsUseCase) + override fun scoringHeaderFor(config: CollatorRecommendationConfig): String { + return when (config.sorting) { + CollatorSorting.REWARDS -> resourceManager.getString(R.string.staking_rewards) + CollatorSorting.MIN_STAKE -> resourceManager.getString(R.string.staking_main_minimum_stake_title) + CollatorSorting.TOTAL_STAKE -> resourceManager.getString(R.string.staking_validator_total_stake) + CollatorSorting.OWN_STAKE -> resourceManager.getString(R.string.staking_parachain_collator_own_stake) } - - router.openCollatorDetails(payload) } - } - fun collatorClicked(collatorModel: CollatorModel) = launch { - val response = withContext(Dispatchers.Default) { - Response(mapCollatorToCollatorParcelModel(collatorModel.stakeTarget)) + override suspend fun convertTargetsToUi( + targets: List, + token: Token, + config: CollatorRecommendationConfig, + ): List> { + return targets.map { collator -> + mapCollatorToCollatorModel( + chain = selectedAssetState.chain(), + collator = collator, + addressIconGenerator = addressIconGenerator, + sorting = config.sorting, + resourceManager = resourceManager, + token = token + ) + } } - - selectCollatorInterScreenResponder.respond(response) - router.returnToStartStaking() } - fun settingsClicked() = launch { - val currentConfig = mapCollatorRecommendationConfigToParcel(recommendationConfigFlow.first()) - - selectCollatorSettingsInterScreenRequester.openRequest(Request((currentConfig))) + override fun settingsClicked(currentConfig: CollatorRecommendationConfig) { + val configPayload = mapCollatorRecommendationConfigToParcel(currentConfig) + selectCollatorSettingsInterScreenRequester.openRequest(Request((configPayload))) } - fun searchClicked() { - router.openSearchCollator() - } + override suspend fun targetSelected(target: Collator) { + val response = Response(mapCollatorToCollatorParcelModel(target)) - private fun listenRecommendationConfigChanges() { - selectCollatorSettingsInterScreenRequester.responseFlow - .map { mapCollatorRecommendationConfigFromParcel(it.newConfig) } - .onEach { recommendationConfigFlow.value = it } - .inBackground() - .launchIn(this) + selectCollatorInterScreenResponder.respond(response) + router.returnToStartStaking() } - private fun defaultConfig() = CollatorRecommendationConfig(CollatorSorting.REWARDS) + override suspend fun targetInfoClicked(target: Collator) { + val payload = withContext(Dispatchers.Default) { + val parcel = mapCollatorToDetailsParcelModel(target) - private suspend fun convertToModels( - collators: List, - token: Token, - ): List { - return collators.map { collator -> - mapCollatorToCollatorModel( - chain = selectedAssetState.chain(), - collator = collator, - addressIconGenerator = addressIconGenerator, - sorting = recommendationConfigFlow.first().sorting, - resourceManager = resourceManager, - token = token - ) + StakeTargetDetailsPayload.parachain(parcel, collatorsUseCase) } + + router.openCollatorDetails(payload) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt index ec32e5523a..2f2db5382b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt @@ -3,7 +3,6 @@ package io.novafoundation.nova.feature_staking_impl.presentation.parachainStakin import io.novafoundation.nova.common.address.AddressIconGenerator import io.novafoundation.nova.common.presentation.ColoredText import io.novafoundation.nova.common.resources.ResourceManager -import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.DelegationState import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.model.Collator @@ -12,6 +11,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.mappers.mapIdent import io.novafoundation.nova.feature_staking_impl.presentation.mappers.rewardsToColoredText import io.novafoundation.nova.feature_staking_impl.presentation.mappers.rewardsToScoring import io.novafoundation.nova.feature_staking_impl.presentation.mappers.stakeToScoring +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.common.collators.collatorAddressModel import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakeTargetDetailsParcelModel import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakeTargetStakeParcelModel @@ -33,12 +33,9 @@ suspend fun mapCollatorToCollatorModel( resourceManager: ResourceManager, token: Token, ): CollatorModel { - val address = chain.addressOf(collator.accountIdHex.fromHex()) - - val addressModel = addressIconGenerator.createAccountAddressModel( - address = address, - chain = chain, - name = collator.identity?.display + val addressModel = addressIconGenerator.collatorAddressModel( + collator = collator, + chain = chain ) val scoring = when (sorting) { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorDetailsViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorDetailsViewModel.kt index aec7dcf5d0..f7ef04866b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorDetailsViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorDetailsViewModel.kt @@ -89,11 +89,11 @@ class ValidatorDetailsViewModel( private suspend fun calculatePayload(asset: Asset, stakeTargetStake: StakeTargetStakeParcelModel) = withContext(Dispatchers.Default) { require(stakeTargetStake is StakeTargetStakeParcelModel.Active) - val nominatorsStake = stakeTargetStake.stakers.sumByBigInteger(StakerParcelModel::value) + val nominatorsStake = stakeTargetStake.stakers?.sumByBigInteger(StakerParcelModel::value) ValidatorStakeBottomSheet.Payload( - own = mapAmountToAmountModel(stakeTargetStake.ownStake, asset), - stakers = mapAmountToAmountModel(nominatorsStake, asset), + own = stakeTargetStake.ownStake?.let { mapAmountToAmountModel(it, asset) }, + stakers = nominatorsStake?.let { mapAmountToAmountModel(it, asset) }, total = mapAmountToAmountModel(stakeTargetStake.totalStake, asset), stakersLabel = payload.displayConfig.stakersLabelRes ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorStakeBottomSheet.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorStakeBottomSheet.kt index f45e8ec10f..2858e88029 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorStakeBottomSheet.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/details/ValidatorStakeBottomSheet.kt @@ -13,6 +13,7 @@ import io.novafoundation.nova.common.view.bottomSheet.list.fixed.FixedListBottom import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_wallet_api.presentation.model.AmountModel import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmount +import io.novafoundation.nova.feature_wallet_api.presentation.view.showAmountOrHide class ValidatorStakeBottomSheet( context: Context, @@ -20,8 +21,8 @@ class ValidatorStakeBottomSheet( ) : FixedListBottomSheet(context), WithContextExtensions by WithContextExtensions(context) { class Payload( - val own: AmountModel, - val stakers: AmountModel, + val own: AmountModel?, + val stakers: AmountModel?, val total: AmountModel, @StringRes val stakersLabel: Int ) @@ -33,12 +34,12 @@ class ValidatorStakeBottomSheet( item(createCellView()) { it.setTitle(R.string.staking_validator_own_stake) - it.showAmount(payload.own) + it.showAmountOrHide(payload.own) } item(createCellView()) { it.setTitle(payload.stakersLabel) - it.showAmount(payload.stakers) + it.showAmountOrHide(payload.stakers) } item(createCellView()) { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/parcel/StakeTargetStakeParcelModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/parcel/StakeTargetStakeParcelModel.kt index c485e46ed9..820c00cbe1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/parcel/StakeTargetStakeParcelModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/validators/parcel/StakeTargetStakeParcelModel.kt @@ -1,6 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel import android.os.Parcelable +import io.novafoundation.nova.common.utils.orZero import kotlinx.android.parcel.Parcelize import java.math.BigDecimal import java.math.BigInteger @@ -13,9 +14,10 @@ sealed class StakeTargetStakeParcelModel : Parcelable { @Parcelize class Active( val totalStake: BigInteger, - val ownStake: BigInteger, + val ownStake: BigInteger?, // null in case unknown val minimumStake: BigInteger?, // null in case there is no separate min stake for this stake target - val stakers: List, + val stakers: List?, // null in case unknown + val stakersCount: Int = stakers?.size.orZero(), val rewards: BigDecimal, val isOversubscribed: Boolean, val userStakeInfo: UserStakeInfo? = null From 0dc5fdc68041bb101f7e1f6ad4fc129c57c5ab43 Mon Sep 17 00:00:00 2001 From: valentunn Date: Tue, 21 Jan 2025 14:31:21 +0300 Subject: [PATCH 2/3] Select myth collator settings --- .../staking/MythosStakingNavigationModule.kt | 8 +++ ...atorSettingsInterScreenCommunicatorImpl.kt | 24 +++++++ ...atorSettingsInterScreenCommunicatorImpl.kt | 2 + .../navigation/staking_mythos_start_graph.xml | 15 +++- .../di/StakingFeatureComponent.kt | 8 ++- .../di/StakingFeatureHolder.kt | 5 +- .../SelectMythosCollatorViewModel.kt | 19 +++-- .../di/SelectMythosCollatorModule.kt | 8 ++- .../SelectMythCollatorSettingsFragment.kt | 70 +++++++++++++++++++ ...CollatorSettingsInterScreenCommunicator.kt | 10 +++ .../SelectMythCollatorSettingsViewModel.kt | 52 ++++++++++++++ .../di/SelectMythCollatorSettingsComponent.kt | 30 ++++++++ .../di/SelectMythCollatorSettingsModule.kt | 46 ++++++++++++ .../MythCollatorRecommendationConfigParcel.kt | 17 +++++ ...ythos_staking_select_collator_settings.xml | 69 ++++++++++++++++++ 15 files changed, 373 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsInterScreenCommunicator.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt create mode 100644 feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/model/MythCollatorRecommendationConfigParcel.kt create mode 100644 feature-staking-impl/src/main/res/layout/fragment_mythos_staking_select_collator_settings.xml diff --git a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt index c6db572659..d3e63fdaaa 100644 --- a/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt +++ b/app/src/main/java/io/novafoundation/nova/app/di/app/navigation/staking/MythosStakingNavigationModule.kt @@ -4,10 +4,12 @@ import dagger.Module import dagger.Provides import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRegistry import io.novafoundation.nova.app.root.navigation.navigators.staking.mythos.MythosStakingNavigator +import io.novafoundation.nova.app.root.navigation.navigators.staking.mythos.SelectMythCollatorSettingsInterScreenCommunicatorImpl import io.novafoundation.nova.app.root.navigation.navigators.staking.mythos.SelectMythosCollatorInterScreenCommunicatorImpl import io.novafoundation.nova.common.di.scope.ApplicationScope import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator @Module class MythosStakingNavigationModule { @@ -25,4 +27,10 @@ class MythosStakingNavigationModule { fun provideSelectCollatorCommunicator(navigationHoldersRegistry: NavigationHoldersRegistry): SelectMythosInterScreenCommunicator { return SelectMythosCollatorInterScreenCommunicatorImpl(navigationHoldersRegistry) } + + @Provides + @ApplicationScope + fun provideSelectSettingsCollatorCommunicator(navigationHoldersRegistry: NavigationHoldersRegistry): SelectMythCollatorSettingsInterScreenCommunicator { + return SelectMythCollatorSettingsInterScreenCommunicatorImpl(navigationHoldersRegistry) + } } diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt new file mode 100644 index 0000000000..5fb6ad5982 --- /dev/null +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt @@ -0,0 +1,24 @@ +package io.novafoundation.nova.app.root.navigation.navigators.staking.mythos + +import io.novafoundation.nova.app.R +import io.novafoundation.nova.app.root.navigation.NavStackInterScreenCommunicator +import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRegistry +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsFragment +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsFragment +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator.Request +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator.Response + +class SelectMythCollatorSettingsInterScreenCommunicatorImpl(navigationHoldersRegistry: NavigationHoldersRegistry) : + SelectMythCollatorSettingsInterScreenCommunicator, + NavStackInterScreenCommunicator(navigationHoldersRegistry) { + + override fun openRequest(request: MythCollatorRecommendationConfigParcel) { + super.openRequest(request) + + val bundle = SelectMythCollatorSettingsFragment.getBundle(request) + navController.navigate(R.id.action_selectMythosCollatorFragment_to_selectMythCollatorSettingsFragment, bundle) + } +} diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/parachain/SelectCollatorSettingsInterScreenCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/parachain/SelectCollatorSettingsInterScreenCommunicatorImpl.kt index 7841a0c416..73cf8c7593 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/parachain/SelectCollatorSettingsInterScreenCommunicatorImpl.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/parachain/SelectCollatorSettingsInterScreenCommunicatorImpl.kt @@ -13,6 +13,8 @@ class SelectCollatorSettingsInterScreenCommunicatorImpl(navigationHoldersRegistr NavStackInterScreenCommunicator(navigationHoldersRegistry) { override fun openRequest(request: Request) { + super.openRequest(request) + val bundle = SelectCollatorSettingsFragment.getBundle(request.currentConfig) navController.navigate(R.id.action_selectCollatorFragment_to_selectCollatorSettingsFragment, bundle) } diff --git a/app/src/main/res/navigation/staking_mythos_start_graph.xml b/app/src/main/res/navigation/staking_mythos_start_graph.xml index b796ee6634..4437e1fa1b 100644 --- a/app/src/main/res/navigation/staking_mythos_start_graph.xml +++ b/app/src/main/res/navigation/staking_mythos_start_graph.xml @@ -31,5 +31,18 @@ + android:label="SelectMythosCollatorFragment"> + + + + \ No newline at end of file diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt index e1201e4493..d273c1245f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt @@ -34,6 +34,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.dashboard.main.d import io.novafoundation.nova.feature_staking_impl.presentation.dashboard.more.di.MoreStakingOptionsComponent import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.di.SelectMythosCollatorComponent +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.di.SelectMythCollatorSettingsComponent import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.di.SetupStartMythosStakingComponent import io.novafoundation.nova.feature_staking_impl.presentation.nominationPools.bondMore.confirm.di.NominationPoolsConfirmBondMoreComponent import io.novafoundation.nova.feature_staking_impl.presentation.nominationPools.bondMore.setup.di.NominationPoolsSetupBondMoreComponent @@ -245,6 +247,9 @@ interface StakingFeatureComponent : StakingFeatureApi { fun selectMythosCollatorFactory(): SelectMythosCollatorComponent.Factory + fun selectMythosSettingsFactory(): SelectMythCollatorSettingsComponent.Factory + + @Component.Factory interface Factory { @@ -257,7 +262,8 @@ interface StakingFeatureComponent : StakingFeatureApi { @BindsInstance selectAddressCommunicator: SelectAddressCommunicator, @BindsInstance mythosStakingRouter: MythosStakingRouter, - @BindsInstance selectMythosCollatorSettingsInterScreenCommunicator: SelectMythosInterScreenCommunicator, + @BindsInstance selectMythosCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator, + @BindsInstance selectMythosCollatorSettingsInterScreenCommunicator: SelectMythCollatorSettingsInterScreenCommunicator, @BindsInstance nominationPoolsRouter: NominationPoolsRouter, diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt index 6725cdfb89..27042c059a 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureHolder.kt @@ -15,6 +15,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.StakingDashboard import io.novafoundation.nova.feature_staking_impl.presentation.StakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.StartMultiStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator import io.novafoundation.nova.feature_wallet_api.di.WalletFeatureApi @@ -33,7 +34,8 @@ class StakingFeatureHolder @Inject constructor( private val selectAddressCommunicator: SelectAddressCommunicator, private val selectCollatorInterScreenCommunicator: SelectCollatorInterScreenCommunicator, private val selectCollatorSettingsInterScreenCommunicator: SelectCollatorSettingsInterScreenCommunicator, - private val selectMythosCollatorSettingsInterScreenCommunicator: SelectMythosInterScreenCommunicator, + private val selectMythosCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator, + private val selectMythosCollatorSettingsInterScreenCommunicator: SelectMythCollatorSettingsInterScreenCommunicator, ) : FeatureApiHolder(featureContainer) { override fun initializeDependencies(): Any { @@ -58,6 +60,7 @@ class StakingFeatureHolder @Inject constructor( nominationPoolsRouter = nominationPoolsRouter, startMultiStakingRouter = startMultiStakingRouter, stakingDashboardRouter = stakingDashboardRouter, + selectMythosCollatorInterScreenCommunicator = selectMythosCollatorInterScreenCommunicator, selectMythosCollatorSettingsInterScreenCommunicator = selectMythosCollatorSettingsInterScreenCommunicator, deps = dependencies ) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt index b918f833b7..b01ba8850b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorViewModel.kt @@ -14,12 +14,15 @@ import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMyt import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.details.mythos import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.model.toParcelable +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenRequester +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toDomain +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toParcel import io.novafoundation.nova.feature_staking_impl.presentation.validators.change.StakeTargetModel import io.novafoundation.nova.feature_staking_impl.presentation.validators.details.StakeTargetDetailsPayload import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase import io.novafoundation.nova.feature_wallet_api.domain.model.Token import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.map class SelectMythosCollatorViewModel( private val router: MythosStakingRouter, @@ -29,17 +32,22 @@ class SelectMythosCollatorViewModel( private val selectedAssetState: StakingSharedState, private val mythosCollatorFormatter: MythosCollatorFormatter, private val selectCollatorResponder: SelectMythosInterScreenResponder, + private val settingsRequester: SelectMythCollatorSettingsInterScreenRequester ) : SingleSelectChooseTargetViewModel( router = router, recommendatorFactory = recommendatorFactory, resourceManager = resourceManager, tokenUseCase = tokenUseCase, selectedAssetState = selectedAssetState, - state = MythosState(mythosCollatorFormatter, resourceManager) + state = MythosState( + mythosCollatorFormatter = mythosCollatorFormatter, + resourceManager = resourceManager, + settingsRequester = settingsRequester + ) ) { override fun settingsClicked(currentConfig: MythosCollatorRecommendationConfig) { - showMessage("TODO") + settingsRequester.openRequest(currentConfig.toParcel()) } override suspend fun targetInfoClicked(target: MythosCollator) { @@ -55,6 +63,7 @@ class SelectMythosCollatorViewModel( class MythosState( private val mythosCollatorFormatter: MythosCollatorFormatter, private val resourceManager: ResourceManager, + private val settingsRequester: SelectMythCollatorSettingsInterScreenRequester ) : SingleSelectChooseTargetState { override val defaultRecommendatorConfig: MythosCollatorRecommendationConfig = MythosCollatorRecommendationConfig.DEFAULT @@ -79,8 +88,8 @@ class SelectMythosCollatorViewModel( } override fun recommendationConfigChanges(): Flow { - // TODO settings - return emptyFlow() + return settingsRequester.responseFlow + .map { it.toDomain() } } } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt index 13f3703db1..7e0ccb8894 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt @@ -20,6 +20,8 @@ import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStaking import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenRequester import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select.SelectCollatorViewModel import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator @@ -38,7 +40,8 @@ class SelectMythosCollatorModule { tokenUseCase: TokenUseCase, selectedAssetState: StakingSharedState, mythosCollatorFormatter: MythosCollatorFormatter, - selectCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator + selectCollatorInterScreenCommunicator: SelectMythosInterScreenCommunicator, + settingsRequester: SelectMythCollatorSettingsInterScreenCommunicator ): ViewModel { return SelectMythosCollatorViewModel( router = router, @@ -47,7 +50,8 @@ class SelectMythosCollatorModule { tokenUseCase = tokenUseCase, selectedAssetState = selectedAssetState, mythosCollatorFormatter = mythosCollatorFormatter, - selectCollatorResponder = selectCollatorInterScreenCommunicator + selectCollatorResponder = selectCollatorInterScreenCommunicator, + settingsRequester = settingsRequester ) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt new file mode 100644 index 0000000000..a64162b4ce --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt @@ -0,0 +1,70 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.os.bundleOf +import androidx.lifecycle.lifecycleScope +import io.novafoundation.nova.common.base.BaseFragment +import io.novafoundation.nova.common.di.FeatureUtils +import io.novafoundation.nova.common.utils.bindTo +import io.novafoundation.nova.common.view.ButtonState +import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi +import io.novafoundation.nova.feature_staking_impl.R +import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorSorting +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsApply +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsSort +import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsToolbar + +private val SORT_MAPPING = mapOf( + MythosCollatorSorting.REWARDS to R.id.selectCollatorSettingsSortRewards, + MythosCollatorSorting.TOTAL_STAKE to R.id.selectCollatorSettingsSortTotalStake, +) + +class SelectMythCollatorSettingsFragment : BaseFragment() { + + companion object { + + private const val PAYLOAD_KEY = "SelectMythCollatorSettingsFragment.Payload" + + fun getBundle(payload: MythCollatorRecommendationConfigParcel) = bundleOf(PAYLOAD_KEY to payload) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_mythos_staking_select_collator_settings, container, false) + } + + override fun initViews() { + selectCollatorSettingsApply.setOnClickListener { viewModel.applyChanges() } + + selectCollatorSettingsToolbar.setHomeButtonListener { viewModel.backClicked() } + selectCollatorSettingsToolbar.setRightActionClickListener { viewModel.reset() } + } + + override fun inject() { + FeatureUtils.getFeature( + requireContext(), + StakingFeatureApi::class.java + ) + .selectMythosSettingsFactory() + .create(this, argument(PAYLOAD_KEY)) + .inject(this) + } + + override fun subscribe(viewModel: SelectMythCollatorSettingsViewModel) { + selectCollatorSettingsSort.bindTo(viewModel.selectedSortingFlow, lifecycleScope, SORT_MAPPING) + + viewModel.isApplyButtonEnabled.observe { + selectCollatorSettingsApply.setState(if (it) ButtonState.NORMAL else ButtonState.DISABLED) + } + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsInterScreenCommunicator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsInterScreenCommunicator.kt new file mode 100644 index 0000000000..ee3b115775 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsInterScreenCommunicator.kt @@ -0,0 +1,10 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings + +import io.novafoundation.nova.common.navigation.InterScreenRequester +import io.novafoundation.nova.common.navigation.InterScreenResponder +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel + +interface SelectMythCollatorSettingsInterScreenRequester : InterScreenRequester +interface SelectMythCollatorSettingsInterScreenResponder : InterScreenResponder + +interface SelectMythCollatorSettingsInterScreenCommunicator : SelectMythCollatorSettingsInterScreenRequester, SelectMythCollatorSettingsInterScreenResponder diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt new file mode 100644 index 0000000000..16a10e343e --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt @@ -0,0 +1,52 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings + +import androidx.lifecycle.viewModelScope +import io.novafoundation.nova.common.base.BaseViewModel +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendationConfig +import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toDomain +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toParcel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch + +class SelectMythCollatorSettingsViewModel( + private val router: MythosStakingRouter, + private val payload: MythCollatorRecommendationConfigParcel, + private val selectCollatorSettingsInterScreenResponder: SelectMythCollatorSettingsInterScreenResponder, +) : BaseViewModel() { + + val selectedSortingFlow = MutableStateFlow(payload.sorting) + + private val initialConfig = payload.toDomain() + + private val modifiedConfig = selectedSortingFlow.map(::MythosCollatorRecommendationConfig) + .share() + + val isApplyButtonEnabled = modifiedConfig.map { modified -> + initialConfig != modified + }.share() + + fun reset() { + viewModelScope.launch { + val defaultSettings = MythosCollatorRecommendationConfig.DEFAULT + selectedSortingFlow.value = defaultSettings.sorting + } + } + + fun applyChanges() { + viewModelScope.launch { + val newConfig = modifiedConfig.first().toParcel() + selectCollatorSettingsInterScreenResponder.respond(newConfig) + + router.back() + } + } + + fun backClicked() { + router.back() + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt new file mode 100644 index 0000000000..43fac4dc76 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt @@ -0,0 +1,30 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.di + +import androidx.fragment.app.Fragment +import dagger.BindsInstance +import dagger.Subcomponent +import io.novafoundation.nova.common.di.scope.ScreenScope +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsFragment +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsFragment +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel + +@Subcomponent( + modules = [ + SelectMythCollatorSettingsModule::class + ] +) +@ScreenScope +interface SelectMythCollatorSettingsComponent { + + @Subcomponent.Factory + interface Factory { + + fun create( + @BindsInstance fragment: Fragment, + @BindsInstance payload: MythCollatorRecommendationConfigParcel, + ): SelectMythCollatorSettingsComponent + } + + fun inject(fragment: SelectMythCollatorSettingsFragment) +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt new file mode 100644 index 0000000000..3258e88754 --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt @@ -0,0 +1,46 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.di + +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoMap +import io.novafoundation.nova.common.di.viewmodel.ViewModelKey +import io.novafoundation.nova.common.di.viewmodel.ViewModelModule +import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenResponder +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsViewModel +import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel + +@Module(includes = [ViewModelModule::class]) +class SelectMythCollatorSettingsModule { + + @Provides + @IntoMap + @ViewModelKey(SelectMythCollatorSettingsViewModel::class) + fun provideViewModel( + router: MythosStakingRouter, + payload: MythCollatorRecommendationConfigParcel, + selectCollatorSettingsInterScreenResponder: SelectMythCollatorSettingsInterScreenCommunicator, + ): ViewModel { + return SelectMythCollatorSettingsViewModel( + router = router, + payload = payload, + selectCollatorSettingsInterScreenResponder = selectCollatorSettingsInterScreenResponder + ) + } + + @Provides + fun provideViewModelCreator( + fragment: Fragment, + viewModelFactory: ViewModelProvider.Factory + ): SelectMythCollatorSettingsViewModel { + return ViewModelProvider(fragment, viewModelFactory).get(SelectMythCollatorSettingsViewModel::class.java) + } +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/model/MythCollatorRecommendationConfigParcel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/model/MythCollatorRecommendationConfigParcel.kt new file mode 100644 index 0000000000..96bc7431ff --- /dev/null +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/model/MythCollatorRecommendationConfigParcel.kt @@ -0,0 +1,17 @@ +package io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model + +import android.os.Parcelable +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendationConfig +import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorSorting +import kotlinx.android.parcel.Parcelize + +@Parcelize +class MythCollatorRecommendationConfigParcel(val sorting: MythosCollatorSorting) : Parcelable + +fun MythosCollatorRecommendationConfig.toParcel(): MythCollatorRecommendationConfigParcel { + return MythCollatorRecommendationConfigParcel(sorting) +} + +fun MythCollatorRecommendationConfigParcel.toDomain(): MythosCollatorRecommendationConfig { + return MythosCollatorRecommendationConfig(sorting) +} diff --git a/feature-staking-impl/src/main/res/layout/fragment_mythos_staking_select_collator_settings.xml b/feature-staking-impl/src/main/res/layout/fragment_mythos_staking_select_collator_settings.xml new file mode 100644 index 0000000000..a65f45ace8 --- /dev/null +++ b/feature-staking-impl/src/main/res/layout/fragment_mythos_staking_select_collator_settings.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file From f43db62aaee748d3896268aad32e9a0123672683 Mon Sep 17 00:00:00 2001 From: valentunn Date: Tue, 21 Jan 2025 14:32:51 +0300 Subject: [PATCH 3/3] Code style --- ...ectMythCollatorSettingsInterScreenCommunicatorImpl.kt | 4 ---- .../nova/common/address/AccountIdParcel.kt | 2 +- .../feature_staking_impl/di/StakingFeatureComponent.kt | 1 - .../domain/mythos/common/model/MythosDelegatorState.kt | 2 +- .../domain/mythos/start/StartMythosStakingInteractor.kt | 2 -- .../chooseTarget/SingleSelectChooseTargetFragment.kt | 3 ++- .../chooseTarget/SingleSelectChooseTargetViewModel.kt | 1 - .../presentation/mappers/Validator.kt | 2 -- .../start/selectCollator/SelectMythosCollatorFragment.kt | 1 - .../selectCollator/di/SelectMythosCollatorComponent.kt | 1 - .../selectCollator/di/SelectMythosCollatorModule.kt | 9 --------- .../SelectMythCollatorSettingsFragment.kt | 2 -- .../SelectMythCollatorSettingsViewModel.kt | 1 - .../di/SelectMythCollatorSettingsComponent.kt | 2 -- .../di/SelectMythCollatorSettingsModule.kt | 5 ----- .../start/setup/SetupStartMythosStakingViewModel.kt | 1 - .../start/setup/di/SetupStartMythosStakingModule.kt | 1 - .../parachainStaking/common/mappers/Collator.kt | 2 -- 18 files changed, 4 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt index 5fb6ad5982..380f742e74 100644 --- a/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt +++ b/app/src/main/java/io/novafoundation/nova/app/root/navigation/navigators/staking/mythos/SelectMythCollatorSettingsInterScreenCommunicatorImpl.kt @@ -6,10 +6,6 @@ import io.novafoundation.nova.app.root.navigation.navigators.NavigationHoldersRe import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsFragment import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsFragment -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator.Request -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator.Response class SelectMythCollatorSettingsInterScreenCommunicatorImpl(navigationHoldersRegistry: NavigationHoldersRegistry) : SelectMythCollatorSettingsInterScreenCommunicator, diff --git a/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt b/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt index 067d035687..6a56aea1ce 100644 --- a/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt +++ b/common/src/main/java/io/novafoundation/nova/common/address/AccountIdParcel.kt @@ -6,7 +6,7 @@ import io.novasama.substrate_sdk_android.runtime.AccountId import kotlinx.android.parcel.Parcelize @Parcelize -class AccountIdParcel(private val value: AccountId): Parcelable { +class AccountIdParcel(private val value: AccountId) : Parcelable { companion object { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt index d273c1245f..0bec77e127 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/di/StakingFeatureComponent.kt @@ -249,7 +249,6 @@ interface StakingFeatureComponent : StakingFeatureApi { fun selectMythosSettingsFactory(): SelectMythCollatorSettingsComponent.Factory - @Component.Factory interface Factory { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt index ef327dcef8..f634df5eaf 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/common/model/MythosDelegatorState.kt @@ -60,7 +60,7 @@ fun MythosDelegatorState.stakeByCollator(): Map { } fun MythosDelegatorState.stakedCollatorsCount(): Int { - return when (this) { + return when (this) { is MythosDelegatorState.Locked.Delegating -> userStakeInfo.candidates.size MythosDelegatorState.NotStarted, is MythosDelegatorState.Locked.NotDelegating -> 0 } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt index 0d43c77447..527cbe3081 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/mythos/start/StartMythosStakingInteractor.kt @@ -12,9 +12,7 @@ import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchai import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.collatorStaking import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.lock import io.novafoundation.nova.feature_staking_impl.data.mythos.network.blockchain.calls.stake -import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.MythosCandidatesRepository import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.MythosStakingRepository -import io.novafoundation.nova.feature_staking_impl.data.mythos.repository.RealMythosCandidatesRepository import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.MythosSharedComputation import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosDelegatorState import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.stakeByCollator diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt index e522cf98c6..c7af7b68dd 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetFragment.kt @@ -22,7 +22,8 @@ import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorSorting import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator.selectCollatorToolbar -abstract class SingleSelectChooseTargetFragment> : BaseFragment(), +abstract class SingleSelectChooseTargetFragment> : + BaseFragment(), StakeTargetAdapter.ItemHandler { val adapter by lazy(LazyThreadSafetyMode.NONE) { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt index ff4d706c85..4bd932209f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/common/singleSelect/chooseTarget/SingleSelectChooseTargetViewModel.kt @@ -126,7 +126,6 @@ abstract class SingleSelectChooseTargetViewModel - } private inner class ShownStakeTargets(val targets: List, val usedConfig: C) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt index e4b6a9543e..9d2653d368 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mappers/Validator.kt @@ -8,9 +8,7 @@ import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.Fraction import io.novafoundation.nova.common.utils.Fraction.Companion.fractions import io.novafoundation.nova.common.utils.formatting.format -import io.novafoundation.nova.common.utils.formatting.formatAsPercentage import io.novafoundation.nova.common.utils.formatting.formatPercents -import io.novafoundation.nova.common.utils.fractionToPercentage import io.novafoundation.nova.feature_account_api.presenatation.account.icon.createAccountAddressModel import io.novafoundation.nova.feature_currency_api.presentation.formatters.formatAsCurrency import io.novafoundation.nova.feature_staking_api.domain.model.NominatedValidator diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt index 450ac243f2..13cd91f0f2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/SelectMythosCollatorFragment.kt @@ -4,7 +4,6 @@ import io.novafoundation.nova.common.di.FeatureUtils import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.model.MythosCollator -import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.model.Collator import io.novafoundation.nova.feature_staking_impl.presentation.common.singleSelect.chooseTarget.SingleSelectChooseTargetFragment class SelectMythosCollatorFragment : SingleSelectChooseTargetFragment() { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt index e3e23dcdf2..a442756034 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorComponent.kt @@ -5,7 +5,6 @@ import dagger.BindsInstance import dagger.Subcomponent import io.novafoundation.nova.common.di.scope.ScreenScope import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorFragment -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select.SelectCollatorFragment @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt index 7e0ccb8894..7b873a7763 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollator/di/SelectMythosCollatorModule.kt @@ -6,25 +6,16 @@ import androidx.lifecycle.ViewModelProvider import dagger.Module import dagger.Provides import dagger.multibindings.IntoMap -import io.novafoundation.nova.common.address.AddressIconGenerator -import io.novafoundation.nova.common.di.modules.Caching import io.novafoundation.nova.common.di.viewmodel.ViewModelKey import io.novafoundation.nova.common.di.viewmodel.ViewModelModule import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.feature_staking_impl.data.StakingSharedState import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendatorFactory -import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.CollatorsUseCase -import io.novafoundation.nova.feature_staking_impl.domain.parachainStaking.common.recommendations.CollatorRecommendatorFactory import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorViewModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenRequester -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.common.SelectCollatorInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.select.SelectCollatorViewModel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator import io.novafoundation.nova.feature_wallet_api.domain.TokenUseCase @Module(includes = [ViewModelModule::class]) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt index a64162b4ce..ddd47aced1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsFragment.kt @@ -14,9 +14,7 @@ import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.di.StakingFeatureComponent import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorSorting -import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollator.SelectMythosCollatorViewModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsApply import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsSort import kotlinx.android.synthetic.main.fragment_parachain_staking_select_collator_settings.selectCollatorSettingsToolbar diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt index 16a10e343e..fc4fe7aad4 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/SelectMythCollatorSettingsViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommendations.MythosCollatorRecommendationConfig import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toDomain import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.toParcel diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt index 43fac4dc76..c99fb7f309 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsComponent.kt @@ -6,8 +6,6 @@ import dagger.Subcomponent import io.novafoundation.nova.common.di.scope.ScreenScope import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsFragment import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsFragment -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel @Subcomponent( modules = [ diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt index 3258e88754..770976b9c1 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/selectCollatorSettings/di/SelectMythCollatorSettingsModule.kt @@ -9,14 +9,9 @@ import dagger.multibindings.IntoMap import io.novafoundation.nova.common.di.viewmodel.ViewModelKey import io.novafoundation.nova.common.di.viewmodel.ViewModelModule import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter -import io.novafoundation.nova.feature_staking_impl.presentation.ParachainStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsInterScreenResponder import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.SelectMythCollatorSettingsViewModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.selectCollatorSettings.model.MythCollatorRecommendationConfigParcel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.SelectCollatorSettingsViewModel -import io.novafoundation.nova.feature_staking_impl.presentation.parachainStaking.collator.settings.model.CollatorRecommendationConfigParcelModel @Module(includes = [ViewModelModule::class]) class SelectMythCollatorSettingsModule { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt index 8ecc2e641c..6824068ecc 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/SetupStartMythosStakingViewModel.kt @@ -37,7 +37,6 @@ import io.novafoundation.nova.feature_wallet_api.presentation.mixin.amountChoose import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import java.math.BigDecimal diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt index e4db51928a..b12b663b4f 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/mythos/start/setup/di/SetupStartMythosStakingModule.kt @@ -18,7 +18,6 @@ import io.novafoundation.nova.feature_staking_impl.domain.mythos.common.recommen import io.novafoundation.nova.feature_staking_impl.domain.mythos.start.StartMythosStakingInteractor import io.novafoundation.nova.feature_staking_impl.presentation.MythosStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenCommunicator -import io.novafoundation.nova.feature_staking_impl.presentation.mythos.SelectMythosInterScreenRequester import io.novafoundation.nova.feature_staking_impl.presentation.mythos.common.MythosCollatorFormatter import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.SetupStartMythosStakingViewModel import io.novafoundation.nova.feature_staking_impl.presentation.mythos.start.setup.rewards.MythosStakingRewardsComponentFactory diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt index 2f2db5382b..6f37a58c6b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/parachainStaking/common/mappers/Collator.kt @@ -19,9 +19,7 @@ import io.novafoundation.nova.feature_staking_impl.presentation.validators.parce import io.novafoundation.nova.feature_staking_impl.presentation.validators.parcel.StakerParcelModel import io.novafoundation.nova.feature_wallet_api.domain.model.Token import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel -import io.novafoundation.nova.runtime.ext.addressOf import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import io.novasama.substrate_sdk_android.extensions.fromHex typealias CollatorModel = StakeTargetModel